Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python: Model posixpath and os.stat #7143

Merged
merged 2 commits into from Nov 24, 2021
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
@@ -0,0 +1,2 @@
lgtm,codescanning
* 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.
@@ -0,0 +1,2 @@
lgtm,codescanning
* 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.
@@ -254,7 +254,17 @@ private module StdlibPrivate {
/** Provides models for the `os` module. */
module os {
/** Gets a reference to the `os.path` module. */
API::Node path() { result = os().getMember("path") }
API::Node path() {
result = os().getMember("path")
or
// although the following modules should not be used directly, they certainly can.
// Each one doesn't expose the full `os.path` API, so this is an overapproximation
// that made implementation easy. See
// - https://github.com/python/cpython/blob/b567b9d74bd9e476a3027335873bb0508d6e450f/Lib/posixpath.py#L31-L38
// - https://github.com/python/cpython/blob/b567b9d74bd9e476a3027335873bb0508d6e450f/Lib/ntpath.py#L26-L32
// - https://github.com/python/cpython/blob/b567b9d74bd9e476a3027335873bb0508d6e450f/Lib/genericpath.py#L9-L11
result = API::moduleImport(["posixpath", "ntpath", "genericpath"])
}

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

/**
* The `os` module has multiple methods for getting the status of a file, like
* a stat() system call.
*
* Note: `os.fstat` and `os.fstatvfs` operate on file-descriptors.
*
* See:
* - https://docs.python.org/3.10/library/os.html#os.stat
* - https://docs.python.org/3.10/library/os.html#os.lstat
* - https://docs.python.org/3.10/library/os.html#os.statvfs
* - https://docs.python.org/3.10/library/os.html#os.fstat
* - https://docs.python.org/3.10/library/os.html#os.fstatvfs
*/
private class OsProbingCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
OsProbingCall() {
this = os().getMember(["stat", "lstat", "statvfs", "fstat", "fstatvfs"]).getACall()
}

override DataFlow::Node getAPathArgument() {
result in [this.getArg(0), this.getArgByName("path")]
}
}

/**
* The `os.path` module offers a number of methods for checking if a file exists and/or has certain
* properties, leading to a file system access.
@@ -34,3 +34,16 @@ def through_function(open_file):
path.isdir("filepath") # $ getAPathArgument="filepath"
path.islink("filepath") # $ getAPathArgument="filepath"
path.ismount("filepath") # $ getAPathArgument="filepath"

import posixpath
import ntpath
import genericpath

posixpath.exists("filepath") # $ getAPathArgument="filepath"
ntpath.exists("filepath") # $ getAPathArgument="filepath"
genericpath.exists("filepath") # $ getAPathArgument="filepath"

import os

os.stat("filepath") # $ getAPathArgument="filepath"
os.stat(path="filepath") # $ getAPathArgument="filepath"