Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 543876f

Browse files
committed
Python: Fix getAGuardedNode
1 parent 0eb8b6c commit 543876f

6 files changed

Lines changed: 62 additions & 11 deletions

File tree

python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ module EssaFlow {
130130
}
131131

132132
predicate useToNextUse(NameNode nodeFrom, NameNode nodeTo) {
133-
AdjacentUses::adjacentUseUseSameVar(nodeFrom, nodeTo)
133+
AdjacentUses::adjacentUseUse(nodeFrom, nodeTo)
134134
}
135135

136136
predicate defToFirstUse(EssaVariable var, NameNode nodeTo) {

python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
private import python
66
private import DataFlowPrivate
77
import experimental.dataflow.TypeTracker
8+
private import semmle.python.essa.SsaCompute
89

910
/**
1011
* IPA type for data flow nodes.
@@ -176,10 +177,10 @@ class BarrierGuard extends GuardNode {
176177

177178
/** Gets a node guarded by this guard. */
178179
final ExprNode getAGuardedNode() {
179-
exists(Variable v, NameNode n, boolean testIsTrue |
180-
n.uses(v) and
181-
this.checks(n, testIsTrue) and
182-
result.asCfgNode().(NameNode).uses(v) and
180+
exists(EssaDefinition def, ControlFlowNode node, boolean testIsTrue |
181+
AdjacentUses::aUse(def, node) and
182+
this.checks(node, testIsTrue) and
183+
AdjacentUses::aUse(def, result.asCfgNode()) and
183184
this.controlsNode(result.asCfgNode(), testIsTrue)
184185
)
185186
}

python/ql/src/semmle/python/essa/SsaCompute.qll

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,9 +443,28 @@ private module SsaComputeImpl {
443443
)
444444
}
445445

446+
/**
447+
* Holds if `use1` and `use2` form an adjacent use-use-pair of the same
448+
* `SsaSourceVariable`, that is, the value read in `use1` can reach `use2`
449+
* without passing through any other use or any SSA definition of the variable
450+
* except for phi nodes.
451+
*/
452+
cached
453+
predicate adjacentUseUse(ControlFlowNode use1, ControlFlowNode use2) {
454+
adjacentUseUseSameVar(use1, use2)
455+
or
456+
exists(SsaSourceVariable v, EssaDefinition def, BasicBlock b1, int i1, BasicBlock b2, int i2 |
457+
adjacentVarRefs(v, b1, i1, b2, i2) and
458+
variableUse(v, use1, b1, i1) and
459+
definesAt(def, v, b2, i2) and
460+
firstUse(def, use2) and
461+
def instanceof PhiFunction
462+
)
463+
}
464+
446465
/**
447466
* Holds if the value defined at `def` can reach `use` without passing through
448-
* any other uses, but possibly through phi nodes and uncertain implicit updates.
467+
* any other uses, but possibly through phi nodes.
449468
*/
450469
cached
451470
predicate firstUse(EssaDefinition def, ControlFlowNode use) {
@@ -482,6 +501,19 @@ private module SsaComputeImpl {
482501
b = def.(PhiFunction).getBasicBlock() and
483502
i = -1
484503
}
504+
505+
/**
506+
* Holds if the value defined at `def` can reach `use`, possibly through phi nodes.
507+
*/
508+
cached
509+
predicate aUse(EssaDefinition def, ControlFlowNode use) {
510+
firstUse(def, use)
511+
or
512+
exists(ControlFlowNode firstUse |
513+
firstUse(def, firstUse) and
514+
adjacentUseUse(firstUse, use)
515+
)
516+
}
485517
}
486518
}
487519

python/ql/test/experimental/dataflow/tainttracking/customSanitizer/TestTaint.expected

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,24 @@ test_taint
22
| test.py:22 | ok | test_custom_sanitizer | s |
33
| test.py:36 | ok | test_custom_sanitizer_guard | s |
44
| test.py:38 | ok | test_custom_sanitizer_guard | s |
5-
| test.py:49 | ok | test_escape | s2 |
5+
| test.py:40 | ok | test_custom_sanitizer_guard | s |
6+
| test.py:51 | ok | test_escape | s2 |
67
isSanitizer
78
| TestTaintTrackingConfiguration | test.py:21:39:21:39 | ControlFlowNode for s |
8-
| TestTaintTrackingConfiguration | test.py:48:10:48:29 | ControlFlowNode for emulated_escaping() |
9+
| TestTaintTrackingConfiguration | test.py:50:10:50:29 | ControlFlowNode for emulated_escaping() |
910
isSanitizerGuard
1011
| TestTaintTrackingConfiguration | test.py:35:8:35:26 | ControlFlowNode for emulated_is_safe() |
1112
sanitizerGuardControls
1213
| TestTaintTrackingConfiguration | test.py:35:8:35:26 | ControlFlowNode for emulated_is_safe() | test.py:36:9:36:26 | ControlFlowNode for ensure_not_tainted | true |
1314
| TestTaintTrackingConfiguration | test.py:35:8:35:26 | ControlFlowNode for emulated_is_safe() | test.py:36:9:36:29 | ControlFlowNode for ensure_not_tainted() | true |
1415
| TestTaintTrackingConfiguration | test.py:35:8:35:26 | ControlFlowNode for emulated_is_safe() | test.py:36:28:36:28 | ControlFlowNode for s | true |
15-
| TestTaintTrackingConfiguration | test.py:35:8:35:26 | ControlFlowNode for emulated_is_safe() | test.py:38:9:38:22 | ControlFlowNode for ensure_tainted | false |
16-
| TestTaintTrackingConfiguration | test.py:35:8:35:26 | ControlFlowNode for emulated_is_safe() | test.py:38:9:38:25 | ControlFlowNode for ensure_tainted() | false |
17-
| TestTaintTrackingConfiguration | test.py:35:8:35:26 | ControlFlowNode for emulated_is_safe() | test.py:38:24:38:24 | ControlFlowNode for s | false |
16+
| TestTaintTrackingConfiguration | test.py:35:8:35:26 | ControlFlowNode for emulated_is_safe() | test.py:37:9:37:9 | ControlFlowNode for s | true |
17+
| TestTaintTrackingConfiguration | test.py:35:8:35:26 | ControlFlowNode for emulated_is_safe() | test.py:37:13:37:26 | ControlFlowNode for TAINTED_STRING | true |
18+
| TestTaintTrackingConfiguration | test.py:35:8:35:26 | ControlFlowNode for emulated_is_safe() | test.py:38:9:38:22 | ControlFlowNode for ensure_tainted | true |
19+
| TestTaintTrackingConfiguration | test.py:35:8:35:26 | ControlFlowNode for emulated_is_safe() | test.py:38:9:38:25 | ControlFlowNode for ensure_tainted() | true |
20+
| TestTaintTrackingConfiguration | test.py:35:8:35:26 | ControlFlowNode for emulated_is_safe() | test.py:38:24:38:24 | ControlFlowNode for s | true |
21+
| TestTaintTrackingConfiguration | test.py:35:8:35:26 | ControlFlowNode for emulated_is_safe() | test.py:40:9:40:22 | ControlFlowNode for ensure_tainted | false |
22+
| TestTaintTrackingConfiguration | test.py:35:8:35:26 | ControlFlowNode for emulated_is_safe() | test.py:40:9:40:25 | ControlFlowNode for ensure_tainted() | false |
23+
| TestTaintTrackingConfiguration | test.py:35:8:35:26 | ControlFlowNode for emulated_is_safe() | test.py:40:24:40:24 | ControlFlowNode for s | false |
24+
sanitizerGuardedNode
25+
| TestTaintTrackingConfiguration | test.py:35:8:35:26 | ControlFlowNode for emulated_is_safe() | test.py:36:28:36:28 | ControlFlowNode for s |

python/ql/test/experimental/dataflow/tainttracking/customSanitizer/TestTaint.ql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,11 @@ query predicate sanitizerGuardControls(
4040
conf.isSanitizerGuard(guard) and
4141
guard.controlsNode(node, testIsTrue)
4242
}
43+
44+
query predicate sanitizerGuardedNode(
45+
TestTaintTrackingConfiguration conf, DataFlow::BarrierGuard guard, DataFlow::ExprNode node
46+
) {
47+
exists(guard.getLocation().getFile().getRelativePath()) and
48+
conf.isSanitizerGuard(guard) and
49+
node = guard.getAGuardedNode()
50+
}

python/ql/test/experimental/dataflow/tainttracking/customSanitizer/test.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ def test_custom_sanitizer_guard():
3434

3535
if emulated_is_safe(s):
3636
ensure_not_tainted(s)
37+
s = TAINTED_STRING
38+
ensure_tainted(s)
3739
else:
3840
ensure_tainted(s)
3941

0 commit comments

Comments
 (0)