Skip to content

Commit d2d5cce

Browse files
committed
Python: Recognize keyword arguments for os.*spawn* calls
1 parent 1459043 commit d2d5cce

File tree

2 files changed

+14
-8
lines changed

2 files changed

+14
-8
lines changed

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,13 @@ private module StdlibPrivate {
492492
)
493493
}
494494

495-
override DataFlow::Node getCommand() { result = this.getArg(1) }
495+
override DataFlow::Node getCommand() {
496+
result = this.getArg(1)
497+
or
498+
// `file` keyword argument only valid for the `v` variants, but this
499+
// over-approximation is not hurting anyone, and is easy to implement.
500+
result = this.getArgByName("file")
501+
}
496502
}
497503

498504
/**
@@ -502,7 +508,7 @@ private module StdlibPrivate {
502508
private class OsPosixSpawnCall extends SystemCommandExecution::Range, DataFlow::CallCfgNode {
503509
OsPosixSpawnCall() { this = os().getMember(["posix_spawn", "posix_spawnp"]).getACall() }
504510

505-
override DataFlow::Node getCommand() { result = this.getArg(0) }
511+
override DataFlow::Node getCommand() { result in [this.getArg(0), this.getArgByName("path")] }
506512
}
507513

508514
/** An additional taint step for calls to `os.path.join` */

python/ql/test/library-tests/frameworks/stdlib/SystemCommandExecution.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,17 +69,17 @@ def os_members():
6969
# unlike os.exec*, some os.spawn* functions is usable with keyword arguments. However,
7070
# despite the docs using both `file` and `path` as the parameter name, you actually need
7171
# to use `file` in all cases.
72-
os.spawnv(mode=os.P_WAIT, file="path", args=["<progname>", "arg0"]) # $ MISSING: getCommand="path" getAPathArgument="path"
73-
os.spawnve(mode=os.P_WAIT, file="path", args=["<progname>", "arg0"], env=env) # $ MISSING: getCommand="path" getAPathArgument="path"
74-
os.spawnvp(mode=os.P_WAIT, file="file", args=["<progname>", "arg0"]) # $ MISSING: getCommand="file" getAPathArgument="file"
75-
os.spawnvpe(mode=os.P_WAIT, file="file", args=["<progname>", "arg0"], env=env) # $ MISSING: getCommand="file" getAPathArgument="file"
72+
os.spawnv(mode=os.P_WAIT, file="path", args=["<progname>", "arg0"]) # $ getCommand="path" MISSING: getAPathArgument="path"
73+
os.spawnve(mode=os.P_WAIT, file="path", args=["<progname>", "arg0"], env=env) # $ getCommand="path" MISSING: getAPathArgument="path"
74+
os.spawnvp(mode=os.P_WAIT, file="file", args=["<progname>", "arg0"]) # $ getCommand="file" MISSING: getAPathArgument="file"
75+
os.spawnvpe(mode=os.P_WAIT, file="file", args=["<progname>", "arg0"], env=env) # $ getCommand="file" MISSING: getAPathArgument="file"
7676

7777
# `posix_spawn` Added in Python 3.8
7878
os.posix_spawn("path", ["<progname>", "arg0"], env) # $ getCommand="path" MISSING: getAPathArgument="path"
79-
os.posix_spawn(path="path", argv=["<progname>", "arg0"], env=env) # $ MISSING: getCommand="path" getAPathArgument="path"
79+
os.posix_spawn(path="path", argv=["<progname>", "arg0"], env=env) # $ getCommand="path" MISSING: getAPathArgument="path"
8080

8181
os.posix_spawnp("path", ["<progname>", "arg0"], env) # $ getCommand="path" MISSING: getAPathArgument="path"
82-
os.posix_spawnp(path="path", argv=["<progname>", "arg0"], env=env) # $ MISSING: getCommand="path" getAPathArgument="path"
82+
os.posix_spawnp(path="path", argv=["<progname>", "arg0"], env=env) # $ getCommand="path" MISSING: getAPathArgument="path"
8383

8484
########################################
8585

0 commit comments

Comments
 (0)