mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Python: Distinguish between Python 2 and 3
Also moves the filtering on `name` to before the big disjunction in `MkModuleImport`.
This commit is contained in:
@@ -303,15 +303,15 @@ module API {
|
||||
MkRoot() or
|
||||
/** An abstract representative for imports of the module called `name`. */
|
||||
MkModuleImport(string name) {
|
||||
// Ignore the following module name for Python 2, as we alias `__builtin__` to `builtins` elsewhere
|
||||
(name != "__builtin__" or major_version() = 3) and
|
||||
(
|
||||
imports(_, name)
|
||||
or
|
||||
// When we `import foo.bar.baz` we want to create API graph nodes also for the prefixes
|
||||
// `foo` and `foo.bar`:
|
||||
name = any(ImportExpr e | not e.isRelative()).getAnImportedModuleName()
|
||||
) and
|
||||
// Ignore the following module name, as we alias `__builtin__` to `builtins` elsewhere
|
||||
name != "__builtin__"
|
||||
)
|
||||
or
|
||||
// The `builtins` module should always be implicitly available
|
||||
name = "builtins"
|
||||
@@ -414,6 +414,7 @@ module API {
|
||||
)
|
||||
or
|
||||
// Ensure the Python 2 `__builtin__` module gets the name of the Python 3 `builtins` module.
|
||||
major_version() = 2 and
|
||||
nd = MkModuleImport("builtins") and
|
||||
imports(ref, "__builtin__")
|
||||
or
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
semmle-extractor-options: --lang=2 --max-import-depth=1
|
||||
@@ -0,0 +1,3 @@
|
||||
def python2_style():
|
||||
from __builtin__ import open #$ use=moduleImport("builtins").getMember("open")
|
||||
open("hello.txt") #$ use=moduleImport("builtins").getMember("open").getReturn()
|
||||
30
python/ql/test/experimental/dataflow/ApiGraphs-py2/use.ql
Normal file
30
python/ql/test/experimental/dataflow/ApiGraphs-py2/use.ql
Normal file
@@ -0,0 +1,30 @@
|
||||
import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
import semmle.python.ApiGraphs
|
||||
|
||||
class ApiUseTest extends InlineExpectationsTest {
|
||||
ApiUseTest() { this = "ApiUseTest" }
|
||||
|
||||
override string getARelevantTag() { result = "use" }
|
||||
|
||||
private predicate relevant_node(API::Node a, DataFlow::Node n, Location l) {
|
||||
n = a.getAUse() and l = n.getLocation()
|
||||
}
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(API::Node a, DataFlow::Node n | relevant_node(a, n, location) |
|
||||
tag = "use" and
|
||||
// Only report the longest path on this line:
|
||||
value =
|
||||
max(API::Node a2, Location l2 |
|
||||
relevant_node(a2, _, l2) and
|
||||
l2.getFile() = location.getFile() and
|
||||
l2.getStartLine() = location.getStartLine()
|
||||
|
|
||||
a2.getPath()
|
||||
) and
|
||||
element = n.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -136,5 +136,6 @@ def obscured_print():
|
||||
p("Can you see me?") #$ use=moduleImport("builtins").getMember("print").getReturn()
|
||||
|
||||
def python2_style():
|
||||
from __builtin__ import open #$ use=moduleImport("builtins").getMember("open")
|
||||
open("hello.txt") #$ use=moduleImport("builtins").getMember("open").getReturn()
|
||||
# In Python 3, `__builtin__` has no special meaning.
|
||||
from __builtin__ import open #$ use=moduleImport("__builtin__").getMember("open")
|
||||
open("hello.txt") #$ use=moduleImport("__builtin__").getMember("open").getReturn()
|
||||
|
||||
Reference in New Issue
Block a user