Skip to content

Commit 4e5afab

Browse files
committed
refactor more python type-trackers to API-graphs
1 parent 319ff35 commit 4e5afab

File tree

2 files changed

+28
-130
lines changed

2 files changed

+28
-130
lines changed

python/ql/lib/semmle/python/frameworks/Cryptography.qll

Lines changed: 21 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ private module CryptographyModel {
2222
* Gets a predefined curve class from
2323
* `cryptography.hazmat.primitives.asymmetric.ec` with a specific key size (in bits).
2424
*/
25-
private API::Node predefinedCurveClass(int keySize) {
25+
API::Node predefinedCurveClass(int keySize) {
2626
exists(string curveName |
2727
result =
2828
API::moduleImport("cryptography")
@@ -73,41 +73,6 @@ private module CryptographyModel {
7373
curveName = "BrainpoolP512R1" and keySize = 512
7474
)
7575
}
76-
77-
/** Gets a reference to a predefined curve class with a specific key size (in bits), as well as the origin of the class. */
78-
private DataFlow::TypeTrackingNode curveClassWithKeySize(
79-
DataFlow::TypeTracker t, int keySize, DataFlow::Node origin
80-
) {
81-
t.start() and
82-
result = predefinedCurveClass(keySize).getAnImmediateUse() and
83-
origin = result
84-
or
85-
exists(DataFlow::TypeTracker t2 |
86-
result = curveClassWithKeySize(t2, keySize, origin).track(t2, t)
87-
)
88-
}
89-
90-
/** Gets a reference to a predefined curve class with a specific key size (in bits), as well as the origin of the class. */
91-
DataFlow::Node curveClassWithKeySize(int keySize, DataFlow::Node origin) {
92-
curveClassWithKeySize(DataFlow::TypeTracker::end(), keySize, origin).flowsTo(result)
93-
}
94-
95-
/** Gets a reference to a predefined curve class instance with a specific key size (in bits), as well as the origin of the class. */
96-
private DataFlow::TypeTrackingNode curveClassInstanceWithKeySize(
97-
DataFlow::TypeTracker t, int keySize, DataFlow::Node origin
98-
) {
99-
t.start() and
100-
result.(DataFlow::CallCfgNode).getFunction() = curveClassWithKeySize(keySize, origin)
101-
or
102-
exists(DataFlow::TypeTracker t2 |
103-
result = curveClassInstanceWithKeySize(t2, keySize, origin).track(t2, t)
104-
)
105-
}
106-
107-
/** Gets a reference to a predefined curve class instance with a specific key size (in bits), as well as the origin of the class. */
108-
DataFlow::Node curveClassInstanceWithKeySize(int keySize, DataFlow::Node origin) {
109-
curveClassInstanceWithKeySize(DataFlow::TypeTracker::end(), keySize, origin).flowsTo(result)
110-
}
11176
}
11277

11378
// ---------------------------------------------------------------------------
@@ -179,9 +144,13 @@ private module CryptographyModel {
179144
DataFlow::Node getCurveArg() { result in [this.getArg(0), this.getArgByName("curve")] }
180145

181146
override int getKeySizeWithOrigin(DataFlow::Node origin) {
182-
this.getCurveArg() = Ecc::curveClassInstanceWithKeySize(result, origin)
183-
or
184-
this.getCurveArg() = Ecc::curveClassWithKeySize(result, origin)
147+
exists(API::Node n |
148+
n = Ecc::predefinedCurveClass(result) and origin = n.getAnImmediateUse()
149+
|
150+
this.getCurveArg() = n.getAUse()
151+
or
152+
this.getCurveArg() = n.getReturn().getAUse()
153+
)
185154
}
186155

187156
// Note: There is not really a key-size argument, since it's always specified by the curve.
@@ -202,9 +171,8 @@ private module CryptographyModel {
202171
}
203172

204173
/** Gets a reference to a Cipher instance using algorithm with `algorithmName`. */
205-
DataFlow::TypeTrackingNode cipherInstance(DataFlow::TypeTracker t, string algorithmName) {
206-
t.start() and
207-
exists(DataFlow::CallCfgNode call | result = call |
174+
API::Node cipherInstance(string algorithmName) {
175+
exists(API::CallNode call | result = call.getReturn() |
208176
call =
209177
API::moduleImport("cryptography")
210178
.getMember("hazmat")
@@ -216,47 +184,6 @@ private module CryptographyModel {
216184
call.getArg(0), call.getArgByName("algorithm")
217185
]
218186
)
219-
or
220-
exists(DataFlow::TypeTracker t2 | result = cipherInstance(t2, algorithmName).track(t2, t))
221-
}
222-
223-
/** Gets a reference to a Cipher instance using algorithm with `algorithmName`. */
224-
DataFlow::Node cipherInstance(string algorithmName) {
225-
cipherInstance(DataFlow::TypeTracker::end(), algorithmName).flowsTo(result)
226-
}
227-
228-
/** Gets a reference to the encryptor of a Cipher instance using algorithm with `algorithmName`. */
229-
DataFlow::TypeTrackingNode cipherEncryptor(DataFlow::TypeTracker t, string algorithmName) {
230-
t.start() and
231-
result.(DataFlow::MethodCallNode).calls(cipherInstance(algorithmName), "encryptor")
232-
or
233-
exists(DataFlow::TypeTracker t2 | result = cipherEncryptor(t2, algorithmName).track(t2, t))
234-
}
235-
236-
/**
237-
* Gets a reference to the encryptor of a Cipher instance using algorithm with `algorithmName`.
238-
*
239-
* You obtain an encryptor by using the `encryptor()` method on a Cipher instance.
240-
*/
241-
DataFlow::Node cipherEncryptor(string algorithmName) {
242-
cipherEncryptor(DataFlow::TypeTracker::end(), algorithmName).flowsTo(result)
243-
}
244-
245-
/** Gets a reference to the dncryptor of a Cipher instance using algorithm with `algorithmName`. */
246-
DataFlow::TypeTrackingNode cipherDecryptor(DataFlow::TypeTracker t, string algorithmName) {
247-
t.start() and
248-
result.(DataFlow::MethodCallNode).calls(cipherInstance(algorithmName), "decryptor")
249-
or
250-
exists(DataFlow::TypeTracker t2 | result = cipherDecryptor(t2, algorithmName).track(t2, t))
251-
}
252-
253-
/**
254-
* Gets a reference to the decryptor of a Cipher instance using algorithm with `algorithmName`.
255-
*
256-
* You obtain an decryptor by using the `decryptor()` method on a Cipher instance.
257-
*/
258-
DataFlow::Node cipherDecryptor(string algorithmName) {
259-
cipherDecryptor(DataFlow::TypeTracker::end(), algorithmName).flowsTo(result)
260187
}
261188

262189
/**
@@ -267,11 +194,12 @@ private module CryptographyModel {
267194
string algorithmName;
268195

269196
CryptographyGenericCipherOperation() {
270-
exists(DataFlow::Node object, string method |
271-
object in [cipherEncryptor(algorithmName), cipherDecryptor(algorithmName)] and
272-
method in ["update", "update_into"] and
273-
this.calls(object, method)
274-
)
197+
this =
198+
cipherInstance(algorithmName)
199+
.getMember(["decryptor", "encryptor"])
200+
.getReturn()
201+
.getMember(["update", "update_into"])
202+
.getACall()
275203
}
276204

277205
override Cryptography::CryptographicAlgorithm getAlgorithm() {
@@ -298,9 +226,8 @@ private module CryptographyModel {
298226
}
299227

300228
/** Gets a reference to a Hash instance using algorithm with `algorithmName`. */
301-
private DataFlow::TypeTrackingNode hashInstance(DataFlow::TypeTracker t, string algorithmName) {
302-
t.start() and
303-
exists(DataFlow::CallCfgNode call | result = call |
229+
private API::Node hashInstance(string algorithmName) {
230+
exists(API::CallNode call | result = call.getReturn() |
304231
call =
305232
API::moduleImport("cryptography")
306233
.getMember("hazmat")
@@ -312,13 +239,6 @@ private module CryptographyModel {
312239
call.getArg(0), call.getArgByName("algorithm")
313240
]
314241
)
315-
or
316-
exists(DataFlow::TypeTracker t2 | result = hashInstance(t2, algorithmName).track(t2, t))
317-
}
318-
319-
/** Gets a reference to a Hash instance using algorithm with `algorithmName`. */
320-
DataFlow::Node hashInstance(string algorithmName) {
321-
hashInstance(DataFlow::TypeTracker::end(), algorithmName).flowsTo(result)
322242
}
323243

324244
/**
@@ -328,7 +248,9 @@ private module CryptographyModel {
328248
DataFlow::MethodCallNode {
329249
string algorithmName;
330250

331-
CryptographyGenericHashOperation() { this.calls(hashInstance(algorithmName), "update") }
251+
CryptographyGenericHashOperation() {
252+
this = hashInstance(algorithmName).getMember("update").getACall()
253+
}
332254

333255
override Cryptography::CryptographicAlgorithm getAlgorithm() {
334256
result.matchesName(algorithmName)

python/ql/src/experimental/semmle/python/frameworks/Xml.qll

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ private module SaxBasedParsing {
119119
*
120120
* See https://docs.python.org/3.10/library/xml.sax.reader.html#xml.sax.xmlreader.XMLReader.setFeature
121121
*/
122-
class SaxParserSetFeatureCall extends DataFlow::MethodCallNode {
122+
class SaxParserSetFeatureCall extends API::CallNode, DataFlow::MethodCallNode {
123123
SaxParserSetFeatureCall() {
124124
this =
125125
API::moduleImport("xml")
@@ -132,27 +132,9 @@ private module SaxBasedParsing {
132132

133133
// The keyword argument names does not match documentation. I checked (with Python
134134
// 3.9.5) that the names used here actually works.
135-
DataFlow::Node getFeatureArg() { result in [this.getArg(0), this.getArgByName("name")] }
135+
API::Node getFeatureArg() { result = this.getParameter(0, "name") }
136136

137-
DataFlow::Node getStateArg() { result in [this.getArg(1), this.getArgByName("state")] }
138-
}
139-
140-
/** Gets a back-reference to the `setFeature` state argument `arg`. */
141-
private DataFlow::TypeTrackingNode saxParserSetFeatureStateArgBacktracker(
142-
DataFlow::TypeBackTracker t, DataFlow::Node arg
143-
) {
144-
t.start() and
145-
arg = any(SaxParserSetFeatureCall c).getStateArg() and
146-
result = arg.getALocalSource()
147-
or
148-
exists(DataFlow::TypeBackTracker t2 |
149-
result = saxParserSetFeatureStateArgBacktracker(t2, arg).backtrack(t2, t)
150-
)
151-
}
152-
153-
/** Gets a back-reference to the `setFeature` state argument `arg`. */
154-
DataFlow::LocalSourceNode saxParserSetFeatureStateArgBacktracker(DataFlow::Node arg) {
155-
result = saxParserSetFeatureStateArgBacktracker(DataFlow::TypeBackTracker::end(), arg)
137+
API::Node getStateArg() { result = this.getParameter(1, "state") }
156138
}
157139

158140
/**
@@ -163,16 +145,13 @@ private module SaxBasedParsing {
163145
private DataFlow::Node saxParserWithFeatureExternalGesTurnedOn(DataFlow::TypeTracker t) {
164146
t.start() and
165147
exists(SaxParserSetFeatureCall call |
166-
call.getFeatureArg() =
148+
call.getFeatureArg().getARhs() =
167149
API::moduleImport("xml")
168150
.getMember("sax")
169151
.getMember("handler")
170152
.getMember("feature_external_ges")
171153
.getAUse() and
172-
saxParserSetFeatureStateArgBacktracker(call.getStateArg())
173-
.asExpr()
174-
.(BooleanLiteral)
175-
.booleanValue() = true and
154+
call.getStateArg().getAValueReachingRhs().asExpr().(BooleanLiteral).booleanValue() = true and
176155
result = call.getObject()
177156
)
178157
or
@@ -182,16 +161,13 @@ private module SaxBasedParsing {
182161
// take account of that we can set the feature to False, which makes the parser safe again
183162
not exists(SaxParserSetFeatureCall call |
184163
call.getObject() = result and
185-
call.getFeatureArg() =
164+
call.getFeatureArg().getARhs() =
186165
API::moduleImport("xml")
187166
.getMember("sax")
188167
.getMember("handler")
189168
.getMember("feature_external_ges")
190169
.getAUse() and
191-
saxParserSetFeatureStateArgBacktracker(call.getStateArg())
192-
.asExpr()
193-
.(BooleanLiteral)
194-
.booleanValue() = false
170+
call.getStateArg().getAValueReachingRhs().asExpr().(BooleanLiteral).booleanValue() = false
195171
)
196172
}
197173

0 commit comments

Comments
 (0)