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
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
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
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
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) if not isinstance(output, JSWrapper): output = JSWrapper(output, traverser=traverser) return output
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
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
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
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
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) if output is None: return JSWrapper(JSObject(), dirty=True, traverser=traverser) return output
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
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.err.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.", filename=traverser.filename, line=traverser.line, column=traverser.position, context=traverser.context) self.data[name] = value
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
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
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