Exemplo n.º 1
0
    def get(self, traverser, name):
        """Retrieves a property from the variable"""

        value = self.value
        dirty = value is None
        if self.is_global:
            if "value" not in value:
                output = JSWrapper(traverser=traverser)
                output.value = {}

                def apply_value(name):
                    if name in self.value:
                        output.value[name] = self.value[name]

                apply_value("dangerous")
                apply_value("readonly")
                output.is_global = True
                return output

            def _evaluate_lambdas(node):
                if isinstance(node, types.LambdaType):
                    return _evaluate_lambdas(node(t=traverser))
                else:
                    return node

            value_val = value["value"]
            value_val = _evaluate_lambdas(value_val)

            if isinstance(value_val, dict):
                if name in value_val:
                    value_val = _evaluate_lambdas(value_val[name])
                    return traverser._build_global(name=name,
                                                   entity=value_val)
            else:
                value = value_val

        # Process any getters that are present for the current property.
        modifier = instanceproperties.get_operation("get", name)
        if modifier:
            modifier(traverser)

        if value is not None:
            output = (value.get(name) if
                      issubclass(type(value), JSObject) else
                      None)
        else:
            output = None

        if not isinstance(output, JSWrapper):
            output = JSWrapper(output,
                               traverser=traverser,
                               dirty=output is None or dirty)

        # If we can predetermine the setter for the wrapper, we can save a ton
        # of lookbehinds in the future. This greatly simplifies the
        # MemberExpression support.
        setter = instanceproperties.get_operation("set", name)
        if setter:
            output.setter = setter
        return output
Exemplo n.º 2
0
    def get(self, name, instantiate=False, traverser=None):
        "Returns the value associated with a property name"
        name = unicode(name)
        output = None

        if name in self.data:
            output = self.data[name]
            if callable(output):
                output = output()
        elif instantiate:
            output = JSWrapper(JSObject(), dirty=True, traverser=traverser)
            self.set(name, output, traverser=traverser)

        if traverser:
            modifier = instanceproperties.get_operation("get", name)
            if modifier:
                modifier(traverser)

        dirty = False
        if output is None:
            dirty = True
            output = JSObject()

        if dirty or not isinstance(output, JSWrapper):
            output = JSWrapper(output, dirty=dirty, traverser=traverser)
        return output
Exemplo n.º 3
0
    def set(self, name, value, traverser=None, ignore_setters=False):
        traverser = self.traverser or traverser
        if traverser and not ignore_setters:
            modifier = instanceproperties.get_operation("set", name)
            if modifier:
                modified_value = modifier(value, traverser)
                if modified_value is not None:
                    value = modified_value

        if traverser:
            if (self.has_var(name, traverser) and
                self.get(traverser, name).const):

                traverser.err.warning(
                    err_id=("js", "JSWrapper_set_value", "const_overwrite"),
                    warning="Overwritten constant value",
                    description="A variable declared as constant has been "
                                "overwritten in some JS code.",
                    filename=traverser.filename,
                    line=traverser.line,
                    column=traverser.position,
                    context=traverser.context)
                return

        self.data[unicode(name)] = value
Exemplo n.º 4
0
    def get(self, name, instantiate=False, traverser=None):
        "Returns the value associated with a property name"
        name = unicode(name)
        output = None

        if name == "wrappedJSObject":
            if traverser:
                traverser._debug("Requested unwrapped JS object...")
            clone = JSObject(unwrapped=True)
            clone.data = self.data
            return JSWrapper(clone, traverser=traverser)

        if name in self.data:
            output = self.data[name]
            if callable(output):
                output = output()
        elif instantiate:
            output = JSWrapper(JSObject(), dirty=True, traverser=traverser)
            self.set(name, output, traverser=traverser)

        if traverser:
            modifier = instanceproperties.get_operation("get", name)
            if modifier:
                modifier(traverser)

        if output is None:
            return JSWrapper(JSObject(), dirty=True, traverser=traverser)
        return output
Exemplo n.º 5
0
    def set(self, name, value, traverser=None):
        if traverser:
            modifier = instanceproperties.get_operation('set', name)
            if modifier:
                modified_value = modifier(value, traverser)
                if modified_value is not None:
                    value = modified_value

            if self.is_unwrapped:
                traverser.warning(
                    err_id=('testcases_javascript_jstypes', 'JSObject_set',
                            'unwrapped_js_object'),
                    warning="Assignment of unwrapped JS Object's properties.",
                    description='Improper use of unwrapped JS objects can '
                                'result in serious security vulnerabilities. '
                                'Please reconsider your use of unwrapped '
                                'JS objects.',
                    signing_help='Please avoid assigning to properties of '
                                 'unwrapped objects from unprivileged scopes, '
                                 'unless you are using an export API '
                                 '(http://mzl.la/1fvvgm9) to expose API '
                                 'functions to content scopes. '
                                 'In this case, however, please note that '
                                 'your add-on will be required to undergo '
                                 'manual code review for at least one '
                                 'submission.',
                    signing_severity='high')

        self.data[name] = value
Exemplo n.º 6
0
    def set(self, name, value, traverser=None):
        "Sets the value of a property"

        if traverser:
            modifier = instanceproperties.get_operation("set", name)
            if modifier:
                modified_value = modifier(value, traverser)
        self.data[name] = value
Exemplo n.º 7
0
    def set(self, name, value, traverser=None):
        if traverser:
            modifier = instanceproperties.get_operation("set", name)
            if modifier:
                modified_value = modifier(value, traverser)
                if modified_value is not None:
                    value = modified_value

        self.data[name] = value
Exemplo n.º 8
0
    def set(self, name, value, traverser=None):
        if traverser:
            modifier = instanceproperties.get_operation("set", name)
            if modifier:
                modified_value = modifier(value, traverser)
                if modified_value is not None:
                    value = modified_value

            if self.is_unwrapped:
                traverser.warning(
                    err_id=("testcases_javascript_jstypes", "JSObject_set",
                            "unwrapped_js_object"),
                    warning="Assignment of unwrapped JS Object's properties.",
                    description="Improper use of unwrapped JS objects can "
                                "result in serious security vulnerabilities. "
                                "Please reconsider your use of unwrapped "
                                "JS objects.",
                    signing_severity="high")

        self.data[name] = value
Exemplo n.º 9
0
    def get(self, traverser, name, instantiate=False):
        "Returns the value associated with a property name"
        name = unicode(name)
        output = None

        if name in self.data:
            output = self.data[name]
            if callable(output):
                output = output()
        elif instantiate or name in ('constructor', 'prototype'):
            output = fake(traverser)
            self.set(name, output, traverser=traverser)

        if traverser:
            modifier = instanceproperties.get_operation("get", name)
            if modifier:
                modifier(traverser)

        if output is None:
            return fake(traverser)

        return output
Exemplo n.º 10
0
def _expr_assignment(traverser, node):
    "Evaluates an AssignmentExpression node."

    traverser._debug("ASSIGNMENT_EXPRESSION")
    traverser.debug_level += 1

    traverser._debug("ASSIGNMENT>>PARSING RIGHT")
    right = traverser._traverse_node(node["right"])
    right = JSWrapper(right, traverser=traverser)

    # Treat direct assignment different than augmented assignment.
    if node["operator"] == "=":

        global_overwrite = False
        readonly_value = True

        node_left = node["left"]
        traverser._debug("ASSIGNMENT:DIRECT(%s)" % node_left["type"])

        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["readonly"] if
                                  "readonly" in global_dict else
                                  True)

            traverser._set_variable(node_left["name"], right, glob=True)
        elif node_left["type"] == "MemberExpression":
            member_object = trace_member(traverser, node_left["object"])
            global_overwrite = (member_object.is_global and
                                not ("overwriteable" in member_object.value and
                                     member_object.value["overwriteable"]))
            member_property = _get_member_exp_property(traverser, node_left)
            traverser._debug("ASSIGNMENT:MEMBER_PROPERTY(%s)" % member_property)

            # Make sure to perform any setter operations.
            setter = instanceproperties.get_operation("set", member_property)
            if setter:
                right = setter(right, traverser) or right or None

            # Don't do the assignment if we're facing a global.
            if not global_overwrite:
                if member_object.value is None:
                    member_object.value = JSObject()

                if not member_object.is_global:
                    member_object.value.set(member_property, right)
                else:
                    # It's probably better to do nothing.
                    pass

            elif "value" in member_object.value:
                member_object_value = _expand_globals(traverser,
                                                      member_object).value
                if member_property in member_object_value["value"]:

                    # If it's a global and the actual member exists, test
                    # whether it can be safely overwritten.
                    member = member_object_value["value"][member_property]
                    readonly_value = (member["readonly"] if
                                      "readonly" in member else
                                      True)

        traverser._debug("ASSIGNMENT:DIRECT:GLOB_OVERWRITE %s" %
                             global_overwrite)

        if (global_overwrite and
            not traverser.is_jsm and
            readonly_value == True):

            traverser.err.warning(
                err_id=("testcases_javascript_actions",
                        "_expr_assignment",
                        "global_overwrite"),
                warning="Global variable overwrite",
                description="An attempt was made to overwrite a global "
                            "variable in some JavaScript code.",
                filename=traverser.filename,
                line=traverser.line,
                column=traverser.position,
                context=traverser.context)

        if isinstance(readonly_value, types.LambdaType):
            # The readonly attribute supports a lambda function that accepts
            readonly_value(t=traverser, r=right, rn=node["right"])

        return right

    lit_right = right.get_literal_value()

    traverser._debug("ASSIGNMENT>>PARSING LEFT")
    left = traverser._traverse_node(node["left"])
    traverser._debug("ASSIGNMENT>>DONE PARSING LEFT")

    if isinstance(left, JSWrapper):
        lit_left = left.get_literal_value()

        # 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 isinstance(lit_left, types.StringTypes) or \
           isinstance(lit_right, types.StringTypes):
            lit_left = _get_as_str(lit_left)
            lit_right = _get_as_str(lit_right)

        gleft = _get_as_num(left)
        gright = _get_as_num(right)
        # All of the assignment operators
        operators = {"=": lambda: right,
                     "+=": lambda: lit_left + lit_right,
                     "-=": lambda: gleft - gright,
                     "*=": lambda: gleft * gright,
                     "/=": lambda: 0 if gright == 0 else (gleft / gright),
                     "%=": lambda: 0 if gright == 0 else (gleft % gright),
                     "<<=": lambda: int(gleft) << int(gright),
                     ">>=": lambda: int(gleft) >> int(gright),
                     ">>>=": lambda: float(abs(int(gleft)) >> gright),
                     "|=": lambda: int(gleft) | int(gright),
                     "^=": lambda: int(gleft) ^ int(gright),
                     "&=": lambda: int(gleft) & int(gright)}

        token = node["operator"]
        traverser._debug("ASSIGNMENT>>OPERATION:%s" % token)
        if token not in operators:
            traverser._debug("ASSIGNMENT>>OPERATOR NOT FOUND")
            traverser.debug_level -= 1
            return left
        elif token in ("<<=", ">>=", ">>>=") and gright < 0:
            left.set_value(0, traverser=traverser)
            return left
        elif (token in ("<<=", ">>=", ">>>=", "|=", "^=", "&=") and
              (abs(gleft) == float('inf') or abs(gright) == float('inf'))):
            # Don't bother handling infinity for integer-converted operations.
            from predefinedentities import GLOBAL_ENTITIES
            left.set_value(traverser._build_global("NaN",
                                                   GLOBAL_ENTITIES[u"NaN"]),
                           traverser=traverser)
            return left

        traverser._debug("ASSIGNMENT::L-value global? (%s)" %
                         ("Y" if left.is_global else "N"))
        new_value = operators[token]()
        traverser._debug("ASSIGNMENT::New value >> %s" % new_value)
        left.set_value(new_value, traverser=traverser)
        traverser.debug_level -= 1
        return left

    # Though it would otherwise be a syntax error, we say that 4=5 should
    # evaluate out to 5.
    traverser.debug_level -= 1
    return right
Exemplo n.º 11
0
    def get(self, traverser, name, instantiate=False):
        """Retrieve a property from the variable."""

        value = self.value
        dirty = value is None
        context = self.context
        if self.is_global:
            if 'value' not in value:
                output = JSWrapper(JSObject(), traverser=traverser)
                output.value = {}

                def apply_value(name):
                    if name in self.value:
                        output.value[name] = self.value[name]

                map(apply_value, ('dangerous', 'readonly', 'context', 'name'))
                output.is_global = True
                output.context = self.context
                return output

            def _evaluate_lambdas(node):
                if callable(node):
                    return _evaluate_lambdas(node(t=traverser))
                else:
                    return node

            value_val = value['value']
            value_val = _evaluate_lambdas(value_val)

            if isinstance(value_val, dict):
                if name in value_val:
                    value_val = _evaluate_lambdas(value_val[name])
                    output = traverser._build_global(name=name,
                                                     entity=value_val)
                    if 'context' not in value_val:
                        output.context = self.context
                    return output
            else:
                value = value_val

        # Process any getters that are present for the current property.
        modifier = instanceproperties.get_operation('get', name)
        if modifier:
            modifier(traverser)

        if value is not None and issubclass(type(value), JSObject):
            output = value.get(name, instantiate=instantiate,
                               traverser=traverser)
        else:
            output = None

        if not isinstance(output, JSWrapper):
            output = JSWrapper(
                output, traverser=traverser, dirty=output is None or dirty)

        output.context = context

        # If we can predetermine the setter for the wrapper, we can save a ton
        # of lookbehinds in the future. This greatly simplifies the
        # MemberExpression support.
        setter = instanceproperties.get_operation('set', name)
        if setter:
            output.setter = setter
        return output