Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f8dba85

Browse files
committed
Python: PathNormalization os.path.normpath
1 parent 17273dd commit f8dba85

1 file changed

Lines changed: 52 additions & 9 deletions

File tree

  • python/ql/src/experimental/semmle/python/frameworks

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

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,22 +82,65 @@ private module Stdlib {
8282

8383
/** Provides models for the `os.path` module */
8484
module path {
85-
/** Gets a reference to the `os.path.join` function. */
86-
private DataFlow::Node join(DataFlow::TypeTracker t) {
87-
t.start() and
88-
result = DataFlow::importNode("os.path.join")
89-
or
90-
t.startInAttr("join") and
91-
result = os::path()
85+
/**
86+
* Gets a reference to the attribute `attr_name` of the `os.path` module.
87+
* WARNING: Only holds for a few predefined attributes.
88+
*
89+
* For example, using `attr_name = "join"` will get all uses of `os.path.join`.
90+
*/
91+
private DataFlow::Node path_attr(DataFlow::TypeTracker t, string attr_name) {
92+
attr_name in ["join", "normpath"] and
93+
(
94+
t.start() and
95+
result = DataFlow::importNode("os.path." + attr_name)
96+
or
97+
t.startInAttr(attr_name) and
98+
result = os::path()
99+
)
92100
or
93-
exists(DataFlow::TypeTracker t2 | result = join(t2).track(t2, t))
101+
// Due to bad performance when using normal setup with `path_attr(t2, attr_name).track(t2, t)`
102+
// we have inlined that code and forced a join
103+
exists(DataFlow::TypeTracker t2 |
104+
exists(DataFlow::StepSummary summary |
105+
path_attr_first_join(t2, attr_name, result, summary) and
106+
t = t2.append(summary)
107+
)
108+
)
109+
}
110+
111+
pragma[nomagic]
112+
private predicate path_attr_first_join(
113+
DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res,
114+
DataFlow::StepSummary summary
115+
) {
116+
DataFlow::StepSummary::step(path_attr(t2, attr_name), res, summary)
117+
}
118+
119+
/**
120+
* Gets a reference to the attribute `attr_name` of the `os.path` module.
121+
* WARNING: Only holds for a few predefined attributes.
122+
*
123+
* For example, using `attr_name = "join"` will get all uses of `os.path.join`.
124+
*/
125+
DataFlow::Node path_attr(string attr_name) {
126+
result = path_attr(DataFlow::TypeTracker::end(), attr_name)
94127
}
95128

96129
/** Gets a reference to the `os.path.join` function. */
97-
DataFlow::Node join() { result = join(DataFlow::TypeTracker::end()) }
130+
DataFlow::Node join() { result = path_attr("join") }
98131
}
99132
}
100133

134+
/**
135+
* A call to `os.path.normpath`.
136+
* See https://docs.python.org/3/library/os.path.html#os.path.normpath
137+
*/
138+
private class NormpathCall extends PathNormalization::Range, DataFlow::CfgNode {
139+
override CallNode node;
140+
141+
NormpathCall() { node.getFunction() = os::path::path_attr("normpath").asCfgNode() }
142+
}
143+
101144
/**
102145
* A call to `os.system`.
103146
* See https://docs.python.org/3/library/os.html#os.system

0 commit comments

Comments
 (0)