From a917019915d8dd5240967588ba3772f8c03f7d62 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Mon, 24 Jun 2019 12:18:48 +0100 Subject: [PATCH 1/2] Python: Add failing tests for undefined variable as value and nested 'from import *'. --- .../PointsTo/import_star/Values.expected | 4 ++++ .../library-tests/PointsTo/import_star/Values.ql | 7 +++++++ .../PointsTo/import_star/nested/__init__.py | 1 + .../PointsTo/import_star/nested/nested.py | 2 ++ .../test/library-tests/PointsTo/import_star/test.py | 2 ++ python/ql/test/library-tests/PointsTo/new/Sanity.ql | 12 +++++++++++- 6 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 python/ql/test/library-tests/PointsTo/import_star/Values.expected create mode 100644 python/ql/test/library-tests/PointsTo/import_star/Values.ql create mode 100644 python/ql/test/library-tests/PointsTo/import_star/nested/__init__.py create mode 100644 python/ql/test/library-tests/PointsTo/import_star/nested/nested.py create mode 100644 python/ql/test/library-tests/PointsTo/import_star/test.py diff --git a/python/ql/test/library-tests/PointsTo/import_star/Values.expected b/python/ql/test/library-tests/PointsTo/import_star/Values.expected new file mode 100644 index 000000000000..6d0f8d1ff05d --- /dev/null +++ b/python/ql/test/library-tests/PointsTo/import_star/Values.expected @@ -0,0 +1,4 @@ +| nested/__init__.py:1:6:1:12 | ControlFlowNode for ImportExpr | import | nested/nested.py:0:0:0:0 | Module nested.nested | +| nested/nested.py:1:1:1:13 | ControlFlowNode for FunctionExpr | import | nested/nested.py:1:1:1:13 | Function nested | +| test.py:1:6:1:11 | ControlFlowNode for ImportExpr | import | file://:0:0:0:0 | Package nested | +| test.py:2:1:2:6 | ControlFlowNode for nested | import | nested/nested.py:1:1:1:13 | Function nested | diff --git a/python/ql/test/library-tests/PointsTo/import_star/Values.ql b/python/ql/test/library-tests/PointsTo/import_star/Values.ql new file mode 100644 index 000000000000..f5bfe1bfeac4 --- /dev/null +++ b/python/ql/test/library-tests/PointsTo/import_star/Values.ql @@ -0,0 +1,7 @@ + +import python + +from ControlFlowNode f, Context ctx, Value v, ControlFlowNode origin +where + f.pointsTo(ctx, v, origin) +select f, ctx, v diff --git a/python/ql/test/library-tests/PointsTo/import_star/nested/__init__.py b/python/ql/test/library-tests/PointsTo/import_star/nested/__init__.py new file mode 100644 index 000000000000..97fccdc48179 --- /dev/null +++ b/python/ql/test/library-tests/PointsTo/import_star/nested/__init__.py @@ -0,0 +1 @@ +from .nested import * \ No newline at end of file diff --git a/python/ql/test/library-tests/PointsTo/import_star/nested/nested.py b/python/ql/test/library-tests/PointsTo/import_star/nested/nested.py new file mode 100644 index 000000000000..78229f0f32f3 --- /dev/null +++ b/python/ql/test/library-tests/PointsTo/import_star/nested/nested.py @@ -0,0 +1,2 @@ +def nested(): + pass diff --git a/python/ql/test/library-tests/PointsTo/import_star/test.py b/python/ql/test/library-tests/PointsTo/import_star/test.py new file mode 100644 index 000000000000..2789e06dc2bc --- /dev/null +++ b/python/ql/test/library-tests/PointsTo/import_star/test.py @@ -0,0 +1,2 @@ +from nested import * +nested diff --git a/python/ql/test/library-tests/PointsTo/new/Sanity.ql b/python/ql/test/library-tests/PointsTo/new/Sanity.ql index 3f49d73d832b..d29e8cc0be24 100644 --- a/python/ql/test/library-tests/PointsTo/new/Sanity.ql +++ b/python/ql/test/library-tests/PointsTo/new/Sanity.ql @@ -109,7 +109,17 @@ predicate ssa_sanity(string clsname, string problem, string what) { ) } +predicate undefined_sanity(string clsname, string problem, string what) { + /* Variables may be undefined, but values cannot be */ + exists(ControlFlowNode f | + PointsToInternal::pointsTo(f, _, ObjectInternal::undefined(), _) and + clsname = f.getAQlClass() and not clsname = "AnyNode" and + problem = " points-to an undefined variable" and + what = f.toString() + ) +} + from string clsname, string problem, string what -where ssa_sanity(clsname, problem, what) +where ssa_sanity(clsname, problem, what) or undefined_sanity(clsname, problem, what) select clsname, what, problem From 9bf67e19c288228d52527a0a115c9731980a9dd7 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Mon, 24 Jun 2019 11:55:50 +0100 Subject: [PATCH 2/2] Python points-to: Fix up some oddities with nested from ... import *. --- python/ql/src/semmle/python/objects/Modules.qll | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/python/ql/src/semmle/python/objects/Modules.qll b/python/ql/src/semmle/python/objects/Modules.qll index c3e3d6f19ef2..5edc710c2b3d 100644 --- a/python/ql/src/semmle/python/objects/Modules.qll +++ b/python/ql/src/semmle/python/objects/Modules.qll @@ -177,13 +177,8 @@ class PackageObjectInternal extends ModuleObjectInternal, TPackageObject { or exists(Module init | init = this.getSourceModule() and - ( - /* There is no variable shadowing the name of the child module */ - not exists(EssaVariable var | var.getAUse() = init.getANormalExit() and var.getSourceVariable().getName() = name) - or - /* The variable shadowing the name of the child module is undefined at exit */ - ModuleAttributes::pointsToAtExit(init, name, ObjectInternal::undefined(), _) - ) and + /* The variable shadowing the name of the child module is undefined at exit */ + ModuleAttributes::pointsToAtExit(init, name, ObjectInternal::undefined(), _) and not name = "__init__" and value = this.submodule(name) and origin = CfgOrigin::fromObject(value) @@ -249,6 +244,7 @@ class PythonModuleObjectInternal extends ModuleObjectInternal, TPythonModule { } pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + value != ObjectInternal::undefined() and ModuleAttributes::pointsToAtExit(this.getSourceModule(), name, value, origin) }