コード例 #1
0
ファイル: jstypes.py プロジェクト: cvan/app-validator
    def has_var(self, name, traverser=None):
        index = None
        if isinstance(name, types.StringTypes) and name.isdigit():
            index = utils.get_as_num(name, traverser)
        elif isinstance(name, int):
            index = name

        if index is not None and len(self.elements) > index >= 0:
            return True

        return super(JSArray, self).has_var(name, traverser=traverser)
コード例 #2
0
ファイル: jstypes.py プロジェクト: andymckay/app-validator
    def has_var(self, name, traverser=None):
        index = None
        if isinstance(name, types.StringTypes) and name.isdigit():
            index = utils.get_as_num(name)
        elif isinstance(name, int):
            index = name

        if index is not None and len(self.elements) > index >= 0:
            return True

        return super(JSArray, self).has_var(name, traverser=traverser)
def math_log(wrapper, arguments, traverser):
    """Return a better value than the standard python log function."""
    if not arguments:
        return JSLiteral(0, traverser=traverser)

    arg = utils.get_as_num(arguments[0].get_literal_value(traverser))
    if arg == 0:
        return JSLiteral(float('-inf'), traverser=traverser)

    if arg < 0:
        return JSLiteral(None, traverser=traverser)

    return JSLiteral(math.log(arg), traverser=traverser)
コード例 #4
0
def math_log(wrapper, arguments, traverser):
    """Return a better value than the standard python log function."""
    if not arguments:
        return JSLiteral(0, traverser=traverser)

    arg = utils.get_as_num(arguments[0].get_literal_value())
    if arg == 0:
        return JSLiteral(float('-inf'), traverser=traverser)

    if arg < 0:
        return JSLiteral(None, traverser=traverser)

    return JSLiteral(math.log(arg), traverser=traverser)
def math_round(wrapper, arguments, traverser):
    """Return a better value than the standard python round function."""
    if not arguments:
        return JSLiteral(0, traverser=traverser)

    arg = utils.get_as_num(arguments[0].get_literal_value(traverser))
    # Prevent nasty infinity tracebacks.
    if abs(arg) == float("inf"):
        return arguments[0]

    # Python rounds away from zero, JS rounds "up".
    if arg < 0 and int(arg) != arg:
        arg += 0.0000000000000001
    return JSLiteral(round(arg), traverser=traverser)
コード例 #6
0
def math_round(wrapper, arguments, traverser):
    """Return a better value than the standard python round function."""
    if not arguments:
        return JSLiteral(0, traverser=traverser)

    arg = utils.get_as_num(arguments[0].get_literal_value())
    # Prevent nasty infinity tracebacks.
    if abs(arg) == float("inf"):
        return arguments[0]

    # Python rounds away from zero, JS rounds "up".
    if arg < 0 and int(arg) != arg:
        arg += 0.0000000000000001
    return JSLiteral(round(arg), traverser=traverser)
 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
コード例 #8
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
コード例 #9
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
コード例 #10
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)
コード例 #11
0
    if wrapper.callable:
        return "function"
    elif isinstance(wrapper, JSGlobal):
        if "typeof" in wrapper.global_data:
            return wrapper.global_data["typeof"]
        if ("return" in wrapper.global_data
                and "value" not in wrapper.global_data):
            return "function"
        if wrapper.global_data.get("undefined", False):
            return "undefined"

    return wrapper.TYPEOF


UNARY_OPERATORS = {
    "-": lambda e, t: -1 * utils.get_as_num(e.get_literal_value(t)),
    "+": lambda e, t: utils.get_as_num(e.get_literal_value(t)),
    "!": lambda e, t: not e.get_literal_value(t),
    "~": lambda e, t: -1 * (utils.get_as_num(e.get_literal_value(t)) + 1),
}


def UnaryExpression(traverser, node):
    operator = node["operator"]
    arg = traverser.traverse_node(node["argument"])
    if (isinstance(arg, JSGlobal) and "literal" in arg.global_data
            and not (operator == "typeof" and "undefined" in arg.global_data)):
        arg = JSLiteral(utils.evaluate_lambdas(traverser,
                                               arg.global_data["literal"]),
                        traverser=traverser)
    if operator in UNARY_OPERATORS:
コード例 #12
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
コード例 #13
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)
コード例 #14
0
    if wrapper.callable:
        return "function"
    elif isinstance(wrapper, JSGlobal):
        if "typeof" in wrapper.global_data:
            return wrapper.global_data["typeof"]
        if ("return" in wrapper.global_data and
            "value" not in wrapper.global_data):
            return "function"
        if wrapper.global_data.get("undefined", False):
            return "undefined"

    return wrapper.TYPEOF


UNARY_OPERATORS = {
    "-": lambda e, t: -1 * utils.get_as_num(e.get_literal_value(t)),
    "+": lambda e, t: utils.get_as_num(e.get_literal_value(t)),
    "!": lambda e, t: not e.get_literal_value(t),
    "~": lambda e, t: -1 * (utils.get_as_num(e.get_literal_value(t)) + 1),
}

def UnaryExpression(traverser, node):
    operator = node["operator"]
    arg = traverser.traverse_node(node["argument"])
    if (isinstance(arg, JSGlobal) and
        "literal" in arg.global_data and
        not (operator == "typeof" and "undefined" in arg.global_data)):
        arg = JSLiteral(
            utils.evaluate_lambdas(traverser, arg.global_data["literal"]),
            traverser=traverser)
    if operator in UNARY_OPERATORS: