def visit_Compare(self, comp):
self.push_format_context()
left_res, left_expl = self.visit(comp.left)
if isinstance(comp.left, (_ast.Compare, _ast.BoolOp)):
left_expl = "({0})".format(left_expl)
res_variables = [self.variable() for i in range(len(comp.ops))]
load_names = [ast.Name(v, ast.Load()) for v in res_variables]
store_names = [ast.Name(v, ast.Store()) for v in res_variables]
it = zip(range(len(comp.ops)), comp.ops, comp.comparators)
expls = []
syms = []
results = [left_res]
for i, op, next_operand in it:
next_res, next_expl = self.visit(next_operand)
if isinstance(next_operand, (_ast.Compare, _ast.BoolOp)):
next_expl = "({0})".format(next_expl)
results.append(next_res)
sym = binop_map[op.__class__]
syms.append(ast.Str(sym))
expl = "%s %s %s" % (left_expl, sym, next_expl)
expls.append(ast.Str(expl))
res_expr = ast.Compare(left_res, [op], [next_res])
self.statements.append(ast.Assign([store_names[i]], res_expr))
left_res, left_expl = next_res, next_expl
# Use pytest.assertion.util._reprcompare if that's available.
expl_call = self.helper("call_reprcompare",
ast.Tuple(syms, ast.Load()),
ast.Tuple(load_names, ast.Load()),
ast.Tuple(expls, ast.Load()),
ast.Tuple(results, ast.Load()))
if len(comp.ops) > 1:
res = ast.BoolOp(ast.And(), load_names)
else:
res = load_names[0]
return res, self.explanation_param(self.pop_format_context(expl_call))
python类Tuple()的实例源码
def visit_Call(self, node):
"""Look for the 'LOG.*' calls."""
# extract the obj_name and method_name
if isinstance(node.func, ast.Attribute):
obj_name = self._find_name(node.func.value)
if isinstance(node.func.value, ast.Name):
method_name = node.func.attr
elif isinstance(node.func.value, ast.Attribute):
obj_name = self._find_name(node.func.value)
method_name = node.func.attr
else: # could be Subscript, Call or many more
return super(CheckLoggingFormatArgs, self).generic_visit(node)
# obj must be a logger instance and method must be a log helper
if (obj_name != 'LOG'
or method_name not in self.LOG_METHODS):
return super(CheckLoggingFormatArgs, self).generic_visit(node)
# the call must have arguments
if not len(node.args):
return super(CheckLoggingFormatArgs, self).generic_visit(node)
# any argument should not be a tuple
for arg in node.args:
if isinstance(arg, ast.Tuple):
self.add_error(arg)
return super(CheckLoggingFormatArgs, self).generic_visit(node)
def listNotEmpty(a):
"""Determines that the iterable is NOT empty, if we can know that"""
"""Used for For objects"""
if not isinstance(a, ast.AST):
return False
if type(a) == ast.Call:
if type(a.func) == ast.Name and a.func.id in ["range"]:
if len(a.args) == 1: # range(x)
return type(a.args[0]) == ast.Num and type(a.args[0].n) != complex and a.args[0].n > 0
elif len(a.args) == 2: # range(start, x)
if type(a.args[0]) == ast.Num and type(a.args[1]) == ast.Num and \
type(a.args[0].n) != complex and type(a.args[1].n) != complex and \
a.args[0].n < a.args[1].n:
return True
elif type(a.args[1]) == ast.BinOp and type(a.args[1].op) == ast.Add:
if type(a.args[1].right) == ast.Num and type(a.args[1].right) != complex and a.args[1].right.n > 0 and \
compareASTs(a.args[0], a.args[1].left, checkEquality=True) == 0:
return True
elif type(a.args[1].left) == ast.Num and type(a.args[1].left) != complex and a.args[1].left.n > 0 and \
compareASTs(a.args[0], a.args[1].right, checkEquality=True) == 0:
return True
elif type(a) in [ast.List, ast.Tuple]:
return len(a.elts) > 0
elif type(a) == ast.Str:
return len(a.s) > 0
return False
def allVariableNamesUsed(a):
"""Gathers all the variable names used in the ast"""
if not isinstance(a, ast.AST):
return []
elif type(a) == ast.Name:
return [a.id]
elif type(a) == ast.Assign:
"""In assignments, ignore all pure names used- they're being assigned to, not used"""
variables = allVariableNamesUsed(a.value)
for target in a.targets:
if type(target) == ast.Name:
pass
elif type(target) in [ast.Tuple, ast.List]:
for elt in target.elts:
if type(elt) != ast.Name:
variables += allVariableNamesUsed(elt)
else:
variables += allVariableNamesUsed(target)
return variables
elif type(a) == ast.AugAssign:
variables = allVariableNamesUsed(a.value)
variables += allVariableNamesUsed(a.target)
return variables
variables = []
for child in ast.iter_child_nodes(a):
variables += allVariableNamesUsed(child)
return variables
def allVariablesUsed(a):
"""Gathers all the variable names used in the ast"""
if type(a) == list:
variables = []
for x in a:
variables += allVariablesUsed(x)
return variables
if not isinstance(a, ast.AST):
return []
elif type(a) == ast.Name:
return [a]
elif type(a) == ast.Assign:
variables = allVariablesUsed(a.value)
for target in a.targets:
if type(target) == ast.Name:
pass
elif type(target) in [ast.Tuple, ast.List]:
for elt in target.elts:
if type(elt) == ast.Name:
pass
else:
variables += allVariablesUsed(elt)
else:
variables += allVariablesUsed(target)
return variables
else:
variables = []
for child in ast.iter_child_nodes(a):
variables += allVariablesUsed(child)
return variables
def gatherAssignedVars(targets):
"""Take a list of assigned variables and extract the names/subscripts/attributes"""
if type(targets) != list:
targets = [targets]
newTargets = []
for target in targets:
if type(target) in [ast.Tuple, ast.List]:
newTargets += gatherAssignedVars(target.elts)
elif type(target) in [ast.Name, ast.Subscript, ast.Attribute]:
newTargets.append(target)
else:
log("astTools\tgatherAssignedVars\tWeird Assign Type: " + str(type(target)),"bug")
return newTargets
def astFormat(x, gid=None):
"""Given a value, turn it into an AST if it's a constant; otherwise, leave it alone."""
if type(x) in [int, float, complex]:
return ast.Num(x)
elif type(x) == bool or x == None:
return ast.NameConstant(x)
elif type(x) == type:
types = { bool : "bool", int : "int", float : "float",
complex : "complex", str : "str", bytes : "bytes", unicode : "unicode",
list : "list", tuple : "tuple", dict : "dict" }
return ast.Name(types[x], ast.Load())
elif type(x) == str: # str or unicode
return ast.Str(x)
elif type(x) == bytes:
return ast.Bytes(x)
elif type(x) == list:
elts = [astFormat(val) for val in x]
return ast.List(elts, ast.Load())
elif type(x) == dict:
keys = []
vals = []
for key in x:
keys.append(astFormat(key))
vals.append(astFormat(x[key]))
return ast.Dict(keys, vals)
elif type(x) == tuple:
elts = [astFormat(val) for val in x]
return ast.Tuple(elts, ast.Load())
elif type(x) == set:
elts = [astFormat(val) for val in x]
if len(elts) == 0: # needs to be a call instead
return ast.Call(ast.Name("set", ast.Load()), [], [])
else:
return ast.Set(elts)
elif type(x) == slice:
return ast.Slice(astFormat(x.start), astFormat(x.stop), astFormat(x.step))
elif isinstance(x, ast.AST):
return x # Do not change if it's not constant!
else:
log("astTools\tastFormat\t" + str(type(x)) + "," + str(x),"bug")
return None
def _translate_tuple(self, elts, ctx, location):
element_nodes, accidentaly_homogeneous, element_type = self._translate_elements(elts, 'tuple', homogeneous=False)
return {
'type': 'array' if accidentaly_homogeneous else 'tuple',
'pseudo_type': ['Array', element_type, len(elts)] if accidentaly_homogeneous else ['Tuple'] + element_type,
'elements': element_nodes
}
def visit_For(self, node):
"""
For(expr target, expr iter, stmt* body, stmt* orelse)
"""
if not isinstance(node.target, (ast.Name,ast.Tuple, ast.List)):
raise RubyError("argument decomposition in 'for' loop is not supported")
#if isinstance(node.target, ast.Tuple):
#print self.visit(node.iter) #or Variable (String case)
#if isinstance(node.iter, ast.Str):
self._tuple_type = '()'
for_target = self.visit(node.target)
self._tuple_type = '[]'
#if isinstance(node.iter, (ast.Tuple, ast.List)):
# for_iter = "[%s]" % self.visit(node.iter)
#else:
# for_iter = self.visit(node.iter)
# ast.Tuple, ast.List, ast.*
for_iter = self.visit(node.iter)
iter_dummy = self.new_dummy()
orelse_dummy = self.new_dummy()
exc_dummy = self.new_dummy()
self.write("for %s in %s" % (for_target, for_iter))
self.indent()
for stmt in node.body:
self.visit(stmt)
self.dedent()
self.write("end")
if node.orelse:
self.write("if (%s) {" % orelse_dummy)
self.indent()
for stmt in node.orelse:
self.visit(stmt)
self.dedent()
self.write("}")
def visit_GeneratorExp(self, node):
"""
GeneratorExp(expr elt, comprehension* generators)
"""
#if isinstance(node.generators[0].iter, (ast.Tuple, ast.List)):
# i = "[%s]" % self.visit(node.generators[0].iter)
#else:
# i = self.visit(node.generators[0].iter)
i = self.visit(node.generators[0].iter) # ast.Tuple, ast.List, ast.*
t = self.visit(node.generators[0].target)
""" <Python> [x**2 for x in [1,2]]
<Ruby> [1, 2].map{|x| x**2} """
return "%s.map{|%s| %s}" % (i, t, self.visit(node.elt))
def visit_ListComp(self, node):
"""
ListComp(expr elt, comprehension* generators)
"""
#if isinstance(node.generators[0].iter, (ast.Tuple, ast.List)):
# i = "[%s]" % self.visit(node.generators[0].iter)
#else:
# i = self.visit(node.generators[0].iter)
i = self.visit(node.generators[0].iter) # ast.Tuple, ast.List, ast.*
if isinstance(node.generators[0].target, ast.Name):
t = self.visit(node.generators[0].target)
else:
# ast.Tuple
self._tuple_type = ''
t = self.visit(node.generators[0].target)
self._tuple_type = '[]'
if len(node.generators[0].ifs) == 0:
""" <Python> [x**2 for x in [1,2]]
<Ruby> [1, 2].map{|x| x**2} """
return "%s.map{|%s| %s}" % (i, t, self.visit(node.elt))
else:
""" <Python> [x**2 for x in [1,2] if x > 1]
<Ruby> [1, 2].select {|x| x > 1 }.map{|x| x**2} """
return "%s.select{|%s| %s}.map{|%s| %s}" % \
(i, t, self.visit(node.generators[0].ifs[0]), t, \
self.visit(node.elt))
def visit_List(self, node):
"""
List(expr* elts, expr_context ctx)
"""
#els = []
#for e in node.elts:
# if isinstance(e, (ast.Tuple, ast.List)):
# els.append("[%s]" % self.visit(e))
# else:
# els.append(self.visit(e))
# ast.Tuple, ast.List, ast.*
els = [self.visit(e) for e in node.elts]
return "[%s]" % (", ".join(els))
#return ", ".join(els)
def visit_Assign(self, node):
rhs_visitor = RHSVisitor()
rhs_visitor.visit(node.value)
if isinstance(node.targets[0], ast.Tuple): # x,y = [1,2]
if isinstance(node.value, ast.Tuple):
return self.assign_tuple_target(node, rhs_visitor.result)
elif isinstance(node.value, ast.Call):
call = None
for element in node.targets[0].elts:
label = LabelVisitor()
label.visit(element)
call = self.assignment_call_node(label.result, node)
return call
else:
label = LabelVisitor()
label.visit(node)
print('Assignment not properly handled.',
'Could result in not finding a vulnerability.',
'Assignment:', label.result)
return self.append_node(AssignmentNode(label.result, label.result, node, rhs_visitor.result, line_number=node.lineno, path=self.filenames[-1]))
elif len(node.targets) > 1: # x = y = 3
return self.assign_multi_target(node, rhs_visitor.result)
else:
if isinstance(node.value, ast.Call): # x = call()
label = LabelVisitor()
label.visit(node.targets[0])
return self.assignment_call_node(label.result, node)
else: # x = 4
label = LabelVisitor()
label.visit(node)
return self.append_node(AssignmentNode(label.result, self.extract_left_hand_side(node.targets[0]), node, rhs_visitor.result, line_number=node.lineno, path=self.filenames[-1]))
def visit_Tuple(self, node):
if node.__class__ != ast.Tuple:
return node
dummy_func = ast.Name(id="tuple", ctx=ast.Load())
return ast.Call(func=dummy_func, args=node.elts, keywords=[], starargs=None, kwargs=None)
def visit_Call(self, node):
if (
isinstance(node.func, ast.Name) and
node.func.id == 'dict' and
len(node.args) == 1 and
not _has_kwargs(node) and
isinstance(node.args[0], (ast.ListComp, ast.GeneratorExp)) and
isinstance(node.args[0].elt, (ast.Tuple, ast.List)) and
len(node.args[0].elt.elts) == 2
):
arg, = node.args
key = Offset(node.func.lineno, node.func.col_offset)
self.dicts[key] = arg
self.generic_visit(node)
def visit_Assign(self, node):
if self.is_valid_assignment(node):
call = node.value
self.encounter_call(call)
name = node.targets[0].value
self.arguments.add(SchedulerRewriter.top_level_name(name))
index = node.targets[0].slice.value
call.func = ast.Attribute(call.func, 'assign', ast.Load())
call.args = [ast.Tuple([name, index], ast.Load())] + call.args
return copy_location(ast.Expr(call), node)
return self.generic_visit(node)
def visit_Compare(self, comp):
self.push_format_context()
left_res, left_expl = self.visit(comp.left)
if isinstance(comp.left, (_ast.Compare, _ast.BoolOp)):
left_expl = "({0})".format(left_expl)
res_variables = [self.variable() for i in range(len(comp.ops))]
load_names = [ast.Name(v, ast.Load()) for v in res_variables]
store_names = [ast.Name(v, ast.Store()) for v in res_variables]
it = zip(range(len(comp.ops)), comp.ops, comp.comparators)
expls = []
syms = []
results = [left_res]
for i, op, next_operand in it:
next_res, next_expl = self.visit(next_operand)
if isinstance(next_operand, (_ast.Compare, _ast.BoolOp)):
next_expl = "({0})".format(next_expl)
results.append(next_res)
sym = binop_map[op.__class__]
syms.append(ast.Str(sym))
expl = "%s %s %s" % (left_expl, sym, next_expl)
expls.append(ast.Str(expl))
res_expr = ast.Compare(left_res, [op], [next_res])
self.statements.append(ast.Assign([store_names[i]], res_expr))
left_res, left_expl = next_res, next_expl
# Use pytest.assertion.util._reprcompare if that's available.
expl_call = self.helper("call_reprcompare",
ast.Tuple(syms, ast.Load()),
ast.Tuple(load_names, ast.Load()),
ast.Tuple(expls, ast.Load()),
ast.Tuple(results, ast.Load()))
if len(comp.ops) > 1:
res = ast.BoolOp(ast.And(), load_names)
else:
res = load_names[0]
return res, self.explanation_param(self.pop_format_context(expl_call))
def visit_Assign(self, node):
for target in node.targets:
if(isinstance(target,ast.Tuple)):#this is to handle variables declared on the same line
for el in target.elts:
self.grabVar(el)
else:
self.grabVar(target)
ast.NodeVisitor.generic_visit(self, node)#Make sure to run the original method so the AST module can do its thing
def visit_Assign(self, node):
for target in node.targets:
if(isinstance(target,ast.Tuple)):#this is to handle variables declared on the same line
for el in target.elts:
self.grabVar(el)
else:
self.grabVar(target)
ast.NodeVisitor.generic_visit(self, node)#Make sure to run the original method so the AST module can do its thing
def get_expr_value_src_dst(src_node, dst_node, name):
test_node = None
if isinstance(name, ast.Name):
name = name.id
if isinstance(dst_node, ast.Name) and dst_node.id == name:
test_node = src_node
elif isinstance(dst_node, (ast.List, ast.Tuple)) and isinstance(src_node, (ast.List, ast.Tuple)):
targets = [elt.id for elt in dst_node.elts if isinstance(elt, ast.Name)]
if name in targets:
test_node = src_node.elts[targets.index(name)]
return test_node