Skip to content

Commit 2b0a809

Browse files
committed
Python: implement Fuzzy for Python
1 parent f1c82b6 commit 2b0a809

File tree

4 files changed

+46
-0
lines changed

4 files changed

+46
-0
lines changed

python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsSpecific.qll

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,23 @@ API::Node getExtraSuccessorFromInvoke(API::CallNode node, AccessPathToken token)
108108
)
109109
}
110110

111+
pragma[inline]
112+
API::Node getAFuzzySuccessor(API::Node node) {
113+
result = node.getAMember()
114+
or
115+
result = node.getParameter(_)
116+
or
117+
result = node.getKeywordParameter(_)
118+
or
119+
result = node.getReturn()
120+
or
121+
result = node.getASubscript()
122+
or
123+
result = node.getAwaited()
124+
or
125+
result = node.getASubclass()
126+
}
127+
111128
/**
112129
* Holds if `invoke` matches the PY-specific call site filter in `token`.
113130
*/

python/ql/test/library-tests/frameworks/data/test.expected

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ taintFlow
1111
| test.py:83:50:83:60 | ControlFlowNode for getSource() | test.py:83:8:83:61 | ControlFlowNode for Attribute() |
1212
| test.py:86:49:86:59 | ControlFlowNode for getSource() | test.py:86:8:86:60 | ControlFlowNode for Attribute() |
1313
| test.py:87:56:87:66 | ControlFlowNode for getSource() | test.py:87:8:87:67 | ControlFlowNode for Attribute() |
14+
| test.py:114:19:114:29 | ControlFlowNode for getSource() | test.py:114:19:114:29 | ControlFlowNode for getSource() |
15+
| test.py:115:20:115:30 | ControlFlowNode for getSource() | test.py:115:20:115:30 | ControlFlowNode for getSource() |
16+
| test.py:116:31:116:41 | ControlFlowNode for getSource() | test.py:116:31:116:41 | ControlFlowNode for getSource() |
17+
| test.py:117:31:117:41 | ControlFlowNode for getSource() | test.py:117:31:117:41 | ControlFlowNode for getSource() |
18+
| test.py:118:35:118:45 | ControlFlowNode for getSource() | test.py:118:35:118:45 | ControlFlowNode for getSource() |
1419
isSink
1520
| test.py:4:8:4:8 | ControlFlowNode for x | test-sink |
1621
| test.py:7:17:7:17 | ControlFlowNode for x | test-sink |
@@ -50,6 +55,11 @@ isSink
5055
| test.py:91:21:91:23 | ControlFlowNode for one | test-sink |
5156
| test.py:91:30:91:32 | ControlFlowNode for two | test-sink |
5257
| test.py:98:6:98:9 | ControlFlowNode for baz2 | test-sink |
58+
| test.py:114:19:114:29 | ControlFlowNode for getSource() | test-sink |
59+
| test.py:115:20:115:30 | ControlFlowNode for getSource() | test-sink |
60+
| test.py:116:31:116:41 | ControlFlowNode for getSource() | test-sink |
61+
| test.py:117:31:117:41 | ControlFlowNode for getSource() | test-sink |
62+
| test.py:118:35:118:45 | ControlFlowNode for getSource() | test-sink |
5363
isSource
5464
| test.py:3:5:3:15 | ControlFlowNode for getSource() | test-source |
5565
| test.py:9:8:9:14 | ControlFlowNode for alias() | test-source |
@@ -89,6 +99,12 @@ isSource
8999
| test.py:104:32:104:37 | ControlFlowNode for param2 | test-source |
90100
| test.py:107:24:107:28 | ControlFlowNode for name1 | test-source |
91101
| test.py:107:31:107:35 | ControlFlowNode for name2 | test-source |
102+
| test.py:114:19:114:29 | ControlFlowNode for getSource() | test-source |
103+
| test.py:115:20:115:30 | ControlFlowNode for getSource() | test-source |
104+
| test.py:116:31:116:41 | ControlFlowNode for getSource() | test-source |
105+
| test.py:117:31:117:41 | ControlFlowNode for getSource() | test-source |
106+
| test.py:118:35:118:45 | ControlFlowNode for getSource() | test-source |
107+
| test.py:119:20:119:30 | ControlFlowNode for getSource() | test-source |
92108
syntaxErrors
93109
| Member[foo |
94110
| Member[foo] .Member[bar] |

python/ql/test/library-tests/frameworks/data/test.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,14 @@ def anyParam(self, param1, param2): # Parameter[any] matches all non-self parame
106106

107107
def anyNamed(self, name1, name2=2): # Parameter[any-named] matches all non-self named parameters
108108
pass
109+
110+
import testlib as testlib
111+
import testlib.nestedlib as testlib2
112+
import otherlib as otherlib
113+
114+
testlib.fuzzyCall(getSource()) # NOT OK
115+
testlib2.fuzzyCall(getSource()) # NOT OK
116+
testlib.foo.bar.baz.fuzzyCall(getSource()) # NOT OK
117+
testlib.foo().bar().fuzzyCall(getSource()) # NOT OK
118+
testlib.foo(lambda x: x.fuzzyCall(getSource())) # NOT OK
119+
otherlib.fuzzyCall(getSource()) # OK

python/ql/test/library-tests/frameworks/data/test.ql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ class Sinks extends ModelInput::SinkModelCsv {
5151
// testing package syntax
5252
"foo1.bar;Member[baz1].Argument[any];test-sink", //
5353
"foo2;Member[bar].Member[baz2].Argument[any];test-sink", //
54+
// testing fuzzy
55+
"testlib;Fuzzy.Member[fuzzyCall].Argument[0];test-sink", //
5456
]
5557
}
5658
}

0 commit comments

Comments
 (0)