From bbf25f3a23ece4d3f20575506e019f0002b04614 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 5 Jun 2019 14:46:51 +0100 Subject: [PATCH] Python points-to. If __all__ is overly complex, treat all 'public' symbols as exported. --- .../ql/src/semmle/python/pointsto/PointsTo.qll | 17 +++++++++++++++-- .../PointsTo/imports/Runtime.expected | 2 ++ .../PointsTo/imports/RuntimeWithType.expected | 2 ++ .../test/library-tests/PointsTo/imports/test.py | 3 +++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/python/ql/src/semmle/python/pointsto/PointsTo.qll b/python/ql/src/semmle/python/pointsto/PointsTo.qll index 9ad03e2a05d2..f750d31ad3f0 100644 --- a/python/ql/src/semmle/python/pointsto/PointsTo.qll +++ b/python/ql/src/semmle/python/pointsto/PointsTo.qll @@ -726,10 +726,12 @@ private module InterModulePointsTo { | src.declaredInAll(name) and result = true or - src.declaredInAll(_) and not src.declaredInAll(name) and + declared_all_is_simple(src) and + not src.declaredInAll(name) and ofInterestInExports(mod, name) and result = false or - not src.declaredInAll(_) and + (not src.declaredInAll(name) and not declared_all_is_simple(src)) + and exists(ObjectInternal val | ModuleAttributes::pointsToAtExit(src, name, val, _) | val = ObjectInternal::undefined() and result = false @@ -739,6 +741,17 @@ private module InterModulePointsTo { ) } + /** Holds if __all__ is declared and not mutated */ + private predicate declared_all_is_simple(Module m) { + exists(AssignStmt a, GlobalVariable all | + a.defines(all) and a.getScope() = m and + all.getId() = "__all__" and + not exists(Attribute attr | + all.getALoad() = attr.getObject() + ) + ) + } + private boolean packageExportsBoolean(PackageObjectInternal mod, string name) { exists(Folder folder | folder = mod.getFolder() | diff --git a/python/ql/test/library-tests/PointsTo/imports/Runtime.expected b/python/ql/test/library-tests/PointsTo/imports/Runtime.expected index f448b4698de5..345f112dccb9 100644 --- a/python/ql/test/library-tests/PointsTo/imports/Runtime.expected +++ b/python/ql/test/library-tests/PointsTo/imports/Runtime.expected @@ -52,4 +52,6 @@ | test.py | 24 | ControlFlowNode for argv | int 0 | ControlFlowNode for IntegerLiteral | | test.py | 27 | ControlFlowNode for ImportExpr | Module sys | ControlFlowNode for ImportExpr | | test.py | 31 | ControlFlowNode for argv | list object | ControlFlowNode for from sys import * | +| test.py | 33 | ControlFlowNode for ImportExpr | Module socket | ControlFlowNode for ImportExpr | +| test.py | 34 | ControlFlowNode for timeout | builtin-class socket.timeout | ControlFlowNode for from _socket import * | | x.py | 2 | ControlFlowNode for ImportExpr | Module sys | ControlFlowNode for ImportExpr | diff --git a/python/ql/test/library-tests/PointsTo/imports/RuntimeWithType.expected b/python/ql/test/library-tests/PointsTo/imports/RuntimeWithType.expected index a26f53ad87d1..7082c15e4104 100644 --- a/python/ql/test/library-tests/PointsTo/imports/RuntimeWithType.expected +++ b/python/ql/test/library-tests/PointsTo/imports/RuntimeWithType.expected @@ -52,4 +52,6 @@ | test.py | 24 | ControlFlowNode for argv | int 0 | builtin-class int | ControlFlowNode for IntegerLiteral | | test.py | 27 | ControlFlowNode for ImportExpr | Module sys | builtin-class module | ControlFlowNode for ImportExpr | | test.py | 31 | ControlFlowNode for argv | list object | builtin-class list | ControlFlowNode for from sys import * | +| test.py | 33 | ControlFlowNode for ImportExpr | Module socket | builtin-class module | ControlFlowNode for ImportExpr | +| test.py | 34 | ControlFlowNode for timeout | builtin-class socket.timeout | builtin-class type | ControlFlowNode for from _socket import * | | x.py | 2 | ControlFlowNode for ImportExpr | Module sys | builtin-class module | ControlFlowNode for ImportExpr | diff --git a/python/ql/test/library-tests/PointsTo/imports/test.py b/python/ql/test/library-tests/PointsTo/imports/test.py index eb57051a8fa5..a63d1fbcdb54 100644 --- a/python/ql/test/library-tests/PointsTo/imports/test.py +++ b/python/ql/test/library-tests/PointsTo/imports/test.py @@ -29,3 +29,6 @@ def f(self): pass argv + +from socket import * +timeout