80 ): |
80 ): |
81 statement = node.value |
81 statement = node.value |
82 # Hierarchy for "".format() is Wrapper -> Call -> Attribute -> Str |
82 # Hierarchy for "".format() is Wrapper -> Call -> Attribute -> Str |
83 wrapper = node._securityParent._securityParent._securityParent |
83 wrapper = node._securityParent._securityParent._securityParent |
84 elif hasattr(ast, "JoinedStr") and isinstance(node._securityParent, ast.JoinedStr): |
84 elif hasattr(ast, "JoinedStr") and isinstance(node._securityParent, ast.JoinedStr): |
85 statement = node.value |
85 substrings = [ |
86 wrapper = node._securityParent._securityParent |
86 child |
|
87 for child in node._securityParent.values |
|
88 if isinstance(child, ast.Constant) and isinstance(node.value, str) |
|
89 ] |
|
90 # JoinedStr consists of list of Constant and FormattedValue |
|
91 # instances. Let's perform one test for the whole string |
|
92 # and abandon all parts except the first one to raise one |
|
93 # failed test instead of many for the same SQL statement. |
|
94 if substrings and node == substrings[0]: |
|
95 statement = "".join([str(child.value) for child in substrings]) |
|
96 wrapper = node._securityParent._securityParent |
87 |
97 |
88 if isinstance(wrapper, ast.Call): # wrapped in "execute" call? |
98 if isinstance(wrapper, ast.Call): # wrapped in "execute" call? |
89 names = ["execute", "executemany"] |
99 names = ["execute", "executemany"] |
90 name = SecurityUtils.getCalledName(wrapper) |
100 name = SecurityUtils.getCalledName(wrapper) |
91 return (name in names, statement) |
101 return (name in names, statement) |