Skip to content

Commit f9729bc

Browse files
authored
Merge pull request #7143 from RasmusWL/path-improvements
Python: Model `posixpath` and `os.stat`
2 parents a3b263e + a980f26 commit f9729bc

File tree

4 files changed

+51
-1
lines changed

4 files changed

+51
-1
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* Added modeling of `os.stat`, `os.lstat`, `os.statvfs`, `os.fstat`, and `os.fstatvfs`, which are new sinks for the _Uncontrolled data used in path expression_ (`py/path-injection`) query.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* Added modeling of the `posixpath`, `ntpath`, and `genericpath` modules for path operations (although these are not supposed to be used), resulting in new sinks for the _Uncontrolled data used in path expression_ (`py/path-injection`) query.

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

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,17 @@ private module StdlibPrivate {
254254
/** Provides models for the `os` module. */
255255
module os {
256256
/** Gets a reference to the `os.path` module. */
257-
API::Node path() { result = os().getMember("path") }
257+
API::Node path() {
258+
result = os().getMember("path")
259+
or
260+
// although the following modules should not be used directly, they certainly can.
261+
// Each one doesn't expose the full `os.path` API, so this is an overapproximation
262+
// that made implementation easy. See
263+
// - https://github.com/python/cpython/blob/b567b9d74bd9e476a3027335873bb0508d6e450f/Lib/posixpath.py#L31-L38
264+
// - https://github.com/python/cpython/blob/b567b9d74bd9e476a3027335873bb0508d6e450f/Lib/ntpath.py#L26-L32
265+
// - https://github.com/python/cpython/blob/b567b9d74bd9e476a3027335873bb0508d6e450f/Lib/genericpath.py#L9-L11
266+
result = API::moduleImport(["posixpath", "ntpath", "genericpath"])
267+
}
258268

259269
/** Provides models for the `os.path` module */
260270
module path {
@@ -263,6 +273,29 @@ private module StdlibPrivate {
263273
}
264274
}
265275

276+
/**
277+
* The `os` module has multiple methods for getting the status of a file, like
278+
* a stat() system call.
279+
*
280+
* Note: `os.fstat` and `os.fstatvfs` operate on file-descriptors.
281+
*
282+
* See:
283+
* - https://docs.python.org/3.10/library/os.html#os.stat
284+
* - https://docs.python.org/3.10/library/os.html#os.lstat
285+
* - https://docs.python.org/3.10/library/os.html#os.statvfs
286+
* - https://docs.python.org/3.10/library/os.html#os.fstat
287+
* - https://docs.python.org/3.10/library/os.html#os.fstatvfs
288+
*/
289+
private class OsProbingCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
290+
OsProbingCall() {
291+
this = os().getMember(["stat", "lstat", "statvfs", "fstat", "fstatvfs"]).getACall()
292+
}
293+
294+
override DataFlow::Node getAPathArgument() {
295+
result in [this.getArg(0), this.getArgByName("path")]
296+
}
297+
}
298+
266299
/**
267300
* The `os.path` module offers a number of methods for checking if a file exists and/or has certain
268301
* properties, leading to a file system access.

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,16 @@ def through_function(open_file):
3434
path.isdir("filepath") # $ getAPathArgument="filepath"
3535
path.islink("filepath") # $ getAPathArgument="filepath"
3636
path.ismount("filepath") # $ getAPathArgument="filepath"
37+
38+
import posixpath
39+
import ntpath
40+
import genericpath
41+
42+
posixpath.exists("filepath") # $ getAPathArgument="filepath"
43+
ntpath.exists("filepath") # $ getAPathArgument="filepath"
44+
genericpath.exists("filepath") # $ getAPathArgument="filepath"
45+
46+
import os
47+
48+
os.stat("filepath") # $ getAPathArgument="filepath"
49+
os.stat(path="filepath") # $ getAPathArgument="filepath"

0 commit comments

Comments
 (0)