Python: Implement simple barrier guard

The one found in the original test case
This commit is contained in:
Rasmus Lerchedahl Petersen
2021-08-30 11:04:27 +02:00
parent 49ae549e89
commit a762373ad6
4 changed files with 143 additions and 27 deletions

View File

@@ -19,16 +19,21 @@ module ModificationOfParameterWithDefault {
* A data-flow configuration for detecting modifications of a parameters default value.
*/
class Configuration extends DataFlow::Configuration {
Configuration() { this = "ModificationOfParameterWithDefault" }
boolean nonEmpty;
override predicate isSource(DataFlow::Node source) { source instanceof Source }
Configuration() {
nonEmpty in [true, false] and
this = "ModificationOfParameterWithDefault:" + nonEmpty.toString()
}
override predicate isSource(DataFlow::Node source) { source.(Source).isNonEmpty() = nonEmpty }
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
override predicate isBarrier(DataFlow::Node node) { node instanceof Barrier }
override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
guard instanceof BarrierGuard
guard.(BarrierGuard).blocksNonEmpty() = nonEmpty
}
}
}

View File

@@ -16,7 +16,9 @@ module ModificationOfParameterWithDefault {
/**
* A data flow source for detecting modifications of a parameters default value.
*/
abstract class Source extends DataFlow::Node { }
abstract class Source extends DataFlow::Node {
abstract boolean isNonEmpty();
}
/**
* A data flow sink for detecting modifications of a parameters default value.
@@ -31,7 +33,9 @@ module ModificationOfParameterWithDefault {
/**
* A sanitizer guard for detecting modifications of a parameters default value.
*/
abstract class BarrierGuard extends DataFlow::BarrierGuard { }
abstract class BarrierGuard extends DataFlow::BarrierGuard {
abstract boolean blocksNonEmpty();
}
/** Gets the truthiness (non emptyness) of the default of `p` if that value is mutable */
private boolean mutableDefaultValue(Parameter p) {
@@ -55,6 +59,8 @@ module ModificationOfParameterWithDefault {
boolean nonEmpty;
MutableDefaultValue() { nonEmpty = mutableDefaultValue(this.asCfgNode().(NameNode).getNode()) }
override boolean isNonEmpty() { result = nonEmpty }
}
/**
@@ -113,4 +119,47 @@ module ModificationOfParameterWithDefault {
)
}
}
private class IdentityGuarded extends Expr {
boolean inverted;
IdentityGuarded() {
this = any(If i).getTest() and
inverted = false
or
exists(IdentityGuarded ig, UnaryExpr notExp |
notExp.getOp() instanceof Not and
ig = notExp and
notExp.getOperand() = this
|
inverted = ig.isInverted().booleanNot()
)
}
boolean isInverted() { result = inverted }
}
class IdentityGuard extends BarrierGuard {
ControlFlowNode checked_node;
boolean safe_branch;
boolean nonEmpty;
IdentityGuard() {
nonEmpty in [true, false] and
exists(IdentityGuarded ig |
this.getNode() = ig and
checked_node = this and
// The raw guard is true if the value is non-empty
// So we are safe either if we are looking for a non-empty value
// or if we are looking for an empty value and the guard is inverted.
safe_branch = ig.isInverted().booleanXor(nonEmpty)
)
}
override predicate checks(ControlFlowNode node, boolean branch) {
node = checked_node and branch = safe_branch
}
override boolean blocksNonEmpty() { result = nonEmpty }
}
}

View File

@@ -1,4 +1,7 @@
edges
| test.py:2:12:2:12 | ControlFlowNode for l | test.py:3:5:3:5 | ControlFlowNode for l |
| test.py:7:11:7:11 | ControlFlowNode for l | test.py:8:5:8:5 | ControlFlowNode for l |
| test.py:12:14:12:14 | ControlFlowNode for l | test.py:13:9:13:9 | ControlFlowNode for l |
| test.py:17:15:17:15 | ControlFlowNode for l | test.py:18:5:18:5 | ControlFlowNode for l |
| test.py:22:15:22:15 | ControlFlowNode for l | test.py:23:5:23:5 | ControlFlowNode for l |
| test.py:27:12:27:12 | ControlFlowNode for l | test.py:28:5:28:5 | ControlFlowNode for l |
@@ -6,16 +9,29 @@ edges
| test.py:43:14:43:14 | ControlFlowNode for l | test.py:44:13:44:13 | ControlFlowNode for l |
| test.py:44:13:44:13 | ControlFlowNode for l | test.py:38:13:38:13 | ControlFlowNode for l |
| test.py:48:14:48:14 | ControlFlowNode for l | test.py:49:5:49:5 | ControlFlowNode for l |
| test.py:53:10:53:10 | ControlFlowNode for d | test.py:54:5:54:5 | ControlFlowNode for d |
| test.py:58:19:58:19 | ControlFlowNode for d | test.py:59:5:59:5 | ControlFlowNode for d |
| test.py:63:28:63:28 | ControlFlowNode for d | test.py:64:5:64:5 | ControlFlowNode for d |
| test.py:67:14:67:14 | ControlFlowNode for d | test.py:68:5:68:5 | ControlFlowNode for d |
| test.py:72:19:72:19 | ControlFlowNode for d | test.py:73:14:73:14 | ControlFlowNode for d |
| test.py:73:14:73:14 | ControlFlowNode for d | test.py:67:14:67:14 | ControlFlowNode for d |
| test.py:77:17:77:17 | ControlFlowNode for d | test.py:78:5:78:5 | ControlFlowNode for d |
| test.py:82:26:82:26 | ControlFlowNode for d | test.py:83:5:83:5 | ControlFlowNode for d |
| test.py:87:35:87:35 | ControlFlowNode for d | test.py:88:5:88:5 | ControlFlowNode for d |
| test.py:91:21:91:21 | ControlFlowNode for d | test.py:92:5:92:5 | ControlFlowNode for d |
| test.py:96:26:96:26 | ControlFlowNode for d | test.py:97:21:97:21 | ControlFlowNode for d |
| test.py:97:21:97:21 | ControlFlowNode for d | test.py:91:21:91:21 | ControlFlowNode for d |
| test.py:108:14:108:14 | ControlFlowNode for d | test.py:109:9:109:9 | ControlFlowNode for d |
| test.py:113:20:113:20 | ControlFlowNode for d | test.py:115:5:115:5 | ControlFlowNode for d |
| test.py:119:29:119:29 | ControlFlowNode for d | test.py:121:5:121:5 | ControlFlowNode for d |
| test.py:125:15:125:15 | ControlFlowNode for l | test.py:127:9:127:9 | ControlFlowNode for l |
nodes
| test.py:2:12:2:12 | ControlFlowNode for l | semmle.label | ControlFlowNode for l |
| test.py:3:5:3:5 | ControlFlowNode for l | semmle.label | ControlFlowNode for l |
| test.py:7:11:7:11 | ControlFlowNode for l | semmle.label | ControlFlowNode for l |
| test.py:8:5:8:5 | ControlFlowNode for l | semmle.label | ControlFlowNode for l |
| test.py:12:14:12:14 | ControlFlowNode for l | semmle.label | ControlFlowNode for l |
| test.py:13:9:13:9 | ControlFlowNode for l | semmle.label | ControlFlowNode for l |
| test.py:17:15:17:15 | ControlFlowNode for l | semmle.label | ControlFlowNode for l |
| test.py:18:5:18:5 | ControlFlowNode for l | semmle.label | ControlFlowNode for l |
| test.py:22:15:22:15 | ControlFlowNode for l | semmle.label | ControlFlowNode for l |
@@ -28,6 +44,16 @@ nodes
| test.py:44:13:44:13 | ControlFlowNode for l | semmle.label | ControlFlowNode for l |
| test.py:48:14:48:14 | ControlFlowNode for l | semmle.label | ControlFlowNode for l |
| test.py:49:5:49:5 | ControlFlowNode for l | semmle.label | ControlFlowNode for l |
| test.py:53:10:53:10 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:54:5:54:5 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:58:19:58:19 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:59:5:59:5 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:63:28:63:28 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:64:5:64:5 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:67:14:67:14 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:68:5:68:5 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:72:19:72:19 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:73:14:73:14 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:77:17:77:17 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:78:5:78:5 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:82:26:82:26 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
@@ -38,6 +64,8 @@ nodes
| test.py:92:5:92:5 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:96:26:96:26 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:97:21:97:21 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:108:14:108:14 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:109:9:109:9 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:113:20:113:20 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:115:5:115:5 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
| test.py:119:29:119:29 | ControlFlowNode for d | semmle.label | ControlFlowNode for d |
@@ -45,15 +73,23 @@ nodes
| test.py:125:15:125:15 | ControlFlowNode for l | semmle.label | ControlFlowNode for l |
| test.py:127:9:127:9 | ControlFlowNode for l | semmle.label | ControlFlowNode for l |
#select
| test.py:3:5:3:5 | ControlFlowNode for l | test.py:2:12:2:12 | ControlFlowNode for l | test.py:3:5:3:5 | ControlFlowNode for l | $@ flows to here and is mutated. | test.py:2:12:2:12 | ControlFlowNode for l | Default value |
| test.py:8:5:8:5 | ControlFlowNode for l | test.py:7:11:7:11 | ControlFlowNode for l | test.py:8:5:8:5 | ControlFlowNode for l | $@ flows to here and is mutated. | test.py:7:11:7:11 | ControlFlowNode for l | Default value |
| test.py:13:9:13:9 | ControlFlowNode for l | test.py:12:14:12:14 | ControlFlowNode for l | test.py:13:9:13:9 | ControlFlowNode for l | $@ flows to here and is mutated. | test.py:12:14:12:14 | ControlFlowNode for l | Default value |
| test.py:18:5:18:5 | ControlFlowNode for l | test.py:17:15:17:15 | ControlFlowNode for l | test.py:18:5:18:5 | ControlFlowNode for l | $@ flows to here and is mutated. | test.py:17:15:17:15 | ControlFlowNode for l | Default value |
| test.py:23:5:23:5 | ControlFlowNode for l | test.py:22:15:22:15 | ControlFlowNode for l | test.py:23:5:23:5 | ControlFlowNode for l | $@ flows to here and is mutated. | test.py:22:15:22:15 | ControlFlowNode for l | Default value |
| test.py:28:5:28:5 | ControlFlowNode for l | test.py:27:12:27:12 | ControlFlowNode for l | test.py:28:5:28:5 | ControlFlowNode for l | $@ flows to here and is mutated. | test.py:27:12:27:12 | ControlFlowNode for l | Default value |
| test.py:39:5:39:5 | ControlFlowNode for l | test.py:43:14:43:14 | ControlFlowNode for l | test.py:39:5:39:5 | ControlFlowNode for l | $@ flows to here and is mutated. | test.py:43:14:43:14 | ControlFlowNode for l | Default value |
| test.py:49:5:49:5 | ControlFlowNode for l | test.py:48:14:48:14 | ControlFlowNode for l | test.py:49:5:49:5 | ControlFlowNode for l | $@ flows to here and is mutated. | test.py:48:14:48:14 | ControlFlowNode for l | Default value |
| test.py:54:5:54:5 | ControlFlowNode for d | test.py:53:10:53:10 | ControlFlowNode for d | test.py:54:5:54:5 | ControlFlowNode for d | $@ flows to here and is mutated. | test.py:53:10:53:10 | ControlFlowNode for d | Default value |
| test.py:59:5:59:5 | ControlFlowNode for d | test.py:58:19:58:19 | ControlFlowNode for d | test.py:59:5:59:5 | ControlFlowNode for d | $@ flows to here and is mutated. | test.py:58:19:58:19 | ControlFlowNode for d | Default value |
| test.py:64:5:64:5 | ControlFlowNode for d | test.py:63:28:63:28 | ControlFlowNode for d | test.py:64:5:64:5 | ControlFlowNode for d | $@ flows to here and is mutated. | test.py:63:28:63:28 | ControlFlowNode for d | Default value |
| test.py:68:5:68:5 | ControlFlowNode for d | test.py:72:19:72:19 | ControlFlowNode for d | test.py:68:5:68:5 | ControlFlowNode for d | $@ flows to here and is mutated. | test.py:72:19:72:19 | ControlFlowNode for d | Default value |
| test.py:78:5:78:5 | ControlFlowNode for d | test.py:77:17:77:17 | ControlFlowNode for d | test.py:78:5:78:5 | ControlFlowNode for d | $@ flows to here and is mutated. | test.py:77:17:77:17 | ControlFlowNode for d | Default value |
| test.py:83:5:83:5 | ControlFlowNode for d | test.py:82:26:82:26 | ControlFlowNode for d | test.py:83:5:83:5 | ControlFlowNode for d | $@ flows to here and is mutated. | test.py:82:26:82:26 | ControlFlowNode for d | Default value |
| test.py:88:5:88:5 | ControlFlowNode for d | test.py:87:35:87:35 | ControlFlowNode for d | test.py:88:5:88:5 | ControlFlowNode for d | $@ flows to here and is mutated. | test.py:87:35:87:35 | ControlFlowNode for d | Default value |
| test.py:92:5:92:5 | ControlFlowNode for d | test.py:96:26:96:26 | ControlFlowNode for d | test.py:92:5:92:5 | ControlFlowNode for d | $@ flows to here and is mutated. | test.py:96:26:96:26 | ControlFlowNode for d | Default value |
| test.py:109:9:109:9 | ControlFlowNode for d | test.py:108:14:108:14 | ControlFlowNode for d | test.py:109:9:109:9 | ControlFlowNode for d | $@ flows to here and is mutated. | test.py:108:14:108:14 | ControlFlowNode for d | Default value |
| test.py:115:5:115:5 | ControlFlowNode for d | test.py:113:20:113:20 | ControlFlowNode for d | test.py:115:5:115:5 | ControlFlowNode for d | $@ flows to here and is mutated. | test.py:113:20:113:20 | ControlFlowNode for d | Default value |
| test.py:121:5:121:5 | ControlFlowNode for d | test.py:119:29:119:29 | ControlFlowNode for d | test.py:121:5:121:5 | ControlFlowNode for d | $@ flows to here and is mutated. | test.py:119:29:119:29 | ControlFlowNode for d | Default value |
| test.py:127:9:127:9 | ControlFlowNode for l | test.py:125:15:125:15 | ControlFlowNode for l | test.py:127:9:127:9 | ControlFlowNode for l | $@ flows to here and is mutated. | test.py:125:15:125:15 | ControlFlowNode for l | Default value |

View File

@@ -1,24 +1,50 @@
edges
| functions_test.py:39:9:39:9 | empty mutable value | functions_test.py:40:5:40:5 | empty mutable value |
| functions_test.py:133:15:133:15 | empty mutable value | functions_test.py:134:5:134:5 | empty mutable value |
| functions_test.py:151:25:151:25 | empty mutable value | functions_test.py:152:5:152:5 | empty mutable value |
| functions_test.py:154:21:154:21 | empty mutable value | functions_test.py:155:5:155:5 | empty mutable value |
| functions_test.py:157:27:157:27 | empty mutable value | functions_test.py:158:25:158:25 | empty mutable value |
| functions_test.py:157:27:157:27 | empty mutable value | functions_test.py:159:21:159:21 | empty mutable value |
| functions_test.py:158:25:158:25 | empty mutable value | functions_test.py:151:25:151:25 | empty mutable value |
| functions_test.py:159:21:159:21 | empty mutable value | functions_test.py:154:21:154:21 | empty mutable value |
| functions_test.py:175:28:175:28 | non-empty mutable value | functions_test.py:179:9:179:9 | non-empty mutable value |
| functions_test.py:175:28:175:28 | non-empty mutable value | functions_test.py:181:9:181:9 | non-empty mutable value |
| functions_test.py:188:18:188:18 | non-empty mutable value | functions_test.py:189:28:189:28 | non-empty mutable value |
| functions_test.py:189:28:189:28 | non-empty mutable value | functions_test.py:175:28:175:28 | non-empty mutable value |
| functions_test.py:191:18:191:18 | non-empty mutable value | functions_test.py:192:28:192:28 | non-empty mutable value |
| functions_test.py:192:28:192:28 | non-empty mutable value | functions_test.py:175:28:175:28 | non-empty mutable value |
| functions_test.py:39:9:39:9 | ControlFlowNode for x | functions_test.py:40:5:40:5 | ControlFlowNode for x |
| functions_test.py:133:15:133:15 | ControlFlowNode for x | functions_test.py:134:5:134:5 | ControlFlowNode for x |
| functions_test.py:151:25:151:25 | ControlFlowNode for x | functions_test.py:152:5:152:5 | ControlFlowNode for x |
| functions_test.py:154:21:154:21 | ControlFlowNode for x | functions_test.py:155:5:155:5 | ControlFlowNode for x |
| functions_test.py:157:27:157:27 | ControlFlowNode for y | functions_test.py:158:25:158:25 | ControlFlowNode for y |
| functions_test.py:157:27:157:27 | ControlFlowNode for y | functions_test.py:159:21:159:21 | ControlFlowNode for y |
| functions_test.py:158:25:158:25 | ControlFlowNode for y | functions_test.py:151:25:151:25 | ControlFlowNode for x |
| functions_test.py:159:21:159:21 | ControlFlowNode for y | functions_test.py:154:21:154:21 | ControlFlowNode for x |
| functions_test.py:166:21:166:25 | ControlFlowNode for param | functions_test.py:170:9:170:13 | ControlFlowNode for param |
| functions_test.py:166:21:166:25 | ControlFlowNode for param | functions_test.py:170:9:170:13 | ControlFlowNode for param |
| functions_test.py:175:28:175:28 | ControlFlowNode for x | functions_test.py:179:9:179:9 | ControlFlowNode for x |
| functions_test.py:175:28:175:28 | ControlFlowNode for x | functions_test.py:181:9:181:9 | ControlFlowNode for x |
| functions_test.py:188:18:188:18 | ControlFlowNode for x | functions_test.py:189:28:189:28 | ControlFlowNode for x |
| functions_test.py:189:28:189:28 | ControlFlowNode for x | functions_test.py:175:28:175:28 | ControlFlowNode for x |
| functions_test.py:191:18:191:18 | ControlFlowNode for x | functions_test.py:192:28:192:28 | ControlFlowNode for x |
| functions_test.py:192:28:192:28 | ControlFlowNode for x | functions_test.py:175:28:175:28 | ControlFlowNode for x |
nodes
| functions_test.py:39:9:39:9 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| functions_test.py:40:5:40:5 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| functions_test.py:133:15:133:15 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| functions_test.py:134:5:134:5 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| functions_test.py:151:25:151:25 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| functions_test.py:152:5:152:5 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| functions_test.py:154:21:154:21 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| functions_test.py:155:5:155:5 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| functions_test.py:157:27:157:27 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| functions_test.py:158:25:158:25 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| functions_test.py:159:21:159:21 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| functions_test.py:166:21:166:25 | ControlFlowNode for param | semmle.label | ControlFlowNode for param |
| functions_test.py:170:9:170:13 | ControlFlowNode for param | semmle.label | ControlFlowNode for param |
| functions_test.py:170:9:170:13 | ControlFlowNode for param | semmle.label | ControlFlowNode for param |
| functions_test.py:175:28:175:28 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| functions_test.py:179:9:179:9 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| functions_test.py:181:9:181:9 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| functions_test.py:188:18:188:18 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| functions_test.py:189:28:189:28 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| functions_test.py:191:18:191:18 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| functions_test.py:192:28:192:28 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
#select
| functions_test.py:40:5:40:5 | x | functions_test.py:39:9:39:9 | empty mutable value | functions_test.py:40:5:40:5 | empty mutable value | $@ flows to here and is mutated. | functions_test.py:39:9:39:9 | x | Default value |
| functions_test.py:134:5:134:5 | x | functions_test.py:133:15:133:15 | empty mutable value | functions_test.py:134:5:134:5 | empty mutable value | $@ flows to here and is mutated. | functions_test.py:133:15:133:15 | x | Default value |
| functions_test.py:152:5:152:5 | x | functions_test.py:157:27:157:27 | empty mutable value | functions_test.py:152:5:152:5 | empty mutable value | $@ flows to here and is mutated. | functions_test.py:157:27:157:27 | y | Default value |
| functions_test.py:155:5:155:5 | x | functions_test.py:157:27:157:27 | empty mutable value | functions_test.py:155:5:155:5 | empty mutable value | $@ flows to here and is mutated. | functions_test.py:157:27:157:27 | y | Default value |
| functions_test.py:179:9:179:9 | x | functions_test.py:188:18:188:18 | non-empty mutable value | functions_test.py:179:9:179:9 | non-empty mutable value | $@ flows to here and is mutated. | functions_test.py:188:18:188:18 | x | Default value |
| functions_test.py:179:9:179:9 | x | functions_test.py:191:18:191:18 | non-empty mutable value | functions_test.py:179:9:179:9 | non-empty mutable value | $@ flows to here and is mutated. | functions_test.py:191:18:191:18 | x | Default value |
| functions_test.py:181:9:181:9 | x | functions_test.py:188:18:188:18 | non-empty mutable value | functions_test.py:181:9:181:9 | non-empty mutable value | $@ flows to here and is mutated. | functions_test.py:188:18:188:18 | x | Default value |
| functions_test.py:181:9:181:9 | x | functions_test.py:191:18:191:18 | non-empty mutable value | functions_test.py:181:9:181:9 | non-empty mutable value | $@ flows to here and is mutated. | functions_test.py:191:18:191:18 | x | Default value |
| functions_test.py:40:5:40:5 | ControlFlowNode for x | functions_test.py:39:9:39:9 | ControlFlowNode for x | functions_test.py:40:5:40:5 | ControlFlowNode for x | $@ flows to here and is mutated. | functions_test.py:39:9:39:9 | ControlFlowNode for x | Default value |
| functions_test.py:134:5:134:5 | ControlFlowNode for x | functions_test.py:133:15:133:15 | ControlFlowNode for x | functions_test.py:134:5:134:5 | ControlFlowNode for x | $@ flows to here and is mutated. | functions_test.py:133:15:133:15 | ControlFlowNode for x | Default value |
| functions_test.py:152:5:152:5 | ControlFlowNode for x | functions_test.py:157:27:157:27 | ControlFlowNode for y | functions_test.py:152:5:152:5 | ControlFlowNode for x | $@ flows to here and is mutated. | functions_test.py:157:27:157:27 | ControlFlowNode for y | Default value |
| functions_test.py:155:5:155:5 | ControlFlowNode for x | functions_test.py:157:27:157:27 | ControlFlowNode for y | functions_test.py:155:5:155:5 | ControlFlowNode for x | $@ flows to here and is mutated. | functions_test.py:157:27:157:27 | ControlFlowNode for y | Default value |
| functions_test.py:170:9:170:13 | ControlFlowNode for param | functions_test.py:166:21:166:25 | ControlFlowNode for param | functions_test.py:170:9:170:13 | ControlFlowNode for param | $@ flows to here and is mutated. | functions_test.py:166:21:166:25 | ControlFlowNode for param | Default value |
| functions_test.py:170:9:170:13 | ControlFlowNode for param | functions_test.py:166:21:166:25 | ControlFlowNode for param | functions_test.py:170:9:170:13 | ControlFlowNode for param | $@ flows to here and is mutated. | functions_test.py:166:21:166:25 | ControlFlowNode for param | Default value |
| functions_test.py:179:9:179:9 | ControlFlowNode for x | functions_test.py:188:18:188:18 | ControlFlowNode for x | functions_test.py:179:9:179:9 | ControlFlowNode for x | $@ flows to here and is mutated. | functions_test.py:188:18:188:18 | ControlFlowNode for x | Default value |
| functions_test.py:179:9:179:9 | ControlFlowNode for x | functions_test.py:191:18:191:18 | ControlFlowNode for x | functions_test.py:179:9:179:9 | ControlFlowNode for x | $@ flows to here and is mutated. | functions_test.py:191:18:191:18 | ControlFlowNode for x | Default value |
| functions_test.py:181:9:181:9 | ControlFlowNode for x | functions_test.py:188:18:188:18 | ControlFlowNode for x | functions_test.py:181:9:181:9 | ControlFlowNode for x | $@ flows to here and is mutated. | functions_test.py:188:18:188:18 | ControlFlowNode for x | Default value |
| functions_test.py:181:9:181:9 | ControlFlowNode for x | functions_test.py:191:18:191:18 | ControlFlowNode for x | functions_test.py:181:9:181:9 | ControlFlowNode for x | $@ flows to here and is mutated. | functions_test.py:191:18:191:18 | ControlFlowNode for x | Default value |