Skip to content

Commit 10be273

Browse files
authored
Python: Get rid of _attr predicates
Also changes all `CfgNode`s representing calls to `CallCfgNode`s.
1 parent 720fbaf commit 10be273

File tree

1 file changed

+32
-126
lines changed

1 file changed

+32
-126
lines changed

python/ql/src/semmle/python/frameworks/Stdlib.qll

Lines changed: 32 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,15 @@ private module Stdlib {
1919
/** Gets a reference to the `os` module. */
2020
API::Node os() { result = API::moduleImport("os") }
2121

22-
/**
23-
* Gets a reference to the attribute `attr_name` of the `os` module.
24-
* WARNING: Only holds for a few predefined attributes.
25-
*
26-
* For example, using `"system"` will get all uses of `os.system`.
27-
*/
28-
private API::Node os_attr(string attr_name) { result = os().getMember(attr_name) }
29-
3022
/** Provides models for the `os` module. */
3123
module os {
3224
/** Gets a reference to the `os.path` module. */
33-
API::Node path() { result = os_attr("path") }
25+
API::Node path() { result = os().getMember("path") }
3426

3527
/** Provides models for the `os.path` module */
3628
module path {
37-
/**
38-
* Gets a reference to the attribute `attr_name` of the `os.path` module.
39-
* WARNING: Only holds for a few predefined attributes.
40-
*
41-
* For example, using `attr_name = "join"` will get all uses of `os.path.join`.
42-
*/
43-
API::Node path_attr(string attr_name) { result = path().getMember(attr_name) }
44-
4529
/** Gets a reference to the `os.path.join` function. */
46-
API::Node join() { result = path_attr("join") }
30+
API::Node join() { result = path().getMember("join") }
4731
}
4832
}
4933

@@ -52,7 +36,7 @@ private module Stdlib {
5236
* See https://docs.python.org/3/library/os.path.html#os.path.normpath
5337
*/
5438
private class OsPathNormpathCall extends Path::PathNormalization::Range, DataFlow::CallCfgNode {
55-
OsPathNormpathCall() { this = os::path::path_attr("normpath").getACall() }
39+
OsPathNormpathCall() { this = os::path().getMember("normpath").getACall() }
5640

5741
DataFlow::Node getPathArg() {
5842
result.asCfgNode() in [node.getArg(0), node.getArgByName("path")]
@@ -73,10 +57,8 @@ private module Stdlib {
7357
* A call to `os.path.abspath`.
7458
* See https://docs.python.org/3/library/os.path.html#os.path.abspath
7559
*/
76-
private class OsPathAbspathCall extends Path::PathNormalization::Range, DataFlow::CfgNode {
77-
override CallNode node;
78-
79-
OsPathAbspathCall() { this = os::path::path_attr("abspath").getACall() }
60+
private class OsPathAbspathCall extends Path::PathNormalization::Range, DataFlow::CallCfgNode {
61+
OsPathAbspathCall() { this = os::path().getMember("abspath").getACall() }
8062

8163
DataFlow::Node getPathArg() {
8264
result.asCfgNode() in [node.getArg(0), node.getArgByName("path")]
@@ -97,10 +79,8 @@ private module Stdlib {
9779
* A call to `os.path.realpath`.
9880
* See https://docs.python.org/3/library/os.path.html#os.path.realpath
9981
*/
100-
private class OsPathRealpathCall extends Path::PathNormalization::Range, DataFlow::CfgNode {
101-
override CallNode node;
102-
103-
OsPathRealpathCall() { this = os::path::path_attr("realpath").getACall() }
82+
private class OsPathRealpathCall extends Path::PathNormalization::Range, DataFlow::CallCfgNode {
83+
OsPathRealpathCall() { this = os::path().getMember("realpath").getACall() }
10484

10585
DataFlow::Node getPathArg() {
10686
result.asCfgNode() in [node.getArg(0), node.getArgByName("path")]
@@ -121,10 +101,8 @@ private module Stdlib {
121101
* A call to `os.system`.
122102
* See https://docs.python.org/3/library/os.html#os.system
123103
*/
124-
private class OsSystemCall extends SystemCommandExecution::Range, DataFlow::CfgNode {
125-
override CallNode node;
126-
127-
OsSystemCall() { this = os_attr("system").getACall() }
104+
private class OsSystemCall extends SystemCommandExecution::Range, DataFlow::CallCfgNode {
105+
OsSystemCall() { this = os().getMember("system").getACall() }
128106

129107
override DataFlow::Node getCommand() { result.asCfgNode() = node.getArg(0) }
130108
}
@@ -137,13 +115,12 @@ private module Stdlib {
137115
* Although deprecated since version 2.6, they still work in 2.7.
138116
* See https://docs.python.org/2.7/library/os.html#os.popen2
139117
*/
140-
private class OsPopenCall extends SystemCommandExecution::Range, DataFlow::CfgNode {
141-
override CallNode node;
118+
private class OsPopenCall extends SystemCommandExecution::Range, DataFlow::CallCfgNode {
142119
string name;
143120

144121
OsPopenCall() {
145122
name in ["popen", "popen2", "popen3", "popen4"] and
146-
this = os_attr(name).getACall()
123+
this = os().getMember(name).getACall()
147124
}
148125

149126
override DataFlow::Node getCommand() {
@@ -158,13 +135,11 @@ private module Stdlib {
158135
* A call to any of the `os.exec*` functions
159136
* See https://docs.python.org/3.8/library/os.html#os.execl
160137
*/
161-
private class OsExecCall extends SystemCommandExecution::Range, DataFlow::CfgNode {
162-
override CallNode node;
163-
138+
private class OsExecCall extends SystemCommandExecution::Range, DataFlow::CallCfgNode {
164139
OsExecCall() {
165140
exists(string name |
166141
name in ["execl", "execle", "execlp", "execlpe", "execv", "execve", "execvp", "execvpe"] and
167-
this = os_attr(name).getACall()
142+
this = os().getMember(name).getACall()
168143
)
169144
}
170145

@@ -175,15 +150,13 @@ private module Stdlib {
175150
* A call to any of the `os.spawn*` functions
176151
* See https://docs.python.org/3.8/library/os.html#os.spawnl
177152
*/
178-
private class OsSpawnCall extends SystemCommandExecution::Range, DataFlow::CfgNode {
179-
override CallNode node;
180-
153+
private class OsSpawnCall extends SystemCommandExecution::Range, DataFlow::CallCfgNode {
181154
OsSpawnCall() {
182155
exists(string name |
183156
name in [
184157
"spawnl", "spawnle", "spawnlp", "spawnlpe", "spawnv", "spawnve", "spawnvp", "spawnvpe"
185158
] and
186-
this = os_attr(name).getACall()
159+
this = os().getMember(name).getACall()
187160
)
188161
}
189162

@@ -194,10 +167,8 @@ private module Stdlib {
194167
* A call to any of the `os.posix_spawn*` functions
195168
* See https://docs.python.org/3.8/library/os.html#os.posix_spawn
196169
*/
197-
private class OsPosixSpawnCall extends SystemCommandExecution::Range, DataFlow::CfgNode {
198-
override CallNode node;
199-
200-
OsPosixSpawnCall() { this = os_attr(["posix_spawn", "posix_spawnp"]).getACall() }
170+
private class OsPosixSpawnCall extends SystemCommandExecution::Range, DataFlow::CallCfgNode {
171+
OsPosixSpawnCall() { this = os().getMember(["posix_spawn", "posix_spawnp"]).getACall() }
201172

202173
override DataFlow::Node getCommand() { result.asCfgNode() = node.getArg(0) }
203174
}
@@ -218,29 +189,17 @@ private module Stdlib {
218189
// subprocess
219190
// ---------------------------------------------------------------------------
220191
/** Gets a reference to the `subprocess` module. */
221-
deprecated DataFlow::Node subprocess() { result = API::moduleImport("subprocess").getAUse() }
222-
223-
/**
224-
* Gets a reference to the attribute `attr_name` of the `subprocess` module.
225-
* WARNING: Only holds for a few predefined attributes.
226-
*
227-
* For example, using `attr_name = "Popen"` will get all uses of `subprocess.Popen`.
228-
*/
229-
private DataFlow::Node subprocess_attr(string attr_name) {
230-
result = API::moduleImport("subprocess").getMember(attr_name).getAUse()
231-
}
192+
API::Node subprocess() { result = API::moduleImport("subprocess") }
232193

233194
/**
234195
* A call to `subprocess.Popen` or helper functions (call, check_call, check_output, run)
235196
* See https://docs.python.org/3.8/library/subprocess.html#subprocess.Popen
236197
*/
237-
private class SubprocessPopenCall extends SystemCommandExecution::Range, DataFlow::CfgNode {
238-
override CallNode node;
239-
198+
private class SubprocessPopenCall extends SystemCommandExecution::Range, DataFlow::CallCfgNode {
240199
SubprocessPopenCall() {
241200
exists(string name |
242201
name in ["Popen", "call", "check_call", "check_output", "run"] and
243-
node.getFunction() = subprocess_attr(name).asCfgNode()
202+
this = subprocess().getMember(name).getACall()
244203
)
245204
}
246205

@@ -311,17 +270,6 @@ private module Stdlib {
311270
// ---------------------------------------------------------------------------
312271
// marshal
313272
// ---------------------------------------------------------------------------
314-
/** Gets a reference to the `marshal` module. */
315-
deprecated DataFlow::Node marshal() { result = API::moduleImport("marshal").getAUse() }
316-
317-
/** Provides models for the `marshal` module. */
318-
module marshal {
319-
/** Gets a reference to the `marshal.loads` function. */
320-
deprecated DataFlow::Node loads() {
321-
result = API::moduleImport("marshal").getMember("loads").getAUse()
322-
}
323-
}
324-
325273
/**
326274
* A call to `marshal.loads`
327275
* See https://docs.python.org/3/library/marshal.html#marshal.loads
@@ -342,9 +290,7 @@ private module Stdlib {
342290
// pickle
343291
// ---------------------------------------------------------------------------
344292
/** Gets a reference to the `pickle` module. */
345-
DataFlow::Node pickle() {
346-
result = API::moduleImport(["pickle", "cPickle", "_pickle"]).getAUse()
347-
}
293+
DataFlow::Node pickle() { result = API::moduleImport(["pickle", "cPickle", "_pickle"]).getAUse() }
348294

349295
/** Provides models for the `pickle` module. */
350296
module pickle {
@@ -376,25 +322,15 @@ private module Stdlib {
376322
/** Gets a reference to the `popen2` module (only available in Python 2). */
377323
API::Node popen2() { result = API::moduleImport("popen2") }
378324

379-
/**
380-
* Gets a reference to the attribute `attr_name` of the `popen2` module.
381-
* WARNING: Only holds for a few predefined attributes.
382-
*/
383-
private API::Node popen2_attr(string attr_name) {
384-
result = API::moduleImport("popen2").getMember(attr_name)
385-
}
386-
387325
/**
388326
* A call to any of the `popen.popen*` functions, or instantiation of a `popen.Popen*` class.
389327
* See https://docs.python.org/2.7/library/popen2.html
390328
*/
391-
private class Popen2PopenCall extends SystemCommandExecution::Range, DataFlow::CfgNode {
392-
override CallNode node;
393-
329+
private class Popen2PopenCall extends SystemCommandExecution::Range, DataFlow::CallCfgNode {
394330
Popen2PopenCall() {
395331
exists(string name |
396332
name in ["popen2", "popen3", "popen4", "Popen3", "Popen4"] and
397-
this = popen2_attr(name).getACall()
333+
this = popen2().getMember(name).getACall()
398334
)
399335
}
400336

@@ -409,18 +345,12 @@ private module Stdlib {
409345
/** Gets a reference to the `platform` module. */
410346
API::Node platform() { result = API::moduleImport("platform") }
411347

412-
/**
413-
* Gets a reference to the attribute `attr_name` of the `platform` module.
414-
* WARNING: Only holds for a few predefined attributes.
415-
*/
416-
private API::Node platform_attr(string attr_name) { result = platform().getMember(attr_name) }
417-
418348
/**
419349
* A call to the `platform.popen` function.
420350
* See https://docs.python.org/2.7/library/platform.html#platform.popen
421351
*/
422352
private class PlatformPopenCall extends SystemCommandExecution::Range, DataFlow::CallCfgNode {
423-
PlatformPopenCall() { this = platform_attr("popen").getACall() }
353+
PlatformPopenCall() { this = platform().getMember("popen").getACall() }
424354

425355
override DataFlow::Node getCommand() {
426356
result.asCfgNode() in [node.getArg(0), node.getArgByName("cmd")]
@@ -500,12 +430,6 @@ private module Stdlib {
500430
/** Gets a reference to the `base64` module. */
501431
API::Node base64() { result = API::moduleImport("base64") }
502432

503-
/**
504-
* Gets a reference to the attribute `attr_name` of the `base64` module.
505-
* WARNING: Only holds for a few predefined attributes.
506-
*/
507-
private API::Node base64_attr(string attr_name) { result = base64().getMember(attr_name) }
508-
509433
/** A call to any of the encode functions in the `base64` module. */
510434
private class Base64EncodeCall extends Encoding::Range, DataFlow::CallCfgNode {
511435
string name;
@@ -515,7 +439,7 @@ private module Stdlib {
515439
"b64encode", "standard_b64encode", "urlsafe_b64encode", "b32encode", "b16encode",
516440
"encodestring", "a85encode", "b85encode", "encodebytes"
517441
] and
518-
this = base64_attr(name).getACall()
442+
this = base64().getMember(name).getACall()
519443
}
520444

521445
override DataFlow::Node getAnInput() { result.asCfgNode() = node.getArg(0) }
@@ -547,7 +471,7 @@ private module Stdlib {
547471
"b64decode", "standard_b64decode", "urlsafe_b64decode", "b32decode", "b16decode",
548472
"decodestring", "a85decode", "b85decode", "decodebytes"
549473
] and
550-
this = base64_attr(name).getACall()
474+
this = base64().getMember(name).getACall()
551475
}
552476

553477
override predicate mayExecuteInput() { none() }
@@ -578,18 +502,12 @@ private module Stdlib {
578502
/** Gets a reference to the `json` module. */
579503
API::Node json() { result = API::moduleImport("json") }
580504

581-
/**
582-
* Gets a reference to the attribute `attr_name` of the `json` module.
583-
* WARNING: Only holds for a few predefined attributes.
584-
*/
585-
private API::Node json_attr(string attr_name) { result = json().getMember(attr_name) }
586-
587505
/**
588506
* A call to `json.loads`
589507
* See https://docs.python.org/3/library/json.html#json.loads
590508
*/
591509
private class JsonLoadsCall extends Decoding::Range, DataFlow::CallCfgNode {
592-
JsonLoadsCall() { this = json_attr("loads").getACall() }
510+
JsonLoadsCall() { this = json().getMember("loads").getACall() }
593511

594512
override predicate mayExecuteInput() { none() }
595513

@@ -605,7 +523,7 @@ private module Stdlib {
605523
* See https://docs.python.org/3/library/json.html#json.dumps
606524
*/
607525
private class JsonDumpsCall extends Encoding::Range, DataFlow::CallCfgNode {
608-
JsonDumpsCall() { this = json_attr("dumps").getACall() }
526+
JsonDumpsCall() { this = json().getMember("dumps").getACall() }
609527

610528
override DataFlow::Node getAnInput() { result.asCfgNode() = node.getArg(0) }
611529

@@ -799,36 +717,24 @@ private module Stdlib {
799717
/** Gets a reference to the `http` module. */
800718
API::Node http() { result = API::moduleImport("http") }
801719

802-
/**
803-
* Gets a reference to the attribute `attr_name` of the `http` module.
804-
* WARNING: Only holds for a few predefined attributes.
805-
*/
806-
private API::Node http_attr(string attr_name) { result = http().getMember(attr_name) }
807-
808720
/** Provides models for the `http` module. */
809721
module http {
810722
// -------------------------------------------------------------------------
811723
// http.server
812724
// -------------------------------------------------------------------------
813725
/** Gets a reference to the `http.server` module. */
814-
API::Node server() { result = http_attr("server") }
726+
API::Node server() { result = http().getMember("server") }
815727

816728
/** Provides models for the `http.server` module */
817729
module server {
818-
/**
819-
* Gets a reference to the attribute `attr_name` of the `http.server` module.
820-
* WARNING: Only holds for a few predefined attributes.
821-
*/
822-
private API::Node server_attr(string attr_name) { result = server().getMember(attr_name) }
823-
824730
/**
825731
* Provides models for the `http.server.BaseHTTPRequestHandler` class (Python 3 only).
826732
*
827733
* See https://docs.python.org/3.9/library/http.server.html#http.server.BaseHTTPRequestHandler.
828734
*/
829735
module BaseHTTPRequestHandler {
830736
/** Gets a reference to the `http.server.BaseHTTPRequestHandler` class. */
831-
API::Node classRef() { result = server_attr("BaseHTTPRequestHandler") }
737+
API::Node classRef() { result = server().getMember("BaseHTTPRequestHandler") }
832738
}
833739

834740
/**
@@ -838,7 +744,7 @@ private module Stdlib {
838744
*/
839745
module SimpleHTTPRequestHandler {
840746
/** Gets a reference to the `http.server.SimpleHTTPRequestHandler` class. */
841-
API::Node classRef() { result = server_attr("SimpleHTTPRequestHandler") }
747+
API::Node classRef() { result = server().getMember("SimpleHTTPRequestHandler") }
842748
}
843749

844750
/**
@@ -848,7 +754,7 @@ private module Stdlib {
848754
*/
849755
module CGIHTTPRequestHandler {
850756
/** Gets a reference to the `http.server.CGIHTTPRequestHandler` class. */
851-
API::Node classRef() { result = server_attr("CGIHTTPRequestHandler") }
757+
API::Node classRef() { result = server().getMember("CGIHTTPRequestHandler") }
852758
}
853759
}
854760
}

0 commit comments

Comments
 (0)