def string_global(wrapper, arguments, traverser):
    if (not arguments or
        not arguments[0].get_literal_value(traverser)):
        return JSObject(traverser=traverser)
    return JSLiteral(
        utils.get_as_str(arguments[0].get_literal_value(traverser)),
        traverser=traverser)
예제 #2
0
def _get_member_exp_property(traverser, node):
    """Return the string value of a member expression's property."""

    if node["property"]["type"] == "Identifier" and not node["computed"]:
        return unicode(node["property"]["name"])
    else:
        eval_exp = traverser.traverse_node(node["property"])
        return utils.get_as_str(eval_exp.get_literal_value(traverser))
def _get_member_exp_property(traverser, node):
    """Return the string value of a member expression's property."""

    if node["property"]["type"] == "Identifier" and not node["computed"]:
        return unicode(node["property"]["name"])
    else:
        eval_exp = traverser.traverse_node(node["property"])
        return utils.get_as_str(eval_exp.get_literal_value(traverser))
예제 #4
0
def createElement(args, traverser, wrapper):
    """Handles createElement calls"""

    if not args:
        return

    first_as_str = utils.get_as_str(args[0].get_literal_value())
    if first_as_str.lower() == u"script":
        _create_script_tag(traverser)
    elif not isinstance(args[0], jstypes.JSLiteral):
        _create_variable_element(traverser)
예제 #5
0
def createElementNS(args, traverser, wrapper):
    """Handles createElementNS calls"""

    if not args or len(args) < 2:
        return

    second_as_str = utils.get_as_str(args[1].get_literal_value())
    if "script" in second_as_str.lower():
        _create_script_tag(traverser)
    elif not isinstance(args[1], jstypes.JSLiteral):
        _create_variable_element(traverser)
def createElement(args, traverser, wrapper):
    """Handles createElement calls"""

    if not args:
        return

    first_as_str = utils.get_as_str(args[0].get_literal_value(traverser))
    if first_as_str.lower() == u"script":
        _create_script_tag(traverser)
    elif not isinstance(args[0], jstypes.JSLiteral):
        _create_variable_element(traverser)
def createElementNS(args, traverser, wrapper):
    """Handles createElementNS calls"""

    if not args or len(args) < 2:
        return

    second_as_str = utils.get_as_str(args[1].get_literal_value(traverser))
    if "script" in second_as_str.lower():
        _create_script_tag(traverser)
    elif not isinstance(args[1], jstypes.JSLiteral):
        _create_variable_element(traverser)
예제 #8
0
def setAttribute(args, traverser, wrapper):
    """This ensures that setAttribute calls don't set on* attributes"""

    if not args:
        return

    first_as_str = utils.get_as_str(args[0].get_literal_value())
    if first_as_str.lower().startswith("on"):
        warn(traverser.err,
             filename=traverser.filename,
             line=traverser.line,
             column=traverser.position,
             context=traverser.context,
             violation_type="setAttribute-on")
def setAttribute(args, traverser, wrapper):
    """This ensures that setAttribute calls don't set on* attributes"""

    if not args:
        return

    first_as_str = utils.get_as_str(args[0].get_literal_value(traverser))
    if first_as_str.lower().startswith("on"):
        warn(traverser.err,
             filename=traverser.filename,
             line=traverser.line,
             column=traverser.position,
             context=traverser.context,
             violation_type="setAttribute-on")
 def _process_literal(type_, literal):
     if type_ == "string":
         return utils.get_as_str(literal)
     elif type_ == "num":
         return utils.get_as_num(literal)
     return literal
def string_global(wrapper, arguments, traverser):
    if (not arguments or not arguments[0].get_literal_value(traverser)):
        return JSObject(traverser=traverser)
    return JSLiteral(utils.get_as_str(
        arguments[0].get_literal_value(traverser)),
                     traverser=traverser)
예제 #12
0
 def _process_literal(type_, literal):
     if type_ == "string":
         return utils.get_as_str(literal)
     elif type_ == "num":
         return utils.get_as_num(literal)
     return literal
예제 #13
0
def AssignmentExpression(traverser, node):
    traverser._debug("ASSIGNMENT_EXPRESSION")
    traverser.debug_level += 1

    traverser._debug("ASSIGNMENT>>PARSING RIGHT")
    right = traverser.traverse_node(node["right"])

    traverser._debug("ASSIGNMENT>>PARSING LEFT")
    orig_left = left = traverser.traverse_node(node["left"])

    operator = node["operator"]

    def set_lvalue(value):
        node_left = node["left"]
        traverser._debug("ASSIGNING:DIRECT(%s)" % node_left["type"])

        global_overwrite = False
        readonly_value = True
        if node_left["type"] == "Identifier":
            # Identifiers just need the ID name and a value to push.
            # Raise a global overwrite issue if the identifier is global.
            global_overwrite = traverser._is_global(node_left["name"])

            # Get the readonly attribute and store its value if is_global
            if global_overwrite:
                from predefinedentities import GLOBAL_ENTITIES
                global_dict = GLOBAL_ENTITIES[node_left["name"]]
                readonly_value = global_dict.get("readonly", False)

            traverser._declare_variable(node_left["name"], value, type_="glob")

        elif node_left["type"] == "MemberExpression":
            member_object = MemberExpression(traverser,
                                             node_left["object"],
                                             instantiate=True)
            member_property = _get_member_exp_property(traverser, node_left)
            traverser._debug("ASSIGNMENT:MEMBER_PROPERTY(%s)" %
                             member_property)

            if member_object is None:
                member_object = JSObject()

            member_object.set(member_property, value, traverser)

    # Treat direct assignment different than augmented assignment.
    if operator == "=":
        set_lvalue(right)
        return right

    elif operator not in ASSIGNMENT_OPERATORS:
        # We don't support that operator. (yet?)
        traverser._debug("ASSIGNMENT>>OPERATOR NOT FOUND", 1)
        return left

    if left.const:
        traverser.err.warning(
            err_id=("js", "AssignmentExpression", "aug_const_overwrite"),
            warning="Overwritten constant value",
            description="A variable declared as constant has been "
            "overwritten in some JS code by an augmented "
            "assignment.",
            filename=traverser.filename,
            line=traverser.line,
            column=traverser.position,
            context=traverser.context)
        return JSObject(traverser=traverser)

    traverser._debug("ASSIGNMENT>>DONE PARSING LEFT")
    traverser.debug_level -= 1

    # If we're modifying a non-numeric type with a numeric operator, return
    # NaN.
    if (operator in NUMERIC_OPERATORS and not isinstance(
            left.get_literal_value(traverser) or 0, NUMERIC_TYPES)):
        set_lvalue(utils.get_NaN(traverser))
        return left

    gleft, gright = utils.get_as_num(left), utils.get_as_num(right)

    traverser._debug("ASSIGNMENT>>OPERATION:%s" % operator)
    if operator in ("<<=", ">>=", ">>>=") and gright < 0:
        # The user is doing weird bitshifting that will return 0 in JS but
        # not in Python.
        set_lvalue(JSLiteral(0, traverser=traverser))
        return left
    elif (operator in ("<<=", ">>=", ">>>=", "|=", "^=", "&=")
          and (abs(gleft) == float('inf') or abs(gright) == float('inf'))):
        # Don't bother handling infinity for integer-converted operations.
        set_lvalue(utils.get_NaN(traverser))
        return left

    if operator == '+=':
        lit_left = left.get_literal_value(traverser)
        lit_right = right.get_literal_value(traverser)
        # Don't perform an operation on None. Python freaks out.
        if lit_left is None:
            lit_left = 0
        if lit_right is None:
            lit_right = 0

        # If either side of the assignment operator is a string, both sides
        # need to be cast to strings first.
        if (isinstance(lit_left, types.StringTypes)
                or isinstance(lit_right, types.StringTypes)):
            left = utils.get_as_str(lit_left)
            right = utils.get_as_str(lit_right)
        else:
            left, right = lit_left, lit_right

    output = ASSIGNMENT_OPERATORS[operator](left, right, gleft, gright)

    # Cap the length of analyzed strings.
    if isinstance(output, types.StringTypes) and len(output) > MAX_STR_SIZE:
        output = output[:MAX_STR_SIZE]

    traverser._debug("ASSIGNMENT::New value >> %s" % output, 1)
    set_lvalue(JSLiteral(output, traverser=traverser))
    return orig_left
예제 #14
0
def BinaryExpression(traverser, node):
    traverser.debug_level += 1

    # Select the proper operator.
    operator = node["operator"]
    traverser._debug("BIN_OPERATOR>>%s" % operator)

    # Traverse the left half of the binary expression.
    traverser._debug("BIN_EXP>>l-value")
    traverser.debug_level += 1

    if (node["left"]["type"] == "BinaryExpression"
            and "__traversal" not in node["left"]):
        # Process the left branch of the binary expression directly. This keeps
        # the recursion cap in line and speeds up processing of large chains
        # of binary expressions.
        left = BinaryExpression(traverser, node["left"])
        node["left"]["__traversal"] = left
    else:
        left = traverser.traverse_node(node["left"])

    # Traverse the right half of the binary expression.
    traverser._debug("BIN_EXP>>r-value", -1)

    if (operator == "instanceof" and node["right"]["type"] == "Identifier"
            and node["right"]["name"] == "Function"):
        # We make an exception for instanceof's r-value if it's a dangerous
        # global, specifically Function.
        traverser.debug_level -= 1
        return JSLiteral(True, traverser=traverser)
    else:
        right = traverser.traverse_node(node["right"])

    traverser.debug_level -= 1

    # Binary expressions are only executed on literals.
    left = left.get_literal_value(traverser)
    right_wrap = right
    right = right.get_literal_value(traverser)

    # Coerce the literals to numbers for numeric operations.
    gleft = utils.get_as_num(left)
    gright = utils.get_as_num(right)

    if operator in (">>", "<<", ">>>"):
        if left is None or right is None or gright < 0:
            return JSLiteral(False, traverser=traverser)
        elif abs(gleft) == float('inf') or abs(gright) == float('inf'):
            return utils.get_NaN(traverser)

    output = None
    if operator in BINARY_OPERATORS:
        # Concatenation can be silly, so always turn undefineds into empty
        # strings and if there are strings, make everything strings.
        if operator == "+":
            if left is None:
                left = ""
            if right is None:
                right = ""
            if (isinstance(left, types.StringTypes)
                    or isinstance(right, types.StringTypes)):
                left = utils.get_as_str(left)
                right = utils.get_as_str(right)

        output = BINARY_OPERATORS[operator](left, right, gleft, gright)
    elif operator == "in":
        return JSLiteral(right_wrap.has_var(left, traverser=traverser),
                         traverser=traverser)
    #TODO: `delete` operator

    # Cap the length of analyzed strings.
    if isinstance(output, types.StringTypes) and len(output) > MAX_STR_SIZE:
        output = output[:MAX_STR_SIZE]

    return JSLiteral(output, traverser=traverser)
def AssignmentExpression(traverser, node):
    traverser._debug("ASSIGNMENT_EXPRESSION")
    traverser.debug_level += 1

    traverser._debug("ASSIGNMENT>>PARSING RIGHT")
    right = traverser.traverse_node(node["right"])

    traverser._debug("ASSIGNMENT>>PARSING LEFT")
    orig_left = left = traverser.traverse_node(node["left"])

    operator = node["operator"]

    def set_lvalue(value):
        node_left = node["left"]
        traverser._debug("ASSIGNING:DIRECT(%s)" % node_left["type"])

        global_overwrite = False
        readonly_value = True
        if node_left["type"] == "Identifier":
            # Identifiers just need the ID name and a value to push.
            # Raise a global overwrite issue if the identifier is global.
            global_overwrite = traverser._is_global(node_left["name"])

            # Get the readonly attribute and store its value if is_global
            if global_overwrite:
                from predefinedentities import GLOBAL_ENTITIES
                global_dict = GLOBAL_ENTITIES[node_left["name"]]
                readonly_value = global_dict.get("readonly", False)

            traverser._declare_variable(node_left["name"], value, type_="glob")

        elif node_left["type"] == "MemberExpression":
            member_object = MemberExpression(traverser, node_left["object"],
                                             instantiate=True)
            member_property = _get_member_exp_property(traverser, node_left)
            traverser._debug("ASSIGNMENT:MEMBER_PROPERTY(%s)" % member_property)

            if member_object is None:
                member_object = JSObject()

            member_object.set(member_property, value, traverser)

    # Treat direct assignment different than augmented assignment.
    if operator == "=":
        set_lvalue(right)
        return right

    elif operator not in ASSIGNMENT_OPERATORS:
        # We don't support that operator. (yet?)
        traverser._debug("ASSIGNMENT>>OPERATOR NOT FOUND", 1)
        return left

    if left.const:
        traverser.err.warning(
            err_id=("js", "AssignmentExpression", "aug_const_overwrite"),
            warning="Overwritten constant value",
            description="A variable declared as constant has been "
                        "overwritten in some JS code by an augmented "
                        "assignment.",
            filename=traverser.filename,
            line=traverser.line,
            column=traverser.position,
            context=traverser.context)
        return JSObject(traverser=traverser)

    traverser._debug("ASSIGNMENT>>DONE PARSING LEFT")
    traverser.debug_level -= 1

    # If we're modifying a non-numeric type with a numeric operator, return
    # NaN.
    if (operator in NUMERIC_OPERATORS and
        not isinstance(left.get_literal_value(traverser) or 0, NUMERIC_TYPES)):
        set_lvalue(utils.get_NaN(traverser))
        return left

    gleft, gright = utils.get_as_num(left), utils.get_as_num(right)

    traverser._debug("ASSIGNMENT>>OPERATION:%s" % operator)
    if operator in ("<<=", ">>=", ">>>=") and gright < 0:
        # The user is doing weird bitshifting that will return 0 in JS but
        # not in Python.
        set_lvalue(JSLiteral(0, traverser=traverser))
        return left
    elif (operator in ("<<=", ">>=", ">>>=", "|=", "^=", "&=") and
          (abs(gleft) == float('inf') or abs(gright) == float('inf'))):
        # Don't bother handling infinity for integer-converted operations.
        set_lvalue(utils.get_NaN(traverser))
        return left

    if operator == '+=':
        lit_left = left.get_literal_value(traverser)
        lit_right = right.get_literal_value(traverser)
        # Don't perform an operation on None. Python freaks out.
        if lit_left is None:
            lit_left = 0
        if lit_right is None:
            lit_right = 0

        # If either side of the assignment operator is a string, both sides
        # need to be cast to strings first.
        if (isinstance(lit_left, types.StringTypes) or
            isinstance(lit_right, types.StringTypes)):
            left = utils.get_as_str(lit_left)
            right = utils.get_as_str(lit_right)
        else:
            left, right = lit_left, lit_right

    output = ASSIGNMENT_OPERATORS[operator](left, right, gleft, gright)

    # Cap the length of analyzed strings.
    if isinstance(output, types.StringTypes) and len(output) > MAX_STR_SIZE:
        output = output[:MAX_STR_SIZE]

    traverser._debug("ASSIGNMENT::New value >> %s" % output, 1)
    set_lvalue(JSLiteral(output, traverser=traverser))
    return orig_left
def BinaryExpression(traverser, node):
    traverser.debug_level += 1

    # Select the proper operator.
    operator = node["operator"]
    traverser._debug("BIN_OPERATOR>>%s" % operator)

    # Traverse the left half of the binary expression.
    traverser._debug("BIN_EXP>>l-value")
    traverser.debug_level += 1

    if (node["left"]["type"] == "BinaryExpression" and
        "__traversal" not in node["left"]):
        # Process the left branch of the binary expression directly. This keeps
        # the recursion cap in line and speeds up processing of large chains
        # of binary expressions.
        left = BinaryExpression(traverser, node["left"])
        node["left"]["__traversal"] = left
    else:
        left = traverser.traverse_node(node["left"])

    # Traverse the right half of the binary expression.
    traverser._debug("BIN_EXP>>r-value", -1)

    if (operator == "instanceof" and
            node["right"]["type"] == "Identifier" and
            node["right"]["name"] == "Function"):
        # We make an exception for instanceof's r-value if it's a dangerous
        # global, specifically Function.
        traverser.debug_level -= 1
        return JSLiteral(True, traverser=traverser)
    else:
        right = traverser.traverse_node(node["right"])

    traverser.debug_level -= 1

    # Binary expressions are only executed on literals.
    left = left.get_literal_value(traverser)
    right_wrap = right
    right = right.get_literal_value(traverser)

    # Coerce the literals to numbers for numeric operations.
    gleft = utils.get_as_num(left)
    gright = utils.get_as_num(right)

    if operator in (">>", "<<", ">>>"):
        if left is None or right is None or gright < 0:
            return JSLiteral(False, traverser=traverser)
        elif abs(gleft) == float('inf') or abs(gright) == float('inf'):
            return utils.get_NaN(traverser)

    output = None
    if operator in BINARY_OPERATORS:
        # Concatenation can be silly, so always turn undefineds into empty
        # strings and if there are strings, make everything strings.
        if operator == "+":
            if left is None:
                left = ""
            if right is None:
                right = ""
            if (isinstance(left, types.StringTypes) or
                    isinstance(right, types.StringTypes)):
                left = utils.get_as_str(left)
                right = utils.get_as_str(right)

        output = BINARY_OPERATORS[operator](left, right, gleft, gright)
    elif operator == "in":
        return JSLiteral(right_wrap.has_var(left, traverser=traverser),
                         traverser=traverser)
    #TODO: `delete` operator

    # Cap the length of analyzed strings.
    if isinstance(output, types.StringTypes) and len(output) > MAX_STR_SIZE:
        output = output[:MAX_STR_SIZE]

    return JSLiteral(output, traverser=traverser)