mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Python: Recognize nested tuple/list assignment
Now we recognize `[(x,y)] = [(1,2)]` -- in itself not a widely used idiom, but more of a warmup excersize for me
This commit is contained in:
@@ -753,9 +753,8 @@ class DefinitionNode extends ControlFlowNode {
|
||||
or
|
||||
augstore(_, this)
|
||||
or
|
||||
exists(Assign a | a.getATarget().(Tuple).getAnElt().getAFlowNode() = this)
|
||||
or
|
||||
exists(Assign a | a.getATarget().(List).getAnElt().getAFlowNode() = this)
|
||||
// `x, y = 1, 2` where LHS is a combination of list or tuples
|
||||
exists(Assign a | list_or_tuple_nested_element(a.getATarget()).getAFlowNode() = this)
|
||||
or
|
||||
exists(For for | for.getTarget().getAFlowNode() = this)
|
||||
}
|
||||
@@ -768,6 +767,18 @@ class DefinitionNode extends ControlFlowNode {
|
||||
}
|
||||
}
|
||||
|
||||
private Expr list_or_tuple_nested_element(Expr list_or_tuple) {
|
||||
exists(Expr elt |
|
||||
elt = list_or_tuple.(Tuple).getAnElt()
|
||||
or
|
||||
elt = list_or_tuple.(List).getAnElt()
|
||||
|
|
||||
result = elt
|
||||
or
|
||||
result = list_or_tuple_nested_element(elt)
|
||||
)
|
||||
}
|
||||
|
||||
/** A control flow node corresponding to a deletion statement, such as `del x`.
|
||||
* There can be multiple `DeletionNode`s for each `Delete` such that each
|
||||
* target has own `DeletionNode`. The CFG for `del a, x.y` looks like:
|
||||
@@ -887,18 +898,38 @@ private AstNode assigned_value(Expr lhs) {
|
||||
/* lhs += x => result = (lhs + x) */
|
||||
exists(AugAssign a, BinaryExpr b | b = a.getOperation() and result = b and lhs = b.getLeft())
|
||||
or
|
||||
/* ..., lhs, ... = ..., result, ... */
|
||||
exists(Assign a, Tuple target, Tuple values, int index |
|
||||
a.getATarget() = target and
|
||||
a.getValue() = values and
|
||||
lhs = target.getElt(index) and
|
||||
result = values.getElt(index)
|
||||
)
|
||||
/* ..., lhs, ... = ..., result, ...
|
||||
* or
|
||||
* ..., (..., lhs, ...), ... = ..., (..., result, ...), ...
|
||||
*/
|
||||
exists(Assign a | nested_sequence_assign(a.getATarget(), a.getValue(), lhs, result))
|
||||
or
|
||||
/* for lhs in seq: => `result` is the `for` node, representing the `iter(next(seq))` operation. */
|
||||
result.(For).getTarget() = lhs
|
||||
}
|
||||
|
||||
predicate nested_sequence_assign(Expr left_parent, Expr right_parent,
|
||||
Expr left_result, Expr right_result) {
|
||||
exists(int i, Expr left_elem, Expr right_elem
|
||||
|
|
||||
(
|
||||
left_elem = left_parent.(Tuple).getElt(i)
|
||||
or
|
||||
left_elem = left_parent.(List).getElt(i)
|
||||
)
|
||||
and
|
||||
(
|
||||
right_elem = right_parent.(Tuple).getElt(i)
|
||||
or
|
||||
right_elem = right_parent.(List).getElt(i)
|
||||
)
|
||||
|
|
||||
left_result = left_elem and right_result = right_elem
|
||||
or
|
||||
nested_sequence_assign(left_elem, right_elem, left_result, right_result)
|
||||
)
|
||||
}
|
||||
|
||||
/** A flow node for a `for` statement. */
|
||||
class ForNode extends ControlFlowNode {
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
| assignment.py:5 | SOURCE | assignment.py:5 | Taint simple.test | a |
|
||||
| assignment.py:7 | a | assignment.py:7 | Taint simple.test | b |
|
||||
| assignment.py:13 | SOURCE | assignment.py:13 | Taint simple.test | t1 |
|
||||
| assignment.py:13 | SOURCE | assignment.py:13 | Taint simple.test | t2 |
|
||||
| carrier.py:4 | ParameterDefinition | carrier.py:4 | Taint explicit.carrier | arg |
|
||||
| carrier.py:4 | ParameterDefinition | carrier.py:4 | Taint simple.test | arg |
|
||||
|
||||
@@ -119,6 +119,7 @@
|
||||
| simple.test | assignment.py:7 | a | | --> | sequence of simple.test | assignment.py:7 | Tuple | |
|
||||
| simple.test | assignment.py:7 | a | | --> | simple.test | assignment.py:8 | b | |
|
||||
| simple.test | assignment.py:13 | SOURCE | | --> | sequence of simple.test | assignment.py:13 | Tuple | |
|
||||
| simple.test | assignment.py:13 | SOURCE | | --> | simple.test | assignment.py:14 | t1 | |
|
||||
| simple.test | assignment.py:13 | SOURCE | | --> | simple.test | assignment.py:14 | t2 | |
|
||||
| simple.test | carrier.py:4 | arg | p1 = simple.test | --> | simple.test | carrier.py:5 | arg | p1 = simple.test |
|
||||
| simple.test | carrier.py:17 | SOURCE | | --> | .attr = simple.test | carrier.py:17 | ImplicitCarrier() | |
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
| assignment.py:8 | swap_taint | b | simple.test |
|
||||
| assignment.py:14 | nested_assignment | s1 | NO TAINT |
|
||||
| assignment.py:14 | nested_assignment | s2 | NO TAINT |
|
||||
| assignment.py:14 | nested_assignment | t1 | NO TAINT |
|
||||
| assignment.py:14 | nested_assignment | t1 | simple.test |
|
||||
| assignment.py:14 | nested_assignment | t2 | simple.test |
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
| assignment.py:5 | a_0 | assignment.py:5 | Taint simple.test |
|
||||
| assignment.py:6 | a_1 | assignment.py:6 | Taint simple.test |
|
||||
| assignment.py:7 | b_1 | assignment.py:7 | Taint simple.test |
|
||||
| assignment.py:13 | t1_0 | assignment.py:13 | Taint simple.test |
|
||||
| assignment.py:13 | t2_0 | assignment.py:13 | Taint simple.test |
|
||||
| assignment.py:14 | t1_1 | assignment.py:14 | Taint simple.test |
|
||||
| carrier.py:4 | arg_0 | carrier.py:4 | Taint explicit.carrier |
|
||||
| carrier.py:4 | arg_0 | carrier.py:4 | Taint simple.test |
|
||||
| carrier.py:5 | self_1 | carrier.py:5 | Taint .attr = explicit.carrier |
|
||||
|
||||
Reference in New Issue
Block a user