Skip to content
This repository has been archived by the owner on Mar 31, 2021. It is now read-only.

Commit

Permalink
New feature profile stuff; refactoring (bug 917738)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattbasta committed Sep 30, 2013
1 parent 4de749c commit 6e03b59
Show file tree
Hide file tree
Showing 11 changed files with 271 additions and 357 deletions.
50 changes: 26 additions & 24 deletions appvalidator/testcases/javascript/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def _get_member_exp_property(traverser, node):
if node["property"]["type"] == "Identifier" and not node["computed"]:
return unicode(node["property"]["name"])
else:
eval_exp = traverser._traverse_node(node["property"])
eval_exp = traverser.traverse_node(node["property"])
return _get_as_str(eval_exp.get_literal_value())


Expand Down Expand Up @@ -98,7 +98,7 @@ def trace_member(traverser, node, instantiate=False):
else:
traverser._debug("MEMBER_EXP>>ROOT:EXPRESSION")
# It's an expression, so just try your damndest.
return traverser._traverse_node(node)
return traverser.traverse_node(node)


def _function(traverser, node):
Expand Down Expand Up @@ -138,7 +138,7 @@ def wrap(traverser, node):
# function.
local_context.set(param, var)

traverser._traverse_node(node["body"])
traverser.traverse_node(node["body"])

# Since we need to manually manage the "this" stack, pop off that
# context.
Expand All @@ -154,7 +154,7 @@ def wrap(traverser, node):
# Put the function off for traversal at the end of the current block scope.
traverser.function_collection[-1].append(lambda: wrap(traverser, node))

return JSWrapper(traverser=traverser, callable=True, dirty=True)
return JSWrapper(traverser=traverser, callable_=True, dirty=True)


def _define_function(traverser, node):
Expand All @@ -168,7 +168,7 @@ def _define_function(traverser, node):


def _define_with(traverser, node):
object_ = traverser._traverse_node(node["object"])
object_ = traverser.traverse_node(node["object"])
if (isinstance(object_, JSWrapper) and
isinstance(object_.value, JSObject)):
traverser.contexts[-1] = object_.value
Expand Down Expand Up @@ -207,21 +207,21 @@ def _define_var(traverser, node):
for value in declaration["init"]["elements"]:
if vars[0]:
traverser._declare_variable(
vars[0], JSWrapper(traverser._traverse_node(value),
vars[0], JSWrapper(traverser.traverse_node(value),
traverser=traverser))
vars = vars[1:] # Pop off the first value

# It's being assigned by a JSArray (presumably)
elif declaration["init"]["type"] == "ArrayExpression":
assigner = traverser._traverse_node(declaration["init"])
assigner = traverser.traverse_node(declaration["init"])
for value in assigner.value.elements:
if vars[0]:
traverser._declare_variable(vars[0], value)
vars = vars[1:]

elif declaration["id"]["type"] == "ObjectPattern":

init = traverser._traverse_node(declaration["init"])
init = traverser.traverse_node(declaration["init"])

def _proc_objpattern(init_obj, properties):
for prop in properties:
Expand Down Expand Up @@ -249,7 +249,7 @@ def _proc_objpattern(init_obj, properties):
var_name = declaration["id"]["name"]
traverser._debug("NAME>>%s" % var_name)

var = traverser._traverse_node(declaration["init"])
var = traverser.traverse_node(declaration["init"])
traverser._debug("VALUE>>%s" % (var.output()
if var is not None
else "None"))
Expand All @@ -273,7 +273,7 @@ def _define_obj(traverser, node):
var_name = ""
key = prop["key"]
var_name = key["value" if key["type"] == "Literal" else "name"]
var_value = traverser._traverse_node(prop["value"])
var_value = traverser.traverse_node(prop["value"])
var.set(var_name, var_value, traverser)

# TODO: Observe "kind"
Expand All @@ -287,7 +287,7 @@ def _define_obj(traverser, node):
def _define_array(traverser, node):
"""Instantiate an array object from the parse tree."""
arr = JSArray()
arr.elements = map(traverser._traverse_node, node["elements"])
arr.elements = map(traverser.traverse_node, node["elements"])
return arr


Expand All @@ -305,14 +305,14 @@ def _define_literal(traverser, node):

def _call_expression(traverser, node):
args = node["arguments"]
map(traverser._traverse_node, args)
map(traverser.traverse_node, args)

member = traverser._traverse_node(node["callee"])
member = traverser.traverse_node(node["callee"])

if member.is_global and callable(member.value.get("dangerous")):

dangerous = member.value["dangerous"]
t = traverser._traverse_node
t = traverser.traverse_node
result = dangerous(a=args, t=t, e=traverser.err)
if result and "name" in member.value:
## Generate a string representation of the params
Expand Down Expand Up @@ -353,9 +353,9 @@ def _call_expression(traverser, node):
def _expression(traverser, node):
"""
This is a helper method that allows node definitions to point at
`_traverse_node` without needing a reference to a traverser.
`traverse_node` without needing a reference to a traverser.
"""
return traverser._traverse_node(node["expression"])
return traverser.traverse_node(node["expression"])


def _get_this(traverser, node):
Expand All @@ -375,18 +375,20 @@ def _new(traverser, node):
args = node["arguments"]
if isinstance(args, list):
for arg in args:
traverser._traverse_node(arg)
traverser.traverse_node(arg)
else:
traverser._traverse_node(args)
traverser.traverse_node(args)

elem = traverser._traverse_node(node["callee"])
elem = traverser.traverse_node(node["callee"])
if not isinstance(elem, JSWrapper):
elem = JSWrapper(elem, traverser=traverser)
if elem.is_global:
traverser._debug("Making overwritable")
elem.value = deepcopy(elem.value)
elem.value["overwritable"] = True
elem.value["readonly"] = False
if "new" in elem.value:
elem = elem.value["new"](traverser, node, elem)
return elem


Expand All @@ -407,7 +409,7 @@ def _expr_assignment(traverser, node):
traverser.debug_level += 1

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

# Treat direct assignment different than augmented assignment.
Expand Down Expand Up @@ -476,7 +478,7 @@ def _expr_assignment(traverser, node):
lit_right = right.get_literal_value()

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

Expand Down Expand Up @@ -581,7 +583,7 @@ def _expr_binary(traverser, node):
left = _expr_binary(traverser, node["left"])
node["left"]["__traversal"] = left
else:
left = traverser._traverse_node(node["left"])
left = traverser.traverse_node(node["left"])

# Traverse the right half of the binary expression.
traverser._debug("BIN_EXP>>r-value", -1)
Expand All @@ -594,7 +596,7 @@ def _expr_binary(traverser, node):
traverser.debug_level -= 1
return JSWrapper(True, traverser=traverser)
else:
right = traverser._traverse_node(node["right"])
right = traverser.traverse_node(node["right"])
traverser._debug("Is dirty? %r" % right.dirty, 1)

traverser.debug_level -= 1
Expand Down Expand Up @@ -675,7 +677,7 @@ def _expr_binary(traverser, node):
def _expr_unary(traverser, node):
"""Evaluate a UnaryExpression node."""

expr = traverser._traverse_node(node["argument"])
expr = traverser.traverse_node(node["argument"])
expr_lit = expr.get_literal_value()
expr_num = _get_as_num(expr_lit)

Expand Down
14 changes: 7 additions & 7 deletions appvalidator/testcases/javascript/call_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,22 @@
def string_global(wrapper, arguments, traverser):
if not arguments:
return JSWrapper("", traverser=traverser)
arg = traverser._traverse_node(arguments[0])
arg = traverser.traverse_node(arguments[0])
value = actions._get_as_str(arg.get_literal_value())
return JSWrapper(value, traverser=traverser)


def array_global(wrapper, arguments, traverser):
output = JSArray()
if arguments:
output.elements = map(traverser._traverse_node, arguments)
output.elements = map(traverser.traverse_node, arguments)
return JSWrapper(output, traverser=traverser)


def number_global(wrapper, arguments, traverser):
if not arguments:
return JSWrapper(0, traverser=traverser)
arg = traverser._traverse_node(arguments[0])
arg = traverser.traverse_node(arguments[0])
try:
return float(arg.get_literal_value())
except (ValueError, TypeError):
Expand All @@ -42,7 +42,7 @@ def number_global(wrapper, arguments, traverser):
def boolean_global(wrapper, arguments, traverser):
if not arguments:
return JSWrapper(False, traverser=traverser)
arg = traverser._traverse_node(arguments[0])
arg = traverser.traverse_node(arguments[0])
return JSWrapper(bool(arg.get_literal_value()), traverser=traverser)


Expand All @@ -67,7 +67,7 @@ def _process_literal(type_, literal):
return literal

def wrap(wrapper, arguments, traverser):
passed_args = map(traverser._traverse_node, arguments)
passed_args = map(traverser.traverse_node, arguments)

params = []
if not nargs:
Expand Down Expand Up @@ -103,7 +103,7 @@ def wrap(wrapper, arguments, traverser):

def math_log(wrapper, arguments, traverser):
"""Return a better value than the standard python log function."""
args = map(traverser._traverse_node, arguments)
args = map(traverser.traverse_node, arguments)
if not args:
return JSWrapper(0, traverser=traverser)

Expand All @@ -120,7 +120,7 @@ def math_log(wrapper, arguments, traverser):

def math_round(wrapper, arguments, traverser):
"""Return a better value than the standard python round function."""
args = map(traverser._traverse_node, arguments)
args = map(traverser.traverse_node, arguments)
if not args:
return JSWrapper(0, traverser=traverser)

Expand Down
94 changes: 57 additions & 37 deletions appvalidator/testcases/javascript/entity_values.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@


ENTITIES = {}


def register_entity(name):
"""Allow an entity's modifier to be registered for use."""
def wrap(function):
Expand Down Expand Up @@ -34,41 +32,11 @@ def call_wrap(*args, **kwargs):
violation_type="script")
return False

return {"dangerous": call_wrap,
"return": call_wrap,
"value": call_wrap, }


@register_entity("createElement")
def csp_warning_createElement(traverser):
def wrap(a, t, e):
if not a or "script" in _get_as_str(t(a[0])).lower():
from appvalidator.csp import warn
warn(err=traverser.err,
filename=traverser.filename,
line=traverser.line,
column=traverser.position,
context=traverser.context,
violation_type="createElement")
return False

return {"return": wrap}


@register_entity("createElementNS")
def csp_warning_createElementNS(traverser):
def wrap(a, t, e):
if not a or "script" in _get_as_str(t(a[1])).lower():
from appvalidator.csp import warn
warn(err=traverser.err,
filename=traverser.filename,
line=traverser.line,
column=traverser.position,
context=traverser.context,
violation_type="createElementNS")
return False

return {"return": wrap}
return {
"dangerous": call_wrap,
"return": call_wrap,
"value": call_wrap,
}


@register_entity("setTimeout")
Expand All @@ -86,3 +54,55 @@ def wrap(a, t, e):
return False

return {"dangerous": wrap}


GUM_FEATURES = {
"video": "CAMERA",
"picture": "CAMERA",
"audio": "MIC",
}

@register_entity("getUserMedia")
def getUserMedia(traverser):
def method(wrapper, arguments, traverser):
if not arguments:
return False
options = traverser.traverse_node(arguments[0])
for feature in GUM_FEATURES:
if (options.has_property(feature) and
options.get(traverser, feature).get_literal_value() == True):
traverser.log_feature(GUM_FEATURES[feature])

if (options.has_property("video") and
options.get(traverser, "video").has_property("mandatory") and
options.get(traverser, "video").get(traverser, "mandatory") and
options.get(traverser, "video").get(traverser, "mandatory"
).get(traverser, "chromeMediaSource"
).get_literal_value() == "screen"):
traverser.log_feature("SCREEN_CAPTURE")

return {"return": method}


@register_entity("XMLHttpRequest")
def XMLHttpRequest(traverser):
def dangerous(a, t, e):
print a, e
if a and len(a) >= 3 and not t(a[2]).get_literal_value():
return ("Synchronous HTTP requests can cause serious UI "
"performance problems, especially to users with "
"slow network connections.")

def new(traverser, node, elem):
if not node["arguments"]: # Ignore XHR without args
return elem
arg = traverser.traverse_node(node["arguments"][0])
if (arg.has_property("mozSystem") and
arg.get(traverser, "mozSystem").get_literal_value()):
traverser.log_feature("SYSTEMXHR")
return elem

return {
"value": {u"open": {"dangerous": dangerous}},
"new": new,
}
Loading

0 comments on commit 6e03b59

Please sign in to comment.