def pop_format_context(self, expl_expr):
"""Format the %-formatted string with current format context.
The expl_expr should be an ast.Str instance constructed from
the %-placeholders created by .explanation_param(). This will
add the required code to format said string to .on_failure and
return the ast.Name instance of the formatted string.
"""
current = self.stack.pop()
if self.stack:
self.explanation_specifiers = self.stack[-1]
keys = [ast.Str(key) for key in current.keys()]
format_dict = ast.Dict(keys, list(current.values()))
form = ast.BinOp(expl_expr, ast.Mod(), format_dict)
name = "@py_format" + str(next(self.variable_counter))
self.on_failure.append(ast.Assign([ast.Name(name, ast.Store())], form))
return ast.Name(name, ast.Load())
python类Mod()的实例源码
def num_negate(op):
top = type(op)
neg = not op.num_negated if hasattr(op, "num_negated") else True
if top == ast.Add:
newOp = ast.Sub()
elif top == ast.Sub:
newOp = ast.Add()
elif top in [ast.Mult, ast.Div, ast.Mod, ast.Pow, ast.LShift,
ast.RShift, ast.BitOr, ast.BitXor, ast.BitAnd, ast.FloorDiv]:
return None # can't negate this
elif top in [ast.Num, ast.Name]:
# this is a normal value, so put a - in front of it
newOp = ast.UnaryOp(ast.USub(addedNeg=True), op)
else:
log("astTools\tnum_negate\tUnusual type: " + str(top), "bug")
transferMetaData(op, newOp)
newOp.num_negated = neg
return newOp
def visit_BinOp(self, node):
if isinstance(node.op, ast.Mod) and isinstance(node.left, ast.Str):
left = self.visit(node.left)
# 'b=%(b)0d and c=%(c)d and d=%(d)d' => 'b=%<b>0d and c=%<c>d and d=%<d>d'
left = re.sub(r"(.+?%)\((.+?)\)(.+?)", r"\1<\2>\3", left)
self._dict_format = True
right = self.visit(node.right)
self._dict_format = False
return "%s %% %s" % (left, right)
left = self.visit(node.left)
right = self.visit(node.right)
if isinstance(node.op, ast.Pow):
return "%s ** %s" % (left, right)
if isinstance(node.op, ast.Div):
if re.search(r"Numo::", left) or re.search(r"Numo::", right):
return "(%s)/(%s)" % (left, right)
else:
return "(%s)/(%s).to_f" % (left, right)
return "(%s)%s(%s)" % (left, self.get_binary_op(node), right)
def pop_format_context(self, expl_expr):
"""Format the %-formatted string with current format context.
The expl_expr should be an ast.Str instance constructed from
the %-placeholders created by .explanation_param(). This will
add the required code to format said string to .on_failure and
return the ast.Name instance of the formatted string.
"""
current = self.stack.pop()
if self.stack:
self.explanation_specifiers = self.stack[-1]
keys = [ast.Str(key) for key in current.keys()]
format_dict = ast.Dict(keys, list(current.values()))
form = ast.BinOp(expl_expr, ast.Mod(), format_dict)
name = "@py_format" + str(next(self.variable_counter))
self.on_failure.append(ast.Assign([ast.Name(name, ast.Store())], form))
return ast.Name(name, ast.Load())
def pop_format_context(self, expl_expr):
"""Format the %-formatted string with current format context.
The expl_expr should be an ast.Str instance constructed from
the %-placeholders created by .explanation_param(). This will
add the required code to format said string to .on_failure and
return the ast.Name instance of the formatted string.
"""
current = self.stack.pop()
if self.stack:
self.explanation_specifiers = self.stack[-1]
keys = [ast.Str(key) for key in current.keys()]
format_dict = ast.Dict(keys, list(current.values()))
form = ast.BinOp(expl_expr, ast.Mod(), format_dict)
name = "@py_format" + str(next(self.variable_counter))
self.on_failure.append(ast.Assign([ast.Name(name, ast.Store())], form))
return ast.Name(name, ast.Load())
def pop_format_context(self, expl_expr):
"""Format the %-formatted string with current format context.
The expl_expr should be an ast.Str instance constructed from
the %-placeholders created by .explanation_param(). This will
add the required code to format said string to .on_failure and
return the ast.Name instance of the formatted string.
"""
current = self.stack.pop()
if self.stack:
self.explanation_specifiers = self.stack[-1]
keys = [ast.Str(key) for key in current.keys()]
format_dict = ast.Dict(keys, list(current.values()))
form = ast.BinOp(expl_expr, ast.Mod(), format_dict)
name = "@py_format" + str(next(self.variable_counter))
self.on_failure.append(ast.Assign([ast.Name(name, ast.Store())], form))
return ast.Name(name, ast.Load())
def binop_str(op: ast.AST) -> str:
if isinstance(op, ast.Add):
return '+'
if isinstance(op, ast.Sub):
return '-'
if isinstance(op, ast.Mult):
return '*'
if isinstance(op, ast.Div):
return '/ '
if isinstance(op, ast.Mod):
return '%'
if isinstance(op, ast.LShift):
return '<<'
if isinstance(op, ast.RShift):
return '>>'
if isinstance(op, ast.BitOr):
return '|'
if isinstance(op, ast.BitXor):
return '^'
if isinstance(op, ast.BitAnd):
return '&'
if isinstance(op, ast.MatMult):
return '@'
error(loc(op), "Invalid binary operator encountered: {0}:{1}. Check supported intrinsics.".format(op.lineno, op.col_offset))
return 'INVALID_BINOP'
def _infer_arithmetic(left_type, right_type, op, lineno, solver):
"""Infer the type of an arithmetic operation, and add the corresponding axioms"""
result_type = solver.new_z3_const("arithmetic_result")
magic_method = ""
if isinstance(op, ast.Sub):
magic_method = "__sub__"
elif isinstance(op, ast.FloorDiv):
magic_method = "__floordiv__"
elif isinstance(op, ast.Mod):
magic_method = "__mod__"
elif isinstance(op, ast.LShift):
magic_method = "__lshift__"
elif isinstance(op, ast.RShift):
magic_method = "__rshift__"
solver.add(axioms.arithmetic(left_type, right_type, result_type, magic_method,
isinstance(op, ast.Mod), solver.z3_types),
fail_message="Arithmetic operation in line {}".format(lineno))
return result_type
def pop_format_context(self, expl_expr):
"""Format the %-formatted string with current format context.
The expl_expr should be an ast.Str instance constructed from
the %-placeholders created by .explanation_param(). This will
add the required code to format said string to .on_failure and
return the ast.Name instance of the formatted string.
"""
current = self.stack.pop()
if self.stack:
self.explanation_specifiers = self.stack[-1]
keys = [ast.Str(key) for key in current.keys()]
format_dict = ast.Dict(keys, list(current.values()))
form = ast.BinOp(expl_expr, ast.Mod(), format_dict)
name = "@py_format" + str(next(self.variable_counter))
self.on_failure.append(ast.Assign([ast.Name(name, ast.Store())], form))
return ast.Name(name, ast.Load())
def aug_assign(self):
target = self.get_target(self.stmt.target)
sub = Expr.parse_value_expr(self.stmt.value, self.context)
if not isinstance(self.stmt.op, (ast.Add, ast.Sub, ast.Mult, ast.Div, ast.Mod)):
raise Exception("Unsupported operator for augassign")
if not isinstance(target.typ, BaseType):
raise TypeMismatchException("Can only use aug-assign operators with simple types!", self.stmt.target)
if target.location == 'storage':
o = Expr.parse_value_expr(ast.BinOp(left=LLLnode.from_list(['sload', '_stloc'], typ=target.typ, pos=target.pos),
right=sub, op=self.stmt.op, lineno=self.stmt.lineno, col_offset=self.stmt.col_offset), self.context)
return LLLnode.from_list(['with', '_stloc', target, ['sstore', '_stloc', base_type_conversion(o, o.typ, target.typ)]], typ=None, pos=getpos(self.stmt))
elif target.location == 'memory':
o = Expr.parse_value_expr(ast.BinOp(left=LLLnode.from_list(['mload', '_mloc'], typ=target.typ, pos=target.pos),
right=sub, op=self.stmt.op, lineno=self.stmt.lineno, col_offset=self.stmt.col_offset), self.context)
return LLLnode.from_list(['with', '_mloc', target, ['mstore', '_mloc', base_type_conversion(o, o.typ, target.typ)]], typ=None, pos=getpos(self.stmt))
def doBinaryOp(op, l, r):
"""Perform the given AST binary operation on the values"""
top = type(op)
if top == ast.Add:
return l + r
elif top == ast.Sub:
return l - r
elif top == ast.Mult:
return l * r
elif top == ast.Div:
# Don't bother if this will be a really long float- it won't work properly!
# Also, in Python 3 this is floating division, so perform it accordingly.
val = 1.0 * l / r
if (val * 1e10 % 1.0) != 0:
raise Exception("Repeating Float")
return val
elif top == ast.Mod:
return l % r
elif top == ast.Pow:
return l ** r
elif top == ast.LShift:
return l << r
elif top == ast.RShift:
return l >> r
elif top == ast.BitOr:
return l | r
elif top == ast.BitXor:
return l ^ r
elif top == ast.BitAnd:
return l & r
elif top == ast.FloorDiv:
return l // r
def old_fmt_str_sql_expressions(context):
binop_node = context.node
if not (isinstance(binop_node.op, ast.Mod) and isinstance(binop_node.left, ast.Str)):
return
return _check_string_for_sql(binop_node.left)
def visit_BinOp(self, node):
if not self.config.constant_folding:
return
eval_binop = EVAL_BINOP.get(node.op.__class__)
if not eval_binop:
return
if isinstance(node.op, ast.Mod):
# FIXME: optimize str%args and bytes%args
left_types = COMPLEX_TYPES
else:
left_types = None
left = get_constant(node.left, types=left_types)
if left is UNSET:
return
right = get_constant(node.right)
if right is UNSET:
return
ok = self.check_binop(node.op, left, right)
if not ok:
return
result = eval_binop(left, right)
new_node = self.new_constant(node, result)
if new_node is None:
return
op_str = BINOP_STR[node.op.__class__]
self.log(node, "constant folding: replace %s %s %s with %s",
compact_ascii(left), op_str, compact_ascii(right),
compact_ascii(result), add_line=True)
return new_node
def get_binary_op_str(bin_op_node):
"""Returns the string representation of the binary operator node (e.g. +, -,
etc.). For some reason astor doesn't implement this???
"""
if isinstance(bin_op_node, ast.Add):
return "+"
elif isinstance(bin_op_node, ast.Sub):
return "-"
elif isinstance(bin_op_node, ast.Mult):
return "*"
elif isinstance(bin_op_node, ast.Div):
return "/"
elif isinstance(bin_op_node, ast.Mod):
return "%"
elif isinstance(bin_op_node, ast.Pow):
return "**"
elif isinstance(bin_op_node, ast.LShift):
return "<<"
elif isinstance(bin_op_node, ast.RShift):
return ">>"
else:
raise ValueError("No string defined for binary operator node %s" % \
bin_op_node.__class__.__name__)
def pythonast(self, args, tonative=False):
# Note: Numba knows that Python's % is modulo and not remainder (unlike C)
return ast.BinOp(args[0], ast.Mod(), args[1])
def syn_BinOp(self, ctx, e):
if isinstance(e.op, (ast.LShift, ast.RShift, ast.BitOr, ast.BitXor, ast.BitAnd)):
raise _errors.TyError("Cannot use bitwise operators on cplx values.", e)
if isinstance(e.op, ast.Mod):
raise _errors.TyError("Cannot take the modulus of a complex number.", e)
right = e.right
ctx.ana(right, self)
return self
def basic_auth_literal(context):
call_node = context.node
parent = s_utils.get_top_parent_node(call_node)
if not (isinstance(call_node.func, ast.Attribute) and call_node.func.attr == 'add_header'):
return
klass_name = next(
(klass for klass in s_utils.iter_method_classes(parent, call_node, context) if klass in ('urllib2.Request', 'urllib.request.Request')),
None
)
if klass_name is None:
return
if not len(call_node.args) == 2:
return
arg0, arg1 = call_node.args[:2]
if not (isinstance(arg0, ast.Str) and arg0.s.lower() == 'authorization'):
return
if isinstance(arg1, ast.BinOp) and isinstance(arg1.left, ast.Str):
str_node = arg1.left
str_node.parent = arg1
elif isinstance(arg1, ast.Str):
str_node = arg1
else:
return
if re.match(r'^basic\s+', str_node.s, flags=re.IGNORECASE) is None:
return
issue = bandit.Issue(
severity=bandit.HIGH,
confidence=bandit.MEDIUM,
text='A hard-coded string is being used as an HTTP basic authorization header'
)
if re.match(r'^basic\s+[\w]{2,}={0,2}$', str_node.s, flags=re.IGNORECASE):
return issue
if not isinstance(str_node.parent, ast.BinOp):
return
binop_node = str_node.parent
if not (isinstance(binop_node.op, (ast.Add, ast.Mod)) and binop_node.left == str_node):
return
header_value = None
if isinstance(binop_node.right, ast.Call):
call_name = b_utils.get_call_name(binop_node.right, context._context['import_aliases'])
if re.match(r'base64.(standard_|urlsafe_)?b64encode', call_name) is None:
return
header_value = next((value for value in s_utils.get_call_arg_values(parent, binop_node.right, arg=0) if isinstance(value, (str, bytes))), None)
elif isinstance(binop_node.right, (ast.Name, ast.Str)):
header_value = next((value for value in s_utils.iter_expr_literal_values(parent, binop_node.right) if isinstance(value, (str, bytes))), None)
if header_value is None:
return
return issue
def visit_BinOp(self, node):
left_term = self.visit(node.left)
right_term = self.visit(node.right)
if self.__is_bool(left_term) and self.__is_bool(right_term):
if isinstance(node.op, ast.BitAnd):
return And(left_term, right_term)
elif isinstance(node.op, ast.BitOr):
return Or(left_term, right_term)
elif isinstance(node.op, ast.BitXor):
return Xor(left_term, right_term)
else:
raise Exception("Unsupported bool binary operation %s" % unparse(node))
if DATA_TYPE == "int":
if isinstance(node.op, ast.Mod):
return left_term % right_term
elif isinstance(node.op, ast.Add):
return left_term + right_term
elif isinstance(node.op, ast.Sub):
return left_term - right_term
elif isinstance(node.op, ast.Mult):
return left_term * right_term
elif isinstance(node.op, ast.BitXor):
# Special-case for bool circuit-examples:
if is_is_int(left_term):
left_term = left_term == IntVal(1)
if is_is_int(right_term):
right_term = right_term == IntVal(1)
return left_term != right_term
else:
raise Exception("Unsupported integer binary operation %s" % unparse(node))
elif DATA_TYPE.startswith("bit_"):
if isinstance(node.op, ast.BitAnd):
return left_term & right_term
elif isinstance(node.op, ast.BitOr):
return left_term | right_term
elif isinstance(node.op, ast.BitXor):
return left_term ^ right_term
else:
raise Exception("Unsupported bitvector operation %s" % unparse(node))
else:
raise Exception("Unsupported data type %s" % DATA_TYPE)
def _gclient_eval(node_or_string, global_scope, filename='<unknown>'):
"""Safely evaluates a single expression. Returns the result."""
_allowed_names = {'None': None, 'True': True, 'False': False}
if isinstance(node_or_string, basestring):
node_or_string = ast.parse(node_or_string, filename=filename, mode='eval')
if isinstance(node_or_string, ast.Expression):
node_or_string = node_or_string.body
def _convert(node):
if isinstance(node, ast.Str):
return node.s
elif isinstance(node, ast.Num):
return node.n
elif isinstance(node, ast.Tuple):
return tuple(map(_convert, node.elts))
elif isinstance(node, ast.List):
return list(map(_convert, node.elts))
elif isinstance(node, ast.Dict):
return collections.OrderedDict(
(_convert(k), _convert(v))
for k, v in zip(node.keys, node.values))
elif isinstance(node, ast.Name):
if node.id not in _allowed_names:
raise ValueError(
'invalid name %r (file %r, line %s)' % (
node.id, filename, getattr(node, 'lineno', '<unknown>')))
return _allowed_names[node.id]
elif isinstance(node, ast.Call):
if not isinstance(node.func, ast.Name):
raise ValueError(
'invalid call: func should be a name (file %r, line %s)' % (
filename, getattr(node, 'lineno', '<unknown>')))
if node.keywords or node.starargs or node.kwargs:
raise ValueError(
'invalid call: use only regular args (file %r, line %s)' % (
filename, getattr(node, 'lineno', '<unknown>')))
args = map(_convert, node.args)
return global_scope[node.func.id](*args)
elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.Add):
return _convert(node.left) + _convert(node.right)
elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.Mod):
return _convert(node.left) % _convert(node.right)
else:
raise ValueError(
'unexpected AST node: %s %s (file %r, line %s)' % (
node, ast.dump(node), filename,
getattr(node, 'lineno', '<unknown>')))
return _convert(node_or_string)