From fef08afff9020323bba3276327b953d3371888d9 Mon Sep 17 00:00:00 2001 From: Taus Date: Wed, 29 Oct 2025 22:05:43 +0000 Subject: [PATCH 01/19] Python: Remove points-to to from `ControlFlowNode` Moves the existing points-to predicates to the newly added class `ControlFlowNodeWithPointsTo` which resides in the `LegacyPointsTo` module. (Existing code that uses these predicates should import this module, and references to `ControlFlowNode` should be changed to `ControlFlowNodeWithPointsTo`.) Also updates all existing points-to based code to do just this. --- python/ql/examples/snippets/store_none.ql | 3 +- python/ql/lib/LegacyPointsTo.qll | 121 ++++++++++++++++++ python/ql/lib/analysis/DefinitionTracking.qll | 21 +-- python/ql/lib/semmle/python/Exprs.qll | 13 +- python/ql/lib/semmle/python/Flow.qll | 90 ------------- python/ql/lib/semmle/python/Metrics.qll | 3 +- .../ql/lib/semmle/python/SpecialMethods.qll | 7 +- .../python/dataflow/old/Implementation.qll | 13 +- .../python/dataflow/old/TaintTracking.qll | 21 ++- .../python/dependencies/Dependencies.qll | 9 +- .../lib/semmle/python/objects/ObjectAPI.qll | 9 +- .../lib/semmle/python/types/ClassObject.qll | 7 +- .../ql/lib/semmle/python/types/Exceptions.qll | 17 ++- .../semmle/python/types/FunctionObject.qll | 23 ++-- python/ql/lib/semmle/python/types/Object.qll | 10 +- .../ql/lib/semmle/python/types/Properties.qll | 21 +-- .../semmle/python/values/StringAttributes.qll | 25 +++- .../src/Expressions/ContainsNonContainer.ql | 4 +- .../Formatting/AdvancedFormatting.qll | 11 +- python/ql/src/Expressions/HashedButNoHash.ql | 5 +- python/ql/src/Expressions/IsComparisons.qll | 7 +- .../ql/src/Expressions/TruncatedDivision.ql | 5 +- python/ql/src/Expressions/UseofApply.ql | 3 +- .../Imports/FromImportOfMutableAttribute.ql | 3 +- .../Statements/IterableStringOrSequence.ql | 3 +- .../ql/src/Statements/ModificationOfLocals.ql | 5 +- .../ql/src/Statements/NonIteratorInForLoop.ql | 3 +- .../src/Statements/ShouldUseWithStatement.ql | 3 +- .../Statements/StringConcatenationInLoop.ql | 3 +- python/ql/src/Statements/UseOfExit.ql | 3 +- python/ql/src/Testing/Mox.qll | 3 +- python/ql/src/Variables/MonkeyPatched.qll | 9 +- python/ql/src/Variables/ShadowGlobal.ql | 10 +- .../SuspiciousUnusedLoopIterationVariable.ql | 3 +- python/ql/src/Variables/UndefinedExport.ql | 13 +- python/ql/src/analysis/Consistency.ql | 11 +- python/ql/src/analysis/Efficiency.ql | 5 +- python/ql/src/analysis/ImportFailure.ql | 6 +- python/ql/src/analysis/PointsToFailure.ql | 3 +- .../ql/src/analysis/TypeInferenceFailure.ql | 3 +- .../PointsTo/class_properties/ClassValues.ql | 3 +- .../library-tests/PointsTo/imports/Runtime.ql | 3 +- .../PointsTo/imports2/Runtime.ql | 3 +- .../PointsTo/imports2/RuntimeWithType.ql | 3 +- .../PointsTo/origin_uniqueness/Origin.ql | 3 +- .../library-tests/PointsTo/attributes/Test.ql | 3 +- .../PointsTo/attributes/TestWithType.ql | 3 +- .../PointsTo/class_properties/ClassValues.ql | 3 +- .../library-tests/PointsTo/imports/Runtime.ql | 3 +- .../PointsTo/imports/RuntimeWithType.ql | 3 +- .../PointsTo/typehints/Values.ql | 3 +- .../library-tests/PointsTo/absent/Absent.ql | 3 +- .../PointsTo/calls/CallPointsTo.ql | 3 +- .../PointsTo/comparisons/PointsTo.ql | 3 +- .../library-tests/PointsTo/decorators/Test.ql | 3 +- .../PointsTo/general/GlobalPointsTo.ql | 3 +- .../PointsTo/general/LocalPointsTo.ql | 3 +- .../PointsTo/general/LocalPointsToType.ql | 3 +- .../PointsTo/guarded/PointsTo.ql | 3 +- .../PointsTo/guarded/PointsToWithType.ql | 3 +- .../PointsTo/import_star/Values.ql | 3 +- .../library-tests/PointsTo/indexing/Test.ql | 3 +- .../PointsTo/indexing/TestWithType.ql | 3 +- .../PointsTo/inheritance/Self.ql | 3 +- .../PointsTo/new/ImpliesDataflow.ql | 3 +- .../PointsTo/new/PointsToNone.ql | 3 +- .../test/library-tests/PointsTo/new/Values.ql | 3 +- .../PointsTo/properties/Values.ql | 3 +- .../missing/if-urlsplit-access/Test.ql | 3 +- .../regressions/missing/re-compile/Test.ql | 3 +- .../missing/uncalled-function/Test.ql | 3 +- .../regressions/wrong/classmethod/Test.ql | 5 +- .../PointsTo/super/SuperMethodCall.ql | 5 +- .../ql/test/library-tests/objects/Strings.ql | 3 +- .../taint/extensions/ExtensionsLib.qll | 3 +- 75 files changed, 410 insertions(+), 236 deletions(-) create mode 100644 python/ql/lib/LegacyPointsTo.qll diff --git a/python/ql/examples/snippets/store_none.ql b/python/ql/examples/snippets/store_none.ql index 57be82f229dc..b35c5fc84b4e 100644 --- a/python/ql/examples/snippets/store_none.ql +++ b/python/ql/examples/snippets/store_none.ql @@ -10,9 +10,10 @@ */ import python +private import LegacyPointsTo from SubscriptNode store where store.isStore() and - store.getIndex().pointsTo(Value::named("None")) + store.getIndex().(ControlFlowNodeWithPointsTo).pointsTo(Value::named("None")) select store diff --git a/python/ql/lib/LegacyPointsTo.qll b/python/ql/lib/LegacyPointsTo.qll new file mode 100644 index 000000000000..f195bc20a519 --- /dev/null +++ b/python/ql/lib/LegacyPointsTo.qll @@ -0,0 +1,121 @@ +/** + * DEPRECATED: Using the methods in this module may lead to a degradation of performance. Use at + * your own peril. + * + * This module contains legacy points-to predicates and methods for various classes in the + * points-to analysis. + * + * Existing code that depends on, say, points-to predicates on `ControlFlowNode` should be modified + * to use `ControlFlowNodeWithPointsTo` instead. In particular, if inside a method call chain such + * as + * + * `someCallNode.getFunction().pointsTo(...)` + * + * an explicit cast should be added as follows + * + * `someCallNode.getFunction().(ControlFlowNodeWithPointsTo).pointsTo(...)` + * + * Similarly, if a bound variable has type `ControlFlowNode`, and a points-to method is called on + * it, the type should be changed to `ControlFlowNodeWithPointsTo`. + */ + +private import python +private import semmle.python.pointsto.PointsTo + +/** + * An extension of `ControlFlowNode` that provides points-to predicates. + */ +class ControlFlowNodeWithPointsTo extends ControlFlowNode { + /** Gets the value that this ControlFlowNode points-to. */ + predicate pointsTo(Value value) { this.pointsTo(_, value, _) } + + /** Gets the value that this ControlFlowNode points-to. */ + Value pointsTo() { this.pointsTo(_, result, _) } + + /** Gets a value that this ControlFlowNode may points-to. */ + Value inferredValue() { this.pointsTo(_, result, _) } + + /** Gets the value and origin that this ControlFlowNode points-to. */ + predicate pointsTo(Value value, ControlFlowNode origin) { this.pointsTo(_, value, origin) } + + /** Gets the value and origin that this ControlFlowNode points-to, given the context. */ + predicate pointsTo(Context context, Value value, ControlFlowNode origin) { + PointsTo::pointsTo(this, context, value, origin) + } + + /** + * Gets what this flow node might "refer-to". Performs a combination of localized (intra-procedural) points-to + * analysis and global module-level analysis. This points-to analysis favours precision over recall. It is highly + * precise, but may not provide information for a significant number of flow-nodes. + * If the class is unimportant then use `refersTo(value)` or `refersTo(value, origin)` instead. + */ + pragma[nomagic] + predicate refersTo(Object obj, ClassObject cls, ControlFlowNode origin) { + this.refersTo(_, obj, cls, origin) + } + + /** Gets what this expression might "refer-to" in the given `context`. */ + pragma[nomagic] + predicate refersTo(Context context, Object obj, ClassObject cls, ControlFlowNode origin) { + not obj = unknownValue() and + not cls = theUnknownType() and + PointsTo::points_to(this, context, obj, cls, origin) + } + + /** + * Whether this flow node might "refer-to" to `value` which is from `origin` + * Unlike `this.refersTo(value, _, origin)` this predicate includes results + * where the class cannot be inferred. + */ + pragma[nomagic] + predicate refersTo(Object obj, ControlFlowNode origin) { + not obj = unknownValue() and + PointsTo::points_to(this, _, obj, _, origin) + } + + /** Equivalent to `this.refersTo(value, _)` */ + predicate refersTo(Object obj) { this.refersTo(obj, _) } + + /** + * Check whether this control-flow node has complete points-to information. + * This would mean that the analysis managed to infer an over approximation + * of possible values at runtime. + */ + predicate hasCompletePointsToSet() { + // If the tracking failed, then `this` will be its own "origin". In that + // case, we want to exclude nodes for which there is also a different + // origin, as that would indicate that some paths failed and some did not. + this.refersTo(_, _, this) and + not exists(ControlFlowNode other | other != this and this.refersTo(_, _, other)) + or + // If `this` is a use of a variable, then we must have complete points-to + // for that variable. + exists(SsaVariable v | v.getAUse() = this | varHasCompletePointsToSet(v)) + } +} + +/** + * Check whether a SSA variable has complete points-to information. + * This would mean that the analysis managed to infer an overapproximation + * of possible values at runtime. + */ +private predicate varHasCompletePointsToSet(SsaVariable var) { + // Global variables may be modified non-locally or concurrently. + not var.getVariable() instanceof GlobalVariable and + ( + // If we have complete points-to information on the definition of + // this variable, then the variable has complete information. + var.getDefinition() + .(DefinitionNode) + .getValue() + .(ControlFlowNodeWithPointsTo) + .hasCompletePointsToSet() + or + // If this variable is a phi output, then we have complete + // points-to information about it if all phi inputs had complete + // information. + forex(SsaVariable phiInput | phiInput = var.getAPhiInput() | + varHasCompletePointsToSet(phiInput) + ) + ) +} diff --git a/python/ql/lib/analysis/DefinitionTracking.qll b/python/ql/lib/analysis/DefinitionTracking.qll index e015d0f70a97..53f8e791cd8b 100644 --- a/python/ql/lib/analysis/DefinitionTracking.qll +++ b/python/ql/lib/analysis/DefinitionTracking.qll @@ -3,6 +3,7 @@ */ import python +private import LegacyPointsTo import semmle.python.pointsto.PointsTo import IDEContextual @@ -36,22 +37,22 @@ private predicate jump_to_defn(ControlFlowNode use, Definition defn) { ) or exists(PythonModuleObject mod | - use.(ImportExprNode).refersTo(mod) and + use.(ImportExprNode).(ControlFlowNodeWithPointsTo).refersTo(mod) and defn.getAstNode() = mod.getModule() ) or exists(PythonModuleObject mod, string name | - use.(ImportMemberNode).getModule(name).refersTo(mod) and + use.(ImportMemberNode).getModule(name).(ControlFlowNodeWithPointsTo).refersTo(mod) and scope_jump_to_defn_attribute(mod.getModule(), name, defn) ) or exists(PackageObject package | - use.(ImportExprNode).refersTo(package) and + use.(ImportExprNode).(ControlFlowNodeWithPointsTo).refersTo(package) and defn.getAstNode() = package.getInitModule().getModule() ) or exists(PackageObject package, string name | - use.(ImportMemberNode).getModule(name).refersTo(package) and + use.(ImportMemberNode).getModule(name).(ControlFlowNodeWithPointsTo).refersTo(package) and scope_jump_to_defn_attribute(package.getInitModule().getModule(), name, defn) ) or @@ -230,7 +231,7 @@ private predicate module_and_name_for_import_star_helper( ModuleObject mod, string name, ImportStarNode im_star, ImportStarRefinement def ) { im_star = def.getDefiningNode() and - im_star.getModule().refersTo(mod) and + im_star.getModule().(ControlFlowNodeWithPointsTo).refersTo(mod) and name = def.getSourceVariable().getName() } @@ -239,7 +240,7 @@ pragma[noinline] private predicate variable_not_redefined_by_import_star(EssaVariable var, ImportStarRefinement def) { var = def.getInput() and exists(ModuleObject mod | - def.getDefiningNode().(ImportStarNode).getModule().refersTo(mod) and + def.getDefiningNode().(ImportStarNode).getModule().(ControlFlowNodeWithPointsTo).refersTo(mod) and not mod.exports(var.getSourceVariable().getName()) ) } @@ -352,7 +353,9 @@ private predicate scope_jump_to_defn_attribute(ImportTimeScope s, string name, D ) } -private predicate jump_to_defn_attribute(ControlFlowNode use, string name, Definition defn) { +private predicate jump_to_defn_attribute( + ControlFlowNodeWithPointsTo use, string name, Definition defn +) { /* Local attribute */ exists(EssaVariable var | use = var.getASourceUse() and @@ -367,7 +370,7 @@ private predicate jump_to_defn_attribute(ControlFlowNode use, string name, Defin /* Super attributes */ exists(AttrNode f, SuperBoundMethod sbm, Object function | use = f.getObject(name) and - f.refersTo(sbm) and + f.(ControlFlowNodeWithPointsTo).refersTo(sbm) and function = sbm.getFunction(_) and function.getOrigin() = defn.getAstNode() ) @@ -408,7 +411,7 @@ private predicate attribute_assignment_jump_to_defn_attribute( private predicate sets_attribute(ArgumentRefinement def, string name) { exists(CallNode call | call = def.getDefiningNode() and - call.getFunction().refersTo(Object::builtin("setattr")) and + call.getFunction().(ControlFlowNodeWithPointsTo).refersTo(Object::builtin("setattr")) and def.getInput().getAUse() = call.getArg(0) and call.getArg(1).getNode().(StringLiteral).getText() = name ) diff --git a/python/ql/lib/semmle/python/Exprs.qll b/python/ql/lib/semmle/python/Exprs.qll index a7f67b0b80ea..e288078247a9 100644 --- a/python/ql/lib/semmle/python/Exprs.qll +++ b/python/ql/lib/semmle/python/Exprs.qll @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo private import semmle.python.pointsto.PointsTo private import semmle.python.objects.ObjectInternal private import semmle.python.internal.CachedStages @@ -71,7 +72,9 @@ class Expr extends Expr_, AstNode { * Gets what this expression might "refer-to" in the given `context`. */ predicate refersTo(Context context, Object obj, ClassObject cls, AstNode origin) { - this.getAFlowNode().refersTo(context, obj, cls, origin.getAFlowNode()) + this.getAFlowNode() + .(ControlFlowNodeWithPointsTo) + .refersTo(context, obj, cls, origin.getAFlowNode()) } /** @@ -82,7 +85,7 @@ class Expr extends Expr_, AstNode { */ pragma[nomagic] predicate refersTo(Object obj, AstNode origin) { - this.getAFlowNode().refersTo(obj, origin.getAFlowNode()) + this.getAFlowNode().(ControlFlowNodeWithPointsTo).refersTo(obj, origin.getAFlowNode()) } /** @@ -96,14 +99,16 @@ class Expr extends Expr_, AstNode { * in the given `context`. */ predicate pointsTo(Context context, Value value, AstNode origin) { - this.getAFlowNode().pointsTo(context, value, origin.getAFlowNode()) + this.getAFlowNode() + .(ControlFlowNodeWithPointsTo) + .pointsTo(context, value, origin.getAFlowNode()) } /** * Holds if this expression might "point-to" to `value` which is from `origin`. */ predicate pointsTo(Value value, AstNode origin) { - this.getAFlowNode().pointsTo(value, origin.getAFlowNode()) + this.getAFlowNode().(ControlFlowNodeWithPointsTo).pointsTo(value, origin.getAFlowNode()) } /** diff --git a/python/ql/lib/semmle/python/Flow.qll b/python/ql/lib/semmle/python/Flow.qll index 621013adcd56..496c1abc52a1 100644 --- a/python/ql/lib/semmle/python/Flow.qll +++ b/python/ql/lib/semmle/python/Flow.qll @@ -1,5 +1,4 @@ import python -private import semmle.python.pointsto.PointsTo private import semmle.python.internal.CachedStages private import codeql.controlflow.BasicBlock as BB @@ -144,56 +143,6 @@ class ControlFlowNode extends @py_flow_node { /** Whether this flow node is the first in its scope */ predicate isEntryNode() { py_scope_flow(this, _, -1) } - /** Gets the value that this ControlFlowNode points-to. */ - predicate pointsTo(Value value) { this.pointsTo(_, value, _) } - - /** Gets the value that this ControlFlowNode points-to. */ - Value pointsTo() { this.pointsTo(_, result, _) } - - /** Gets a value that this ControlFlowNode may points-to. */ - Value inferredValue() { this.pointsTo(_, result, _) } - - /** Gets the value and origin that this ControlFlowNode points-to. */ - predicate pointsTo(Value value, ControlFlowNode origin) { this.pointsTo(_, value, origin) } - - /** Gets the value and origin that this ControlFlowNode points-to, given the context. */ - predicate pointsTo(Context context, Value value, ControlFlowNode origin) { - PointsTo::pointsTo(this, context, value, origin) - } - - /** - * Gets what this flow node might "refer-to". Performs a combination of localized (intra-procedural) points-to - * analysis and global module-level analysis. This points-to analysis favours precision over recall. It is highly - * precise, but may not provide information for a significant number of flow-nodes. - * If the class is unimportant then use `refersTo(value)` or `refersTo(value, origin)` instead. - */ - pragma[nomagic] - predicate refersTo(Object obj, ClassObject cls, ControlFlowNode origin) { - this.refersTo(_, obj, cls, origin) - } - - /** Gets what this expression might "refer-to" in the given `context`. */ - pragma[nomagic] - predicate refersTo(Context context, Object obj, ClassObject cls, ControlFlowNode origin) { - not obj = unknownValue() and - not cls = theUnknownType() and - PointsTo::points_to(this, context, obj, cls, origin) - } - - /** - * Whether this flow node might "refer-to" to `value` which is from `origin` - * Unlike `this.refersTo(value, _, origin)` this predicate includes results - * where the class cannot be inferred. - */ - pragma[nomagic] - predicate refersTo(Object obj, ControlFlowNode origin) { - not obj = unknownValue() and - PointsTo::points_to(this, _, obj, _, origin) - } - - /** Equivalent to `this.refersTo(value, _)` */ - predicate refersTo(Object obj) { this.refersTo(obj, _) } - /** Gets the basic block containing this flow node */ BasicBlock getBasicBlock() { result.contains(this) } @@ -259,23 +208,6 @@ class ControlFlowNode extends @py_flow_node { ) } - /** - * Check whether this control-flow node has complete points-to information. - * This would mean that the analysis managed to infer an over approximation - * of possible values at runtime. - */ - predicate hasCompletePointsToSet() { - // If the tracking failed, then `this` will be its own "origin". In that - // case, we want to exclude nodes for which there is also a different - // origin, as that would indicate that some paths failed and some did not. - this.refersTo(_, _, this) and - not exists(ControlFlowNode other | other != this and this.refersTo(_, _, other)) - or - // If `this` is a use of a variable, then we must have complete points-to - // for that variable. - exists(SsaVariable v | v.getAUse() = this | varHasCompletePointsToSet(v)) - } - /** Whether this strictly dominates other. */ pragma[inline] predicate strictlyDominates(ControlFlowNode other) { @@ -332,28 +264,6 @@ private class AnyNode extends ControlFlowNode { override AstNode getNode() { result = super.getNode() } } -/** - * Check whether a SSA variable has complete points-to information. - * This would mean that the analysis managed to infer an overapproximation - * of possible values at runtime. - */ -private predicate varHasCompletePointsToSet(SsaVariable var) { - // Global variables may be modified non-locally or concurrently. - not var.getVariable() instanceof GlobalVariable and - ( - // If we have complete points-to information on the definition of - // this variable, then the variable has complete information. - var.getDefinition().(DefinitionNode).getValue().hasCompletePointsToSet() - or - // If this variable is a phi output, then we have complete - // points-to information about it if all phi inputs had complete - // information. - forex(SsaVariable phiInput | phiInput = var.getAPhiInput() | - varHasCompletePointsToSet(phiInput) - ) - ) -} - /** A control flow node corresponding to a call expression, such as `func(...)` */ class CallNode extends ControlFlowNode { CallNode() { toAst(this) instanceof Call } diff --git a/python/ql/lib/semmle/python/Metrics.qll b/python/ql/lib/semmle/python/Metrics.qll index e5130ba000f5..16d89711eea3 100644 --- a/python/ql/lib/semmle/python/Metrics.qll +++ b/python/ql/lib/semmle/python/Metrics.qll @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo /** The metrics for a function */ class FunctionMetrics extends Function { @@ -59,7 +60,7 @@ class FunctionMetrics extends Function { not non_coupling_method(result) and exists(Call call | call.getScope() = this | exists(FunctionObject callee | callee.getFunction() = result | - call.getAFlowNode().getFunction().refersTo(callee) + call.getAFlowNode().getFunction().(ControlFlowNodeWithPointsTo).refersTo(callee) ) or exists(Attribute a | call.getFunc() = a | diff --git a/python/ql/lib/semmle/python/SpecialMethods.qll b/python/ql/lib/semmle/python/SpecialMethods.qll index a5832ae45ae1..ea9e753d0f89 100644 --- a/python/ql/lib/semmle/python/SpecialMethods.qll +++ b/python/ql/lib/semmle/python/SpecialMethods.qll @@ -9,6 +9,7 @@ */ private import python +private import LegacyPointsTo /** A control flow node which might correspond to a special method call. */ class PotentialSpecialMethodCallNode extends ControlFlowNode instanceof SpecialMethod::Potential { } @@ -106,7 +107,11 @@ class SpecialMethodCallNode extends PotentialSpecialMethodCallNode { SpecialMethodCallNode() { exists(SpecialMethod::Potential pot | this = pot and - pot.getSelf().pointsTo().getClass().lookup(pot.getSpecialMethodName()) = resolvedSpecialMethod + pot.getSelf() + .(ControlFlowNodeWithPointsTo) + .pointsTo() + .getClass() + .lookup(pot.getSpecialMethodName()) = resolvedSpecialMethod ) } diff --git a/python/ql/lib/semmle/python/dataflow/old/Implementation.qll b/python/ql/lib/semmle/python/dataflow/old/Implementation.qll index 19197f4bd306..83476db803c6 100644 --- a/python/ql/lib/semmle/python/dataflow/old/Implementation.qll +++ b/python/ql/lib/semmle/python/dataflow/old/Implementation.qll @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo import semmle.python.dataflow.TaintTracking private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.Filters as Filters @@ -374,7 +375,7 @@ class TaintTrackingImplementation extends string instanceof TaintTracking::Confi exists(ModuleValue m, string name | src = TTaintTrackingNode_(_, context, path, kind, this) and this.moduleAttributeTainted(m, name, src) and - node.asCfgNode().(ImportMemberNode).getModule(name).pointsTo(m) + node.asCfgNode().(ImportMemberNode).getModule(name).(ControlFlowNodeWithPointsTo).pointsTo(m) ) } @@ -408,7 +409,9 @@ class TaintTrackingImplementation extends string instanceof TaintTracking::Confi src = TTaintTrackingNode_(srcnode, context, srcpath, srckind, this) and exists(CallNode call, ControlFlowNode arg | call = node.asCfgNode() and - call.getFunction().pointsTo(ObjectInternal::builtin("getattr")) and + call.getFunction() + .(ControlFlowNodeWithPointsTo) + .pointsTo(ObjectInternal::builtin("getattr")) and arg = call.getArg(0) and attrname = call.getArg(1).getNode().(StringLiteral).getText() and arg = srcnode.asCfgNode() @@ -515,7 +518,7 @@ class TaintTrackingImplementation extends string instanceof TaintTracking::Confi TaintTrackingContext caller, TaintTrackingContext callee ) { exists(ClassValue cls | - call.getFunction().pointsTo(cls) and + call.getFunction().(ControlFlowNodeWithPointsTo).pointsTo(cls) and cls.lookup("__init__") = init | exists(int arg, TaintKind callerKind, AttributePath callerPath, DataFlow::Node argument | @@ -878,7 +881,7 @@ private class EssaTaintTracking extends string instanceof TaintTracking::Configu const.getNode() instanceof ImmutableLiteral ) or - exists(ControlFlowNode c, ClassValue cls | + exists(ControlFlowNodeWithPointsTo c, ClassValue cls | Filters::isinstance(test, c, use) and c.pointsTo(cls) | @@ -978,7 +981,7 @@ module Implementation { tonode.getArg(0) = fromnode ) or - tonode.getFunction().pointsTo(ObjectInternal::builtin("reversed")) and + tonode.getFunction().(ControlFlowNodeWithPointsTo).pointsTo(ObjectInternal::builtin("reversed")) and tonode.getArg(0) = fromnode } } diff --git a/python/ql/lib/semmle/python/dataflow/old/TaintTracking.qll b/python/ql/lib/semmle/python/dataflow/old/TaintTracking.qll index 0ce4bc27790e..15459a310438 100644 --- a/python/ql/lib/semmle/python/dataflow/old/TaintTracking.qll +++ b/python/ql/lib/semmle/python/dataflow/old/TaintTracking.qll @@ -87,6 +87,7 @@ */ import python +private import LegacyPointsTo private import semmle.python.pointsto.Filters as Filters private import semmle.python.objects.ObjectInternal private import semmle.python.dataflow.Implementation @@ -267,7 +268,11 @@ module DictKind { Implementation::copyCall(fromnode, tonode) and edgeLabel = "dict copy" or - tonode.(CallNode).getFunction().pointsTo(ObjectInternal::builtin("dict")) and + tonode + .(CallNode) + .getFunction() + .(ControlFlowNodeWithPointsTo) + .pointsTo(ObjectInternal::builtin("dict")) and tonode.(CallNode).getArg(0) = fromnode and edgeLabel = "dict() call" } @@ -615,7 +620,7 @@ module DataFlow { TCfgNode(ControlFlowNode node) abstract class Node extends TDataFlowNode { - abstract ControlFlowNode asCfgNode(); + abstract ControlFlowNodeWithPointsTo asCfgNode(); abstract EssaVariable asVariable(); @@ -632,7 +637,7 @@ module DataFlow { } class CfgNode extends Node, TCfgNode { - override ControlFlowNode asCfgNode() { this = TCfgNode(result) } + override ControlFlowNodeWithPointsTo asCfgNode() { this = TCfgNode(result) } override EssaVariable asVariable() { none() } @@ -647,7 +652,7 @@ module DataFlow { } class EssaNode extends Node, TEssaNode { - override ControlFlowNode asCfgNode() { none() } + override ControlFlowNodeWithPointsTo asCfgNode() { none() } override EssaVariable asVariable() { this = TEssaNode(result) } @@ -668,7 +673,11 @@ pragma[noinline] private predicate dict_construct(ControlFlowNode itemnode, ControlFlowNode dictnode) { dictnode.(DictNode).getAValue() = itemnode or - dictnode.(CallNode).getFunction().pointsTo(ObjectInternal::builtin("dict")) and + dictnode + .(CallNode) + .getFunction() + .(ControlFlowNodeWithPointsTo) + .pointsTo(ObjectInternal::builtin("dict")) and dictnode.(CallNode).getArgByName(_) = itemnode } @@ -688,7 +697,7 @@ private predicate sequence_construct(ControlFlowNode itemnode, ControlFlowNode s pragma[noinline] private predicate sequence_call(ControlFlowNode fromnode, CallNode tonode) { tonode.getArg(0) = fromnode and - exists(ControlFlowNode cls | cls = tonode.getFunction() | + exists(ControlFlowNodeWithPointsTo cls | cls = tonode.getFunction() | cls.pointsTo(ObjectInternal::builtin("list")) or cls.pointsTo(ObjectInternal::builtin("tuple")) diff --git a/python/ql/lib/semmle/python/dependencies/Dependencies.qll b/python/ql/lib/semmle/python/dependencies/Dependencies.qll index 6f70c7e4ec06..a224ad1b9601 100644 --- a/python/ql/lib/semmle/python/dependencies/Dependencies.qll +++ b/python/ql/lib/semmle/python/dependencies/Dependencies.qll @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo import semmle.python.dependencies.DependencyKind private predicate importDependency(Object target, AstNode source) { @@ -59,7 +60,7 @@ class PythonUse extends DependencyKind { interesting(target) and this = this and source != target.(ControlFlowNode).getNode() and - exists(ControlFlowNode use, Object obj | + exists(ControlFlowNodeWithPointsTo use, Object obj | use.getNode() = source and use.refersTo(obj) and use.isLoad() @@ -114,12 +115,14 @@ private predicate attribute_access_dependency(Object target, AstNode source) { private predicate use_of_attribute(Attribute attr, Scope s, string name) { exists(AttrNode cfg | cfg.isLoad() and cfg.getNode() = attr | - exists(Object obj | cfg.getObject(name).refersTo(obj) | + exists(Object obj | cfg.getObject(name).(ControlFlowNodeWithPointsTo).refersTo(obj) | s = obj.(PythonModuleObject).getModule() or s = obj.(ClassObject).getPyClass() ) or - exists(ClassObject cls | cfg.getObject(name).refersTo(_, cls, _) | s = cls.getPyClass()) + exists(ClassObject cls | cfg.getObject(name).(ControlFlowNodeWithPointsTo).refersTo(_, cls, _) | + s = cls.getPyClass() + ) ) or exists(SelfAttributeRead sar | sar = attr | diff --git a/python/ql/lib/semmle/python/objects/ObjectAPI.qll b/python/ql/lib/semmle/python/objects/ObjectAPI.qll index 4a36ec6d847f..26c57a78c179 100644 --- a/python/ql/lib/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/lib/semmle/python/objects/ObjectAPI.qll @@ -4,6 +4,7 @@ */ import python +private import LegacyPointsTo private import TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo @@ -704,12 +705,14 @@ abstract class FunctionValue extends CallableValue { abstract ClassValue getARaisedType(); /** Gets a call-site from where this function is called as a function */ - CallNode getAFunctionCall() { result.getFunction().pointsTo() = this } + CallNode getAFunctionCall() { + result.getFunction().(ControlFlowNodeWithPointsTo).pointsTo() = this + } /** Gets a call-site from where this function is called as a method */ CallNode getAMethodCall() { exists(BoundMethodObjectInternal bm | - result.getFunction().pointsTo() = bm and + result.getFunction().(ControlFlowNodeWithPointsTo).pointsTo() = bm and bm.getFunction() = this ) } @@ -753,7 +756,7 @@ class PythonFunctionValue extends FunctionValue { * explicit return nodes that we can query and get the class of. */ - result = this.getAReturnedNode().pointsTo().getClass() + result = this.getAReturnedNode().(ControlFlowNodeWithPointsTo).pointsTo().getClass() } } diff --git a/python/ql/lib/semmle/python/types/ClassObject.qll b/python/ql/lib/semmle/python/types/ClassObject.qll index e3ad51ea1626..6954a83463c6 100644 --- a/python/ql/lib/semmle/python/types/ClassObject.qll +++ b/python/ql/lib/semmle/python/types/ClassObject.qll @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo private import semmle.python.objects.Classes private import semmle.python.objects.Instances private import semmle.python.pointsto.PointsTo @@ -193,7 +194,9 @@ class ClassObject extends Object { * It is guaranteed that getProbableSingletonInstance() returns at most one Object for each ClassObject. */ Object getProbableSingletonInstance() { - exists(ControlFlowNode use, Expr origin | use.refersTo(result, this, origin.getAFlowNode()) | + exists(ControlFlowNodeWithPointsTo use, Expr origin | + use.refersTo(result, this, origin.getAFlowNode()) + | this.hasStaticallyUniqueInstance() and /* Ensure that original expression will be executed only one. */ origin.getScope() instanceof ImportTimeScope and @@ -351,7 +354,7 @@ class ClassObject extends Object { * Gets a call to this class. Note that the call may not create a new instance of * this class, as that depends on the `__new__` method of this class. */ - CallNode getACall() { result.getFunction().refersTo(this) } + CallNode getACall() { result.getFunction().(ControlFlowNodeWithPointsTo).refersTo(this) } override predicate notClass() { none() } } diff --git a/python/ql/lib/semmle/python/types/Exceptions.qll b/python/ql/lib/semmle/python/types/Exceptions.qll index 93bace1cf516..5e982aa01346 100644 --- a/python/ql/lib/semmle/python/types/Exceptions.qll +++ b/python/ql/lib/semmle/python/types/Exceptions.qll @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo /** The subset of ControlFlowNodes which might raise an exception */ class RaisingNode extends ControlFlowNode { @@ -30,7 +31,9 @@ class RaisingNode extends ControlFlowNode { ) } - private predicate quits() { this.(CallNode).getFunction().refersTo(Object::quitter(_)) } + private predicate quits() { + this.(CallNode).getFunction().(ControlFlowNodeWithPointsTo).refersTo(Object::quitter(_)) + } /** * Gets the type of an exception that may be raised @@ -68,7 +71,7 @@ class RaisingNode extends ControlFlowNode { private ClassObject localRaisedType_objectapi() { result.isSubclassOf(theBaseExceptionType()) and ( - exists(ControlFlowNode ex | + exists(ControlFlowNodeWithPointsTo ex | ex = this.getExceptionNode() and (ex.refersTo(result) or ex.refersTo(_, result, _)) ) @@ -95,7 +98,7 @@ class RaisingNode extends ControlFlowNode { private ClassValue localRaisedType() { result.getASuperType() = ClassValue::baseException() and ( - exists(ControlFlowNode ex | + exists(ControlFlowNodeWithPointsTo ex | ex = this.getExceptionNode() and (ex.pointsTo(result) or ex.pointsTo().getClass() = result) ) @@ -153,7 +156,9 @@ class RaisingNode extends ControlFlowNode { /* Call to an unknown object */ this.getNode() instanceof Call and not exists(FunctionObject func | this = func.getACall()) and - not exists(ClassObject known | this.(CallNode).getFunction().refersTo(known)) + not exists(ClassObject known | + this.(CallNode).getFunction().(ControlFlowNodeWithPointsTo).refersTo(known) + ) or this.getNode() instanceof Exec or @@ -371,7 +376,7 @@ class ExceptFlowNode extends ControlFlowNode { * Gets the type handled by this exception handler. * `ExceptionType` in `except ExceptionType as e:` */ - ControlFlowNode getType() { + ControlFlowNodeWithPointsTo getType() { exists(ExceptStmt ex | this.getBasicBlock().dominates(result.getBasicBlock()) and ex = this.getNode() and @@ -470,7 +475,7 @@ class ExceptGroupFlowNode extends ControlFlowNode { } } -private ControlFlowNode element_from_tuple_objectapi(Object tuple) { +private ControlFlowNodeWithPointsTo element_from_tuple_objectapi(Object tuple) { exists(Tuple t | t = tuple.getOrigin() and result = t.getAnElt().getAFlowNode()) } diff --git a/python/ql/lib/semmle/python/types/FunctionObject.qll b/python/ql/lib/semmle/python/types/FunctionObject.qll index f64c02b9c6bf..72ddb9411fb1 100644 --- a/python/ql/lib/semmle/python/types/FunctionObject.qll +++ b/python/ql/lib/semmle/python/types/FunctionObject.qll @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo import semmle.python.types.Exceptions private import semmle.python.pointsto.PointsTo private import semmle.python.objects.Callables @@ -32,27 +33,31 @@ abstract class FunctionObject extends Object { abstract string descriptiveString(); /** Gets a call-site from where this function is called as a function */ - CallNode getAFunctionCall() { result.getFunction().inferredValue() = this.theCallable() } + CallNode getAFunctionCall() { + result.getFunction().(ControlFlowNodeWithPointsTo).inferredValue() = this.theCallable() + } /** Gets a call-site from where this function is called as a method */ CallNode getAMethodCall() { exists(BoundMethodObjectInternal bm | - result.getFunction().inferredValue() = bm and + result.getFunction().(ControlFlowNodeWithPointsTo).inferredValue() = bm and bm.getFunction() = this.theCallable() ) } /** Gets a call-site from where this function is called */ - ControlFlowNode getACall() { result = this.theCallable().getACall() } + ControlFlowNodeWithPointsTo getACall() { result = this.theCallable().getACall() } /** Gets a call-site from where this function is called, given the `context` */ - ControlFlowNode getACall(Context context) { result = this.theCallable().getACall(context) } + ControlFlowNodeWithPointsTo getACall(Context context) { + result = this.theCallable().getACall(context) + } /** * Gets the `ControlFlowNode` that will be passed as the nth argument to `this` when called at `call`. * This predicate will correctly handle `x.y()`, treating `x` as the zeroth argument. */ - ControlFlowNode getArgumentForCall(CallNode call, int n) { + ControlFlowNodeWithPointsTo getArgumentForCall(CallNode call, int n) { result = this.theCallable().getArgumentForCall(call, n) } @@ -60,7 +65,7 @@ abstract class FunctionObject extends Object { * Gets the `ControlFlowNode` that will be passed as the named argument to `this` when called at `call`. * This predicate will correctly handle `x.y()`, treating `x` as the self argument. */ - ControlFlowNode getNamedArgumentForCall(CallNode call, string name) { + ControlFlowNodeWithPointsTo getNamedArgumentForCall(CallNode call, string name) { result = this.theCallable().getNamedArgumentForCall(call, name) } @@ -134,7 +139,9 @@ class PyFunctionObject extends FunctionObject { override predicate raisesUnknownType() { scope_raises_unknown(this.getFunction()) } /** Gets a control flow node corresponding to the value of a return statement */ - ControlFlowNode getAReturnedNode() { result = this.getFunction().getAReturnValueFlowNode() } + ControlFlowNodeWithPointsTo getAReturnedNode() { + result = this.getFunction().getAReturnValueFlowNode() + } override string descriptiveString() { if this.getFunction().isMethod() @@ -216,7 +223,7 @@ abstract class BuiltinCallable extends FunctionObject { abstract override string getQualifiedName(); - override ControlFlowNode getArgumentForCall(CallNode call, int n) { + override ControlFlowNodeWithPointsTo getArgumentForCall(CallNode call, int n) { call = this.getACall() and result = call.getArg(n) } } diff --git a/python/ql/lib/semmle/python/types/Object.qll b/python/ql/lib/semmle/python/types/Object.qll index 6c76067dc68e..1e0868648be0 100644 --- a/python/ql/lib/semmle/python/types/Object.qll +++ b/python/ql/lib/semmle/python/types/Object.qll @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo private import semmle.python.objects.ObjectInternal private import semmle.python.types.Builtins private import semmle.python.internal.CachedStages @@ -41,7 +42,7 @@ class Object extends @py_object { * for a control flow node 'f' */ ClassObject getAnInferredType() { - exists(ControlFlowNode somewhere | somewhere.refersTo(this, result, _)) + exists(ControlFlowNodeWithPointsTo somewhere | somewhere.refersTo(this, result, _)) or this.asBuiltin().getClass() = result.asBuiltin() and not this = unknownValue() or @@ -327,7 +328,7 @@ abstract class SequenceObject extends Object { Object getInferredElement(int n) { result = this.getBuiltinElement(n) or - this.getSourceElement(n).refersTo(result) + this.getSourceElement(n).(ControlFlowNodeWithPointsTo).refersTo(result) } } @@ -438,7 +439,8 @@ class SuperBoundMethod extends Object { string name; SuperBoundMethod() { - this.(AttrNode).getObject(name).inferredValue().getClass() = Value::named("super") + this.(AttrNode).getObject(name).(ControlFlowNodeWithPointsTo).inferredValue().getClass() = + Value::named("super") } override string toString() { result = "super()." + name } @@ -446,7 +448,7 @@ class SuperBoundMethod extends Object { Object getFunction(string fname) { fname = name and exists(SuperInstance sup, BoundMethodObjectInternal m | - sup = this.(AttrNode).getObject(name).inferredValue() and + sup = this.(AttrNode).getObject(name).(ControlFlowNodeWithPointsTo).inferredValue() and sup.attribute(name, m, _) and result = m.getFunction().getSource() ) diff --git a/python/ql/lib/semmle/python/types/Properties.qll b/python/ql/lib/semmle/python/types/Properties.qll index a0efe6ca5eb9..899f0a3407ec 100644 --- a/python/ql/lib/semmle/python/types/Properties.qll +++ b/python/ql/lib/semmle/python/types/Properties.qll @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo /** * A Python property: @@ -77,32 +78,32 @@ class BuiltinPropertyObject extends PropertyObject { } private predicate property_getter(CallNode decorated, FunctionObject getter) { - decorated.getFunction().refersTo(thePropertyType()) and - decorated.getArg(0).refersTo(getter) + decorated.getFunction().(ControlFlowNodeWithPointsTo).refersTo(thePropertyType()) and + decorated.getArg(0).(ControlFlowNodeWithPointsTo).refersTo(getter) } private predicate property_setter(CallNode decorated, FunctionObject setter) { property_getter(decorated, _) and exists(CallNode setter_call, AttrNode prop_setter | - prop_setter.getObject("setter").refersTo(decorated) + prop_setter.getObject("setter").(ControlFlowNodeWithPointsTo).refersTo(decorated) | - setter_call.getArg(0).refersTo(setter) and + setter_call.getArg(0).(ControlFlowNodeWithPointsTo).refersTo(setter) and setter_call.getFunction() = prop_setter ) or - decorated.getFunction().refersTo(thePropertyType()) and - decorated.getArg(1).refersTo(setter) + decorated.getFunction().(ControlFlowNodeWithPointsTo).refersTo(thePropertyType()) and + decorated.getArg(1).(ControlFlowNodeWithPointsTo).refersTo(setter) } private predicate property_deleter(CallNode decorated, FunctionObject deleter) { property_getter(decorated, _) and exists(CallNode deleter_call, AttrNode prop_deleter | - prop_deleter.getObject("deleter").refersTo(decorated) + prop_deleter.getObject("deleter").(ControlFlowNodeWithPointsTo).refersTo(decorated) | - deleter_call.getArg(0).refersTo(deleter) and + deleter_call.getArg(0).(ControlFlowNodeWithPointsTo).refersTo(deleter) and deleter_call.getFunction() = prop_deleter ) or - decorated.getFunction().refersTo(thePropertyType()) and - decorated.getArg(2).refersTo(deleter) + decorated.getFunction().(ControlFlowNodeWithPointsTo).refersTo(thePropertyType()) and + decorated.getArg(2).(ControlFlowNodeWithPointsTo).refersTo(deleter) } diff --git a/python/ql/lib/semmle/python/values/StringAttributes.qll b/python/ql/lib/semmle/python/values/StringAttributes.qll index 792ee9232275..e94540dbf204 100644 --- a/python/ql/lib/semmle/python/values/StringAttributes.qll +++ b/python/ql/lib/semmle/python/values/StringAttributes.qll @@ -1,6 +1,10 @@ import python +private import LegacyPointsTo +private import semmle.python.types.Object +private import semmle.python.types.ClassObject +private import semmle.python.types.FunctionObject -predicate string_attribute_all(ControlFlowNode n, string attr) { +predicate string_attribute_all(ControlFlowNodeWithPointsTo n, string attr) { (n.getNode() instanceof Unicode or n.getNode() instanceof Bytes) and attr = "const" or @@ -19,18 +23,27 @@ predicate tracked_object(ControlFlowNode obj, string attr) { tracked_object_any(obj, attr) } -predicate open_file(Object obj) { obj.(CallNode).getFunction().refersTo(Object::builtin("open")) } +predicate open_file(Object obj) { + obj.(CallNode).getFunction().(ControlFlowNodeWithPointsTo).refersTo(Object::builtin("open")) +} -predicate string_attribute_any(ControlFlowNode n, string attr) { +predicate string_attribute_any(ControlFlowNodeWithPointsTo n, string attr) { attr = "user-input" and - exists(Object input | n.(CallNode).getFunction().refersTo(input) | + exists(Object input | n.(CallNode).getFunction().(ControlFlowNodeWithPointsTo).refersTo(input) | if major_version() = 2 then input = Object::builtin("raw_input") else input = Object::builtin("input") ) or attr = "file-input" and - exists(Object fd | n.(CallNode).getFunction().(AttrNode).getObject("read").refersTo(fd) | + exists(Object fd | + n.(CallNode) + .getFunction() + .(AttrNode) + .getObject("read") + .(ControlFlowNodeWithPointsTo) + .refersTo(fd) + | open_file(fd) ) or @@ -65,7 +78,7 @@ ControlFlowNode sequence_for_iterator(ControlFlowNode f) { } pragma[noinline] -private predicate tracking_step(ControlFlowNode src, ControlFlowNode dest) { +private predicate tracking_step(ControlFlowNode src, ControlFlowNodeWithPointsTo dest) { src = dest.(BinaryExprNode).getAnOperand() or src = dest.(UnaryExprNode).getOperand() diff --git a/python/ql/src/Expressions/ContainsNonContainer.ql b/python/ql/src/Expressions/ContainsNonContainer.ql index cf6af5ce7b18..fd2123dd436e 100644 --- a/python/ql/src/Expressions/ContainsNonContainer.ql +++ b/python/ql/src/Expressions/ContainsNonContainer.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo import semmle.python.pointsto.PointsTo predicate rhs_in_expr(ControlFlowNode rhs, Compare cmp) { @@ -20,7 +21,8 @@ predicate rhs_in_expr(ControlFlowNode rhs, Compare cmp) { ) } -from ControlFlowNode non_seq, Compare cmp, Value v, ClassValue cls, ControlFlowNode origin +from + ControlFlowNodeWithPointsTo non_seq, Compare cmp, Value v, ClassValue cls, ControlFlowNode origin where rhs_in_expr(non_seq, cmp) and non_seq.pointsTo(_, v, origin) and diff --git a/python/ql/src/Expressions/Formatting/AdvancedFormatting.qll b/python/ql/src/Expressions/Formatting/AdvancedFormatting.qll index 7da80ffa0278..d98286d85faf 100644 --- a/python/ql/src/Expressions/Formatting/AdvancedFormatting.qll +++ b/python/ql/src/Expressions/Formatting/AdvancedFormatting.qll @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo /** A string constant that looks like it may be used in string formatting operations. */ class PossibleAdvancedFormatString extends StringLiteral { @@ -98,11 +99,15 @@ private predicate brace_pair(PossibleAdvancedFormatString fmt, int start, int en private predicate advanced_format_call(Call format_expr, PossibleAdvancedFormatString fmt, int args) { exists(CallNode call | call = format_expr.getAFlowNode() | - call.getFunction().pointsTo(Value::named("format")) and - call.getArg(0).pointsTo(_, fmt.getAFlowNode()) and + call.getFunction().(ControlFlowNodeWithPointsTo).pointsTo(Value::named("format")) and + call.getArg(0).(ControlFlowNodeWithPointsTo).pointsTo(_, fmt.getAFlowNode()) and args = count(format_expr.getAnArg()) - 1 or - call.getFunction().(AttrNode).getObject("format").pointsTo(_, fmt.getAFlowNode()) and + call.getFunction() + .(AttrNode) + .getObject("format") + .(ControlFlowNodeWithPointsTo) + .pointsTo(_, fmt.getAFlowNode()) and args = count(format_expr.getAnArg()) ) } diff --git a/python/ql/src/Expressions/HashedButNoHash.ql b/python/ql/src/Expressions/HashedButNoHash.ql index eb86f3b55332..795865987603 100644 --- a/python/ql/src/Expressions/HashedButNoHash.ql +++ b/python/ql/src/Expressions/HashedButNoHash.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo /* * This assumes that any indexing operation where the value is not a sequence or numpy array involves hashing. @@ -41,13 +42,13 @@ predicate unhashable_subscript(ControlFlowNode f, ClassValue c, ControlFlowNode is_unhashable(f, c, origin) and exists(SubscriptNode sub | sub.getIndex() = f | exists(Value custom_getitem | - sub.getObject().pointsTo(custom_getitem) and + sub.getObject().(ControlFlowNodeWithPointsTo).pointsTo(custom_getitem) and not has_custom_getitem(custom_getitem) ) ) } -predicate is_unhashable(ControlFlowNode f, ClassValue cls, ControlFlowNode origin) { +predicate is_unhashable(ControlFlowNodeWithPointsTo f, ClassValue cls, ControlFlowNode origin) { exists(Value v | f.pointsTo(v, origin) and v.getClass() = cls | not cls.hasAttribute("__hash__") and not cls.failedInference(_) and cls.isNewStyle() or diff --git a/python/ql/src/Expressions/IsComparisons.qll b/python/ql/src/Expressions/IsComparisons.qll index 7825d01999b9..25058206c862 100644 --- a/python/ql/src/Expressions/IsComparisons.qll +++ b/python/ql/src/Expressions/IsComparisons.qll @@ -1,6 +1,7 @@ /** INTERNAL - Helper predicates for queries that inspect the comparison of objects using `is`. */ import python +private import LegacyPointsTo /** Holds if the comparison `comp` uses `is` or `is not` (represented as `op`) to compare its `left` and `right` arguments. */ predicate comparison_using_is(Compare comp, ControlFlowNode left, Cmpop op, ControlFlowNode right) { @@ -42,7 +43,7 @@ predicate invalid_to_use_is_portably(ClassValue c) { } /** Holds if the control flow node `f` points to either `True`, `False`, or `None`. */ -predicate simple_constant(ControlFlowNode f) { +predicate simple_constant(ControlFlowNodeWithPointsTo f) { exists(Value val | f.pointsTo(val) | val = Value::named("True") or val = Value::named("False") or val = Value::named("None") ) @@ -84,7 +85,7 @@ predicate universally_interned_constant(Expr e) { } private predicate comparison_both_types(Compare comp, Cmpop op, ClassValue cls1, ClassValue cls2) { - exists(ControlFlowNode op1, ControlFlowNode op2 | + exists(ControlFlowNodeWithPointsTo op1, ControlFlowNodeWithPointsTo op2 | comparison_using_is(comp, op1, op, op2) or comparison_using_is(comp, op2, op, op1) | op1.inferredValue().getClass() = cls1 and @@ -94,7 +95,7 @@ private predicate comparison_both_types(Compare comp, Cmpop op, ClassValue cls1, private predicate comparison_one_type(Compare comp, Cmpop op, ClassValue cls) { not comparison_both_types(comp, _, _, _) and - exists(ControlFlowNode operand | + exists(ControlFlowNodeWithPointsTo operand | comparison_using_is(comp, operand, op, _) or comparison_using_is(comp, _, op, operand) | operand.inferredValue().getClass() = cls diff --git a/python/ql/src/Expressions/TruncatedDivision.ql b/python/ql/src/Expressions/TruncatedDivision.ql index 54758b4b78e2..c731a21f7d26 100644 --- a/python/ql/src/Expressions/TruncatedDivision.ql +++ b/python/ql/src/Expressions/TruncatedDivision.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo from BinaryExpr div, ControlFlowNode left, ControlFlowNode right where @@ -20,9 +21,9 @@ where exists(BinaryExprNode bin, Value lval, Value rval | bin = div.getAFlowNode() and bin.getNode().getOp() instanceof Div and - bin.getLeft().pointsTo(lval, left) and + bin.getLeft().(ControlFlowNodeWithPointsTo).pointsTo(lval, left) and lval.getClass() = ClassValue::int_() and - bin.getRight().pointsTo(rval, right) and + bin.getRight().(ControlFlowNodeWithPointsTo).pointsTo(rval, right) and rval.getClass() = ClassValue::int_() and // Ignore instances where integer division leaves no remainder not lval.(NumericValue).getIntValue() % rval.(NumericValue).getIntValue() = 0 and diff --git a/python/ql/src/Expressions/UseofApply.ql b/python/ql/src/Expressions/UseofApply.ql index 7a0d72b43cf6..2012f2d93618 100644 --- a/python/ql/src/Expressions/UseofApply.ql +++ b/python/ql/src/Expressions/UseofApply.ql @@ -10,8 +10,9 @@ */ import python +private import LegacyPointsTo private import semmle.python.types.Builtins -from CallNode call, ControlFlowNode func +from CallNode call, ControlFlowNodeWithPointsTo func where major_version() = 2 and call.getFunction() = func and func.pointsTo(Value::named("apply")) select call, "Call to the obsolete builtin function 'apply'." diff --git a/python/ql/src/Imports/FromImportOfMutableAttribute.ql b/python/ql/src/Imports/FromImportOfMutableAttribute.ql index c66a7578de61..63198bece30c 100644 --- a/python/ql/src/Imports/FromImportOfMutableAttribute.ql +++ b/python/ql/src/Imports/FromImportOfMutableAttribute.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo import semmle.python.filters.Tests from ImportMember im, ModuleValue m, AttrNode store_attr, string name @@ -23,7 +24,7 @@ where /* variable resulting from import must have a long lifetime */ not im.getScope() instanceof Function and store_attr.isStore() and - store_attr.getObject(name).pointsTo(m) and + store_attr.getObject(name).(ControlFlowNodeWithPointsTo).pointsTo(m) and /* Import not in same module as modification. */ not im.getEnclosingModule() = store_attr.getScope().getEnclosingModule() and /* Modification is not in a test */ diff --git a/python/ql/src/Statements/IterableStringOrSequence.ql b/python/ql/src/Statements/IterableStringOrSequence.ql index 5cf92754f622..d1c4a507f0d1 100644 --- a/python/ql/src/Statements/IterableStringOrSequence.ql +++ b/python/ql/src/Statements/IterableStringOrSequence.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo import semmle.python.filters.Tests predicate has_string_type(Value v) { @@ -21,7 +22,7 @@ predicate has_string_type(Value v) { } from - For loop, ControlFlowNode iter, Value str, Value seq, ControlFlowNode seq_origin, + For loop, ControlFlowNodeWithPointsTo iter, Value str, Value seq, ControlFlowNode seq_origin, ControlFlowNode str_origin where loop.getIter().getAFlowNode() = iter and diff --git a/python/ql/src/Statements/ModificationOfLocals.ql b/python/ql/src/Statements/ModificationOfLocals.ql index 05c2095f88cb..e4791a410f7a 100644 --- a/python/ql/src/Statements/ModificationOfLocals.ql +++ b/python/ql/src/Statements/ModificationOfLocals.ql @@ -12,8 +12,11 @@ */ import python +private import LegacyPointsTo -predicate originIsLocals(ControlFlowNode n) { n.pointsTo(_, _, Value::named("locals").getACall()) } +predicate originIsLocals(ControlFlowNodeWithPointsTo n) { + n.pointsTo(_, _, Value::named("locals").getACall()) +} predicate modification_of_locals(ControlFlowNode f) { originIsLocals(f.(SubscriptNode).getObject()) and diff --git a/python/ql/src/Statements/NonIteratorInForLoop.ql b/python/ql/src/Statements/NonIteratorInForLoop.ql index 92527a10e3bb..f8e6e51b55ff 100644 --- a/python/ql/src/Statements/NonIteratorInForLoop.ql +++ b/python/ql/src/Statements/NonIteratorInForLoop.ql @@ -12,8 +12,9 @@ */ import python +private import LegacyPointsTo -from For loop, ControlFlowNode iter, Value v, ClassValue t, ControlFlowNode origin +from For loop, ControlFlowNodeWithPointsTo iter, Value v, ClassValue t, ControlFlowNode origin where loop.getIter().getAFlowNode() = iter and iter.pointsTo(_, v, origin) and diff --git a/python/ql/src/Statements/ShouldUseWithStatement.ql b/python/ql/src/Statements/ShouldUseWithStatement.ql index 2ad76b5c832d..eb5cf9237d57 100644 --- a/python/ql/src/Statements/ShouldUseWithStatement.ql +++ b/python/ql/src/Statements/ShouldUseWithStatement.ql @@ -13,6 +13,7 @@ */ import python +private import LegacyPointsTo predicate calls_close(Call c) { exists(Attribute a | c.getFunc() = a and a.getName() = "close") } @@ -22,7 +23,7 @@ predicate only_stmt_in_finally(Try t, Call c) { ) } -predicate points_to_context_manager(ControlFlowNode f, ClassValue cls) { +predicate points_to_context_manager(ControlFlowNodeWithPointsTo f, ClassValue cls) { forex(Value v | f.pointsTo(v) | v.getClass() = cls) and cls.isContextManager() } diff --git a/python/ql/src/Statements/StringConcatenationInLoop.ql b/python/ql/src/Statements/StringConcatenationInLoop.ql index 563a42e5462a..c85292cf26aa 100644 --- a/python/ql/src/Statements/StringConcatenationInLoop.ql +++ b/python/ql/src/Statements/StringConcatenationInLoop.ql @@ -11,6 +11,7 @@ */ import python +private import LegacyPointsTo predicate string_concat_in_loop(BinaryExpr b) { b.getOp() instanceof Add and @@ -19,7 +20,7 @@ predicate string_concat_in_loop(BinaryExpr b) { | d.getDefinition().(DefinitionNode).getValue() = add and u.getAUse() = add.getAnOperand() and - add.getAnOperand().pointsTo().getClass() = ClassValue::str() + add.getAnOperand().(ControlFlowNodeWithPointsTo).pointsTo().getClass() = ClassValue::str() ) } diff --git a/python/ql/src/Statements/UseOfExit.ql b/python/ql/src/Statements/UseOfExit.ql index be3579481fcb..437ff93b5371 100644 --- a/python/ql/src/Statements/UseOfExit.ql +++ b/python/ql/src/Statements/UseOfExit.ql @@ -12,9 +12,10 @@ */ import python +private import LegacyPointsTo from CallNode call, string name -where call.getFunction().pointsTo(Value::siteQuitter(name)) +where call.getFunction().(ControlFlowNodeWithPointsTo).pointsTo(Value::siteQuitter(name)) select call, "The '" + name + "' site.Quitter object may not exist if the 'site' module is not loaded or is modified." diff --git a/python/ql/src/Testing/Mox.qll b/python/ql/src/Testing/Mox.qll index a131ca7eecaf..969c49c68438 100644 --- a/python/ql/src/Testing/Mox.qll +++ b/python/ql/src/Testing/Mox.qll @@ -1,9 +1,10 @@ import python +private import LegacyPointsTo /** Whether `mox` or `.StubOutWithMock()` is used in thin module `m`. */ predicate useOfMoxInModule(Module m) { exists(ModuleObject mox | mox.getName() = "mox" or mox.getName() = "mox3.mox" | - exists(ControlFlowNode use | + exists(ControlFlowNodeWithPointsTo use | use.refersTo(mox) and use.getScope().getEnclosingModule() = m ) diff --git a/python/ql/src/Variables/MonkeyPatched.qll b/python/ql/src/Variables/MonkeyPatched.qll index ab842afbf265..86d9edac0a9b 100644 --- a/python/ql/src/Variables/MonkeyPatched.qll +++ b/python/ql/src/Variables/MonkeyPatched.qll @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo predicate monkey_patched_builtin(string name) { exists(AttrNode attr, SubscriptNode subscr, StringLiteral s | @@ -6,19 +7,19 @@ predicate monkey_patched_builtin(string name) { subscr.getIndex().getNode() = s and s.getText() = name and subscr.getObject() = attr and - attr.getObject("__dict__").pointsTo(Module::builtinModule()) + attr.getObject("__dict__").(ControlFlowNodeWithPointsTo).pointsTo(Module::builtinModule()) ) or - exists(CallNode call, ControlFlowNode bltn, StringLiteral s | + exists(CallNode call, ControlFlowNodeWithPointsTo bltn, StringLiteral s | call.getArg(0) = bltn and bltn.pointsTo(Module::builtinModule()) and call.getArg(1).getNode() = s and s.getText() = name and - call.getFunction().pointsTo(Value::named("setattr")) + call.getFunction().(ControlFlowNodeWithPointsTo).pointsTo(Value::named("setattr")) ) or exists(AttrNode attr | attr.isStore() and - attr.getObject(name).pointsTo(Module::builtinModule()) + attr.getObject(name).(ControlFlowNodeWithPointsTo).pointsTo(Module::builtinModule()) ) } diff --git a/python/ql/src/Variables/ShadowGlobal.ql b/python/ql/src/Variables/ShadowGlobal.ql index 2f06e4fe57d7..fad86935cf1d 100644 --- a/python/ql/src/Variables/ShadowGlobal.ql +++ b/python/ql/src/Variables/ShadowGlobal.ql @@ -15,6 +15,7 @@ */ import python +private import LegacyPointsTo import Shadowing import semmle.python.types.Builtins @@ -35,7 +36,9 @@ predicate shadows(Name d, GlobalVariable g, Function scope, int line) { /* pytest dynamically populates its namespace so, we cannot look directly for the pytest.fixture function */ AttrNode pytest_fixture_attr() { - exists(ModuleValue pytest | result.getObject("fixture").pointsTo(pytest)) + exists(ModuleValue pytest | + result.getObject("fixture").(ControlFlowNodeWithPointsTo).pointsTo(pytest) + ) } Value pytest_fixture() { @@ -44,14 +47,15 @@ Value pytest_fixture() { or call.getFunction().(CallNode).getFunction() = pytest_fixture_attr() | - call.pointsTo(result) + call.(ControlFlowNodeWithPointsTo).pointsTo(result) ) } /* pytest fixtures require that the parameter name is also a global */ predicate assigned_pytest_fixture(GlobalVariable v) { exists(NameNode def | - def.defines(v) and def.(DefinitionNode).getValue().pointsTo(pytest_fixture()) + def.defines(v) and + def.(DefinitionNode).getValue().(ControlFlowNodeWithPointsTo).pointsTo(pytest_fixture()) ) } diff --git a/python/ql/src/Variables/SuspiciousUnusedLoopIterationVariable.ql b/python/ql/src/Variables/SuspiciousUnusedLoopIterationVariable.ql index fbeb9b2b4f96..87900c48fc58 100644 --- a/python/ql/src/Variables/SuspiciousUnusedLoopIterationVariable.ql +++ b/python/ql/src/Variables/SuspiciousUnusedLoopIterationVariable.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo import Definition predicate is_increment(Stmt s) { @@ -55,7 +56,7 @@ predicate points_to_call_to_range(ControlFlowNode f) { ) or /* Handle list(range(...)) and list(list(range(...))) */ - f.(CallNode).pointsTo().getClass() = ClassValue::list() and + f.(CallNode).(ControlFlowNodeWithPointsTo).pointsTo().getClass() = ClassValue::list() and points_to_call_to_range(f.(CallNode).getArg(0)) } diff --git a/python/ql/src/Variables/UndefinedExport.ql b/python/ql/src/Variables/UndefinedExport.ql index 173139e224a8..ff3f78ec4bcc 100644 --- a/python/ql/src/Variables/UndefinedExport.ql +++ b/python/ql/src/Variables/UndefinedExport.ql @@ -13,6 +13,7 @@ */ import python +private import LegacyPointsTo /** Whether name is declared in the __all__ list of this module */ predicate declaredInAll(Module m, StringLiteral name) { @@ -44,7 +45,7 @@ predicate mutates_globals(ModuleValue m) { enum_convert = enum_class.attr("_convert") and exists(CallNode call | call.getScope() = m.getScope() | enum_convert.getACall() = call or - call.getFunction().pointsTo(enum_convert) + call.getFunction().(ControlFlowNodeWithPointsTo).pointsTo(enum_convert) ) ) or @@ -52,7 +53,11 @@ predicate mutates_globals(ModuleValue m) { // analysis doesn't handle that well enough. So we need a special case for this not exists(enum_class.attr("_convert")) and exists(CallNode call | call.getScope() = m.getScope() | - call.getFunction().(AttrNode).getObject(["_convert", "_convert_"]).pointsTo() = enum_class + call.getFunction() + .(AttrNode) + .getObject(["_convert", "_convert_"]) + .(ControlFlowNodeWithPointsTo) + .pointsTo() = enum_class ) ) ) @@ -65,9 +70,9 @@ predicate is_exported_submodule_name(ModuleValue m, string exported_name) { predicate contains_unknown_import_star(ModuleValue m) { exists(ImportStarNode imp | imp.getEnclosingModule() = m.getScope() | - imp.getModule().pointsTo().isAbsent() + imp.getModule().(ControlFlowNodeWithPointsTo).pointsTo().isAbsent() or - not exists(imp.getModule().pointsTo()) + not exists(imp.getModule().(ControlFlowNodeWithPointsTo).pointsTo()) ) } diff --git a/python/ql/src/analysis/Consistency.ql b/python/ql/src/analysis/Consistency.ql index f7d80a5da957..aafb461a5045 100644 --- a/python/ql/src/analysis/Consistency.ql +++ b/python/ql/src/analysis/Consistency.ql @@ -5,6 +5,7 @@ */ import python +private import LegacyPointsTo import analysis.DefinitionTracking predicate uniqueness_error(int number, string what, string problem) { @@ -208,18 +209,22 @@ predicate function_object_consistency(string clsname, string problem, string wha predicate multiple_origins_per_object(Object obj) { not obj.isC() and not obj instanceof ModuleObject and - exists(ControlFlowNode use, Context ctx | + exists(ControlFlowNodeWithPointsTo use, Context ctx | strictcount(ControlFlowNode orig | use.refersTo(ctx, obj, _, orig)) > 1 ) } -predicate intermediate_origins(ControlFlowNode use, ControlFlowNode inter, Object obj) { +predicate intermediate_origins( + ControlFlowNodeWithPointsTo use, ControlFlowNodeWithPointsTo inter, Object obj +) { exists(ControlFlowNode orig, Context ctx | not inter = orig | use.refersTo(ctx, obj, _, inter) and inter.refersTo(ctx, obj, _, orig) and // It can sometimes happen that two different modules (e.g. cPickle and Pickle) // have the same attribute, but different origins. - not strictcount(Object val | inter.(AttrNode).getObject().refersTo(val)) > 1 + not strictcount(Object val | + inter.(AttrNode).getObject().(ControlFlowNodeWithPointsTo).refersTo(val) + ) > 1 ) } diff --git a/python/ql/src/analysis/Efficiency.ql b/python/ql/src/analysis/Efficiency.ql index ff44fc2c47d0..37cb5c973879 100644 --- a/python/ql/src/analysis/Efficiency.ql +++ b/python/ql/src/analysis/Efficiency.ql @@ -4,6 +4,7 @@ */ import python +private import LegacyPointsTo import semmle.python.pointsto.PointsTo import semmle.python.pointsto.PointsToContext @@ -18,11 +19,11 @@ predicate trivial(ControlFlowNode f) { from int interesting_facts, int interesting_facts_in_source, int total_size, float efficiency where interesting_facts = - strictcount(ControlFlowNode f, Object value, ClassObject cls | + strictcount(ControlFlowNodeWithPointsTo f, Object value, ClassObject cls | f.refersTo(value, cls, _) and not trivial(f) ) and interesting_facts_in_source = - strictcount(ControlFlowNode f, Object value, ClassObject cls | + strictcount(ControlFlowNodeWithPointsTo f, Object value, ClassObject cls | f.refersTo(value, cls, _) and not trivial(f) and exists(f.getScope().getEnclosingModule().getFile().getRelativePath()) diff --git a/python/ql/src/analysis/ImportFailure.ql b/python/ql/src/analysis/ImportFailure.ql index 62de72f3b3ea..9dd6ac52adcf 100644 --- a/python/ql/src/analysis/ImportFailure.ql +++ b/python/ql/src/analysis/ImportFailure.ql @@ -7,6 +7,7 @@ */ import python +private import LegacyPointsTo ImportExpr alternative_import(ImportExpr ie) { exists(Alias thisalias, Alias otheralias | @@ -62,7 +63,10 @@ class VersionTest extends ControlFlowNode { VersionTest() { exists(string name | name.matches("%version%") and - this.(CompareNode).getAChild+().pointsTo(Module::named("sys").attr(name)) + this.(CompareNode) + .getAChild+() + .(ControlFlowNodeWithPointsTo) + .pointsTo(Module::named("sys").attr(name)) ) } diff --git a/python/ql/src/analysis/PointsToFailure.ql b/python/ql/src/analysis/PointsToFailure.ql index 66ff2d811a36..7b9a2ac06595 100644 --- a/python/ql/src/analysis/PointsToFailure.ql +++ b/python/ql/src/analysis/PointsToFailure.ql @@ -9,7 +9,8 @@ */ import python +private import LegacyPointsTo from Expr e -where exists(ControlFlowNode f | f = e.getAFlowNode() | not f.refersTo(_)) +where exists(ControlFlowNodeWithPointsTo f | f = e.getAFlowNode() | not f.refersTo(_)) select e, "Expression does not 'point-to' any object." diff --git a/python/ql/src/analysis/TypeInferenceFailure.ql b/python/ql/src/analysis/TypeInferenceFailure.ql index 70c4e880879d..5cfafee36b1e 100644 --- a/python/ql/src/analysis/TypeInferenceFailure.ql +++ b/python/ql/src/analysis/TypeInferenceFailure.ql @@ -8,8 +8,9 @@ */ import python +private import LegacyPointsTo -from ControlFlowNode f, Object o +from ControlFlowNodeWithPointsTo f, Object o where f.refersTo(o) and not f.refersTo(o, _, _) diff --git a/python/ql/test/2/library-tests/PointsTo/class_properties/ClassValues.ql b/python/ql/test/2/library-tests/PointsTo/class_properties/ClassValues.ql index 3281b8d26e64..382312a4b5c6 100644 --- a/python/ql/test/2/library-tests/PointsTo/class_properties/ClassValues.ql +++ b/python/ql/test/2/library-tests/PointsTo/class_properties/ClassValues.ql @@ -1,10 +1,11 @@ import python +private import LegacyPointsTo from ClassValue cls, string res where exists(CallNode call | call.getFunction().(NameNode).getId() = "test" and - call.getAnArg().pointsTo(cls) + call.getAnArg().(ControlFlowNodeWithPointsTo).pointsTo(cls) ) and ( cls.isSequence() and diff --git a/python/ql/test/2/library-tests/PointsTo/imports/Runtime.ql b/python/ql/test/2/library-tests/PointsTo/imports/Runtime.ql index 7a46cc8cad13..aad100c14d52 100644 --- a/python/ql/test/2/library-tests/PointsTo/imports/Runtime.ql +++ b/python/ql/test/2/library-tests/PointsTo/imports/Runtime.ql @@ -1,6 +1,7 @@ import python +private import LegacyPointsTo -from int line, ControlFlowNode f, Object o, ControlFlowNode orig +from int line, ControlFlowNodeWithPointsTo f, Object o, ControlFlowNode orig where not f.getLocation().getFile().inStdlib() and f.refersTo(o, orig) and diff --git a/python/ql/test/2/library-tests/PointsTo/imports2/Runtime.ql b/python/ql/test/2/library-tests/PointsTo/imports2/Runtime.ql index f694bc64cf01..19add3600a04 100644 --- a/python/ql/test/2/library-tests/PointsTo/imports2/Runtime.ql +++ b/python/ql/test/2/library-tests/PointsTo/imports2/Runtime.ql @@ -1,6 +1,7 @@ import python +private import LegacyPointsTo -from int line, ControlFlowNode f, Object o, ControlFlowNode orig +from int line, ControlFlowNodeWithPointsTo f, Object o, ControlFlowNode orig where not f.getLocation().getFile().inStdlib() and f.refersTo(o, orig) and diff --git a/python/ql/test/2/library-tests/PointsTo/imports2/RuntimeWithType.ql b/python/ql/test/2/library-tests/PointsTo/imports2/RuntimeWithType.ql index 99a5f7b81630..09c330596c96 100644 --- a/python/ql/test/2/library-tests/PointsTo/imports2/RuntimeWithType.ql +++ b/python/ql/test/2/library-tests/PointsTo/imports2/RuntimeWithType.ql @@ -1,6 +1,7 @@ import python +private import LegacyPointsTo -from int line, ControlFlowNode f, Object o, ClassObject cls, ControlFlowNode orig +from int line, ControlFlowNodeWithPointsTo f, Object o, ClassObject cls, ControlFlowNode orig where not f.getLocation().getFile().inStdlib() and f.refersTo(o, cls, orig) and diff --git a/python/ql/test/2/library-tests/PointsTo/origin_uniqueness/Origin.ql b/python/ql/test/2/library-tests/PointsTo/origin_uniqueness/Origin.ql index 4c7a4fff3588..3f923bc63fa3 100644 --- a/python/ql/test/2/library-tests/PointsTo/origin_uniqueness/Origin.ql +++ b/python/ql/test/2/library-tests/PointsTo/origin_uniqueness/Origin.ql @@ -1,8 +1,9 @@ import python +private import LegacyPointsTo string short_loc(Location l) { result = l.getFile().getShortName() + ":" + l.getStartLine() } -from ControlFlowNode use, Object obj, ControlFlowNode orig, int line +from ControlFlowNodeWithPointsTo use, Object obj, ControlFlowNode orig, int line where use.refersTo(obj, orig) and use.getLocation().getFile().getShortName() = "test.py" and diff --git a/python/ql/test/3/library-tests/PointsTo/attributes/Test.ql b/python/ql/test/3/library-tests/PointsTo/attributes/Test.ql index cc191d7c7d84..ad7b74f8c581 100644 --- a/python/ql/test/3/library-tests/PointsTo/attributes/Test.ql +++ b/python/ql/test/3/library-tests/PointsTo/attributes/Test.ql @@ -1,5 +1,6 @@ import python +private import LegacyPointsTo -from ControlFlowNode f, Object o, ControlFlowNode x +from ControlFlowNodeWithPointsTo f, Object o, ControlFlowNode x where f.refersTo(o, x) select f.getLocation().getStartLine(), f.toString(), o.toString(), x.getLocation().getStartLine() diff --git a/python/ql/test/3/library-tests/PointsTo/attributes/TestWithType.ql b/python/ql/test/3/library-tests/PointsTo/attributes/TestWithType.ql index 2b4b8a8c70ca..dc19fefb4ce3 100644 --- a/python/ql/test/3/library-tests/PointsTo/attributes/TestWithType.ql +++ b/python/ql/test/3/library-tests/PointsTo/attributes/TestWithType.ql @@ -1,6 +1,7 @@ import python +private import LegacyPointsTo -from ControlFlowNode f, Object o, ClassObject c, ControlFlowNode x +from ControlFlowNodeWithPointsTo f, Object o, ClassObject c, ControlFlowNode x where f.refersTo(o, c, x) select f.getLocation().getStartLine(), f.toString(), o.toString(), c.toString(), x.getLocation().getStartLine() diff --git a/python/ql/test/3/library-tests/PointsTo/class_properties/ClassValues.ql b/python/ql/test/3/library-tests/PointsTo/class_properties/ClassValues.ql index 3281b8d26e64..382312a4b5c6 100644 --- a/python/ql/test/3/library-tests/PointsTo/class_properties/ClassValues.ql +++ b/python/ql/test/3/library-tests/PointsTo/class_properties/ClassValues.ql @@ -1,10 +1,11 @@ import python +private import LegacyPointsTo from ClassValue cls, string res where exists(CallNode call | call.getFunction().(NameNode).getId() = "test" and - call.getAnArg().pointsTo(cls) + call.getAnArg().(ControlFlowNodeWithPointsTo).pointsTo(cls) ) and ( cls.isSequence() and diff --git a/python/ql/test/3/library-tests/PointsTo/imports/Runtime.ql b/python/ql/test/3/library-tests/PointsTo/imports/Runtime.ql index f694bc64cf01..19add3600a04 100644 --- a/python/ql/test/3/library-tests/PointsTo/imports/Runtime.ql +++ b/python/ql/test/3/library-tests/PointsTo/imports/Runtime.ql @@ -1,6 +1,7 @@ import python +private import LegacyPointsTo -from int line, ControlFlowNode f, Object o, ControlFlowNode orig +from int line, ControlFlowNodeWithPointsTo f, Object o, ControlFlowNode orig where not f.getLocation().getFile().inStdlib() and f.refersTo(o, orig) and diff --git a/python/ql/test/3/library-tests/PointsTo/imports/RuntimeWithType.ql b/python/ql/test/3/library-tests/PointsTo/imports/RuntimeWithType.ql index 99a5f7b81630..09c330596c96 100644 --- a/python/ql/test/3/library-tests/PointsTo/imports/RuntimeWithType.ql +++ b/python/ql/test/3/library-tests/PointsTo/imports/RuntimeWithType.ql @@ -1,6 +1,7 @@ import python +private import LegacyPointsTo -from int line, ControlFlowNode f, Object o, ClassObject cls, ControlFlowNode orig +from int line, ControlFlowNodeWithPointsTo f, Object o, ClassObject cls, ControlFlowNode orig where not f.getLocation().getFile().inStdlib() and f.refersTo(o, cls, orig) and diff --git a/python/ql/test/3/library-tests/PointsTo/typehints/Values.ql b/python/ql/test/3/library-tests/PointsTo/typehints/Values.ql index 192468a2248c..be451d6f5960 100644 --- a/python/ql/test/3/library-tests/PointsTo/typehints/Values.ql +++ b/python/ql/test/3/library-tests/PointsTo/typehints/Values.ql @@ -1,6 +1,7 @@ import python +private import LegacyPointsTo -from ControlFlowNode f, Context ctx, Value v, ControlFlowNode origin +from ControlFlowNodeWithPointsTo f, Context ctx, Value v, ControlFlowNode origin where f.pointsTo(ctx, v, origin) and f.getLocation().getFile().getBaseName() = "test.py" diff --git a/python/ql/test/library-tests/PointsTo/absent/Absent.ql b/python/ql/test/library-tests/PointsTo/absent/Absent.ql index 95cdf3a10844..b73eb9b5296c 100644 --- a/python/ql/test/library-tests/PointsTo/absent/Absent.ql +++ b/python/ql/test/library-tests/PointsTo/absent/Absent.ql @@ -1,6 +1,7 @@ import python +private import LegacyPointsTo import semmle.python.objects.Modules -from Value val, ControlFlowNode f +from Value val, ControlFlowNodeWithPointsTo f where f.pointsTo(val) select f, val diff --git a/python/ql/test/library-tests/PointsTo/calls/CallPointsTo.ql b/python/ql/test/library-tests/PointsTo/calls/CallPointsTo.ql index 10247a98f941..70a9bbd914b0 100644 --- a/python/ql/test/library-tests/PointsTo/calls/CallPointsTo.ql +++ b/python/ql/test/library-tests/PointsTo/calls/CallPointsTo.ql @@ -1,5 +1,6 @@ import python +private import LegacyPointsTo from CallNode call, Value func -where call.getFunction().pointsTo(func) +where call.getFunction().(ControlFlowNodeWithPointsTo).pointsTo(func) select call.getLocation().getStartLine(), call.toString(), func.toString() diff --git a/python/ql/test/library-tests/PointsTo/comparisons/PointsTo.ql b/python/ql/test/library-tests/PointsTo/comparisons/PointsTo.ql index 61f802a2ea5a..31d2f1cab36c 100644 --- a/python/ql/test/library-tests/PointsTo/comparisons/PointsTo.ql +++ b/python/ql/test/library-tests/PointsTo/comparisons/PointsTo.ql @@ -1,6 +1,7 @@ import python +private import LegacyPointsTo -from int line, ControlFlowNode f, Value v +from int line, ControlFlowNodeWithPointsTo f, Value v where any(ExprStmt s).getValue() = f.getNode() and line = f.getLocation().getStartLine() and diff --git a/python/ql/test/library-tests/PointsTo/decorators/Test.ql b/python/ql/test/library-tests/PointsTo/decorators/Test.ql index b5175845070d..b237ce513d2b 100644 --- a/python/ql/test/library-tests/PointsTo/decorators/Test.ql +++ b/python/ql/test/library-tests/PointsTo/decorators/Test.ql @@ -1,10 +1,11 @@ import python +private import LegacyPointsTo // We don't care about the internals of functools which vary from // version to version, just the end result. from NameNode f, Object o, ControlFlowNode x, int line where - f.refersTo(o, x) and + f.(ControlFlowNodeWithPointsTo).refersTo(o, x) and f.getLocation().getFile().getBaseName() = "test.py" and line = f.getLocation().getStartLine() select line, f.toString(), o.toString(), x.getLocation().toString() diff --git a/python/ql/test/library-tests/PointsTo/general/GlobalPointsTo.ql b/python/ql/test/library-tests/PointsTo/general/GlobalPointsTo.ql index 8caa54ccc237..e90674bab2e3 100644 --- a/python/ql/test/library-tests/PointsTo/general/GlobalPointsTo.ql +++ b/python/ql/test/library-tests/PointsTo/general/GlobalPointsTo.ql @@ -1,7 +1,8 @@ import python +private import LegacyPointsTo import interesting -from int line, ControlFlowNode f, Object o, ImportTimeScope n +from int line, ControlFlowNodeWithPointsTo f, Object o, ImportTimeScope n where of_interest(f, line) and f.refersTo(o) and diff --git a/python/ql/test/library-tests/PointsTo/general/LocalPointsTo.ql b/python/ql/test/library-tests/PointsTo/general/LocalPointsTo.ql index aee2cb11bf4c..76d711c00e08 100644 --- a/python/ql/test/library-tests/PointsTo/general/LocalPointsTo.ql +++ b/python/ql/test/library-tests/PointsTo/general/LocalPointsTo.ql @@ -6,10 +6,11 @@ */ import python +private import LegacyPointsTo import interesting import Util -from int line, ControlFlowNode f, Object o +from int line, ControlFlowNodeWithPointsTo f, Object o where of_interest(f, line) and f.refersTo(o) diff --git a/python/ql/test/library-tests/PointsTo/general/LocalPointsToType.ql b/python/ql/test/library-tests/PointsTo/general/LocalPointsToType.ql index fe14e61e01b4..8b5e008d60a0 100644 --- a/python/ql/test/library-tests/PointsTo/general/LocalPointsToType.ql +++ b/python/ql/test/library-tests/PointsTo/general/LocalPointsToType.ql @@ -1,8 +1,9 @@ import python +private import LegacyPointsTo import interesting import Util -from int line, ControlFlowNode f, Object o, ClassObject cls +from int line, ControlFlowNodeWithPointsTo f, Object o, ClassObject cls where of_interest(f, line) and f.refersTo(o, cls, _) diff --git a/python/ql/test/library-tests/PointsTo/guarded/PointsTo.ql b/python/ql/test/library-tests/PointsTo/guarded/PointsTo.ql index db4710786ac1..c264bf040136 100644 --- a/python/ql/test/library-tests/PointsTo/guarded/PointsTo.ql +++ b/python/ql/test/library-tests/PointsTo/guarded/PointsTo.ql @@ -1,6 +1,7 @@ import python +private import LegacyPointsTo -from ControlFlowNode f, Object o, ControlFlowNode x +from ControlFlowNodeWithPointsTo f, Object o, ControlFlowNode x where f.refersTo(o, x) and exists(CallNode call | call.getFunction().getNode().(Name).getId() = "use" and call.getArg(0) = f) diff --git a/python/ql/test/library-tests/PointsTo/guarded/PointsToWithType.ql b/python/ql/test/library-tests/PointsTo/guarded/PointsToWithType.ql index 1c294e642820..f7c3d5a5c717 100644 --- a/python/ql/test/library-tests/PointsTo/guarded/PointsToWithType.ql +++ b/python/ql/test/library-tests/PointsTo/guarded/PointsToWithType.ql @@ -1,6 +1,7 @@ import python +private import LegacyPointsTo -from ControlFlowNode f, Object o, ClassObject c, ControlFlowNode x +from ControlFlowNodeWithPointsTo f, Object o, ClassObject c, ControlFlowNode x where f.refersTo(o, c, x) and exists(CallNode call | call.getFunction().getNode().(Name).getId() = "use" and call.getArg(0) = f) diff --git a/python/ql/test/library-tests/PointsTo/import_star/Values.ql b/python/ql/test/library-tests/PointsTo/import_star/Values.ql index b54b8c6c78dc..f8c620662d63 100644 --- a/python/ql/test/library-tests/PointsTo/import_star/Values.ql +++ b/python/ql/test/library-tests/PointsTo/import_star/Values.ql @@ -1,5 +1,6 @@ import python +private import LegacyPointsTo -from ControlFlowNode f, Context ctx, Value v, ControlFlowNode origin +from ControlFlowNodeWithPointsTo 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/indexing/Test.ql b/python/ql/test/library-tests/PointsTo/indexing/Test.ql index 694e4d8e98e0..d9a9d7156dea 100644 --- a/python/ql/test/library-tests/PointsTo/indexing/Test.ql +++ b/python/ql/test/library-tests/PointsTo/indexing/Test.ql @@ -1,6 +1,7 @@ import python +private import LegacyPointsTo -from ControlFlowNode f, Object o, ControlFlowNode x +from ControlFlowNodeWithPointsTo f, Object o, ControlFlowNode x where f.refersTo(o, x) and f.getLocation().getFile().getBaseName() = "test.py" diff --git a/python/ql/test/library-tests/PointsTo/indexing/TestWithType.ql b/python/ql/test/library-tests/PointsTo/indexing/TestWithType.ql index 9f16abc2de07..b3888d5bf109 100644 --- a/python/ql/test/library-tests/PointsTo/indexing/TestWithType.ql +++ b/python/ql/test/library-tests/PointsTo/indexing/TestWithType.ql @@ -1,6 +1,7 @@ import python +private import LegacyPointsTo -from ControlFlowNode f, Object o, ClassObject c, ControlFlowNode x +from ControlFlowNodeWithPointsTo f, Object o, ClassObject c, ControlFlowNode x where f.refersTo(o, c, x) and f.getLocation().getFile().getBaseName() = "test.py" diff --git a/python/ql/test/library-tests/PointsTo/inheritance/Self.ql b/python/ql/test/library-tests/PointsTo/inheritance/Self.ql index 050690fd1cb5..571f39d34ab5 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/Self.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/Self.ql @@ -1,5 +1,6 @@ import python +private import LegacyPointsTo from NameNode n, Object value, ClassObject cls -where n.getId() = "self" and n.refersTo(value, cls, _) +where n.getId() = "self" and n.(ControlFlowNodeWithPointsTo).refersTo(value, cls, _) select n.getNode().getLocation().getStartLine(), value.toString(), cls.toString() diff --git a/python/ql/test/library-tests/PointsTo/new/ImpliesDataflow.ql b/python/ql/test/library-tests/PointsTo/new/ImpliesDataflow.ql index 620cac343329..da4b46595e67 100644 --- a/python/ql/test/library-tests/PointsTo/new/ImpliesDataflow.ql +++ b/python/ql/test/library-tests/PointsTo/new/ImpliesDataflow.ql @@ -4,10 +4,11 @@ */ private import python +private import LegacyPointsTo import semmle.python.dataflow.new.DataFlow predicate pointsToOrigin(DataFlow::CfgNode pointer, DataFlow::CfgNode origin) { - origin.getNode() = pointer.getNode().pointsTo().getOrigin() + origin.getNode() = pointer.getNode().(ControlFlowNodeWithPointsTo).pointsTo().getOrigin() } module PointsToConfig implements DataFlow::ConfigSig { diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToNone.ql b/python/ql/test/library-tests/PointsTo/new/PointsToNone.ql index c5009ad4cb67..8dca05a8a273 100644 --- a/python/ql/test/library-tests/PointsTo/new/PointsToNone.ql +++ b/python/ql/test/library-tests/PointsTo/new/PointsToNone.ql @@ -1,6 +1,7 @@ import python +private import LegacyPointsTo import Util -from ControlFlowNode f, ControlFlowNode x +from ControlFlowNodeWithPointsTo f, ControlFlowNode x where f.refersTo(theNoneObject(), _, x) select locate(f.getLocation(), "abcdghijklmopqr"), f.toString(), x.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/new/Values.ql b/python/ql/test/library-tests/PointsTo/new/Values.ql index 668e7a6b2655..9e49b44d37ea 100644 --- a/python/ql/test/library-tests/PointsTo/new/Values.ql +++ b/python/ql/test/library-tests/PointsTo/new/Values.ql @@ -1,7 +1,8 @@ import python +private import LegacyPointsTo import Util -from ControlFlowNode f, Context ctx, Value v, ControlFlowNode origin +from ControlFlowNodeWithPointsTo f, Context ctx, Value v, ControlFlowNode origin where f.pointsTo(ctx, v, origin) select locate(f.getLocation(), "abeghijklmnpqrstu"), f.toString(), ctx, vrepr(v), vrepr(v.getClass()) diff --git a/python/ql/test/library-tests/PointsTo/properties/Values.ql b/python/ql/test/library-tests/PointsTo/properties/Values.ql index 23416efc0ebd..6ab52924bb9e 100644 --- a/python/ql/test/library-tests/PointsTo/properties/Values.ql +++ b/python/ql/test/library-tests/PointsTo/properties/Values.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo import semmle.python.objects.ObjectInternal string vrepr(Value v) { @@ -8,6 +9,6 @@ string vrepr(Value v) { v = ObjectInternal::boundMethod() and result = "builtin-class method" } -from ControlFlowNode f, Context ctx, Value v, ControlFlowNode origin +from ControlFlowNodeWithPointsTo f, Context ctx, Value v, ControlFlowNode origin where f.pointsTo(ctx, v, origin) select f.getLocation(), f.toString(), ctx, vrepr(v), vrepr(v.getClass()) diff --git a/python/ql/test/library-tests/PointsTo/regressions/missing/if-urlsplit-access/Test.ql b/python/ql/test/library-tests/PointsTo/regressions/missing/if-urlsplit-access/Test.ql index db02e9c4f085..87b4bb605d74 100644 --- a/python/ql/test/library-tests/PointsTo/regressions/missing/if-urlsplit-access/Test.ql +++ b/python/ql/test/library-tests/PointsTo/regressions/missing/if-urlsplit-access/Test.ql @@ -1,6 +1,7 @@ import python +private import LegacyPointsTo -from ControlFlowNode arg, CallNode call, string debug +from ControlFlowNodeWithPointsTo arg, CallNode call, string debug where call.getAnArg() = arg and call.getFunction().(NameNode).getId() = "check" and diff --git a/python/ql/test/library-tests/PointsTo/regressions/missing/re-compile/Test.ql b/python/ql/test/library-tests/PointsTo/regressions/missing/re-compile/Test.ql index db02e9c4f085..87b4bb605d74 100644 --- a/python/ql/test/library-tests/PointsTo/regressions/missing/re-compile/Test.ql +++ b/python/ql/test/library-tests/PointsTo/regressions/missing/re-compile/Test.ql @@ -1,6 +1,7 @@ import python +private import LegacyPointsTo -from ControlFlowNode arg, CallNode call, string debug +from ControlFlowNodeWithPointsTo arg, CallNode call, string debug where call.getAnArg() = arg and call.getFunction().(NameNode).getId() = "check" and diff --git a/python/ql/test/library-tests/PointsTo/regressions/missing/uncalled-function/Test.ql b/python/ql/test/library-tests/PointsTo/regressions/missing/uncalled-function/Test.ql index db02e9c4f085..87b4bb605d74 100644 --- a/python/ql/test/library-tests/PointsTo/regressions/missing/uncalled-function/Test.ql +++ b/python/ql/test/library-tests/PointsTo/regressions/missing/uncalled-function/Test.ql @@ -1,6 +1,7 @@ import python +private import LegacyPointsTo -from ControlFlowNode arg, CallNode call, string debug +from ControlFlowNodeWithPointsTo arg, CallNode call, string debug where call.getAnArg() = arg and call.getFunction().(NameNode).getId() = "check" and diff --git a/python/ql/test/library-tests/PointsTo/regressions/wrong/classmethod/Test.ql b/python/ql/test/library-tests/PointsTo/regressions/wrong/classmethod/Test.ql index 700e0dd72a59..a7be670276fd 100644 --- a/python/ql/test/library-tests/PointsTo/regressions/wrong/classmethod/Test.ql +++ b/python/ql/test/library-tests/PointsTo/regressions/wrong/classmethod/Test.ql @@ -1,10 +1,11 @@ import python +private import LegacyPointsTo from NameNode name, CallNode call, string debug where call.getAnArg() = name and call.getFunction().(NameNode).getId() = "check" and - if exists(name.pointsTo()) - then debug = name.pointsTo().toString() + if exists(name.(ControlFlowNodeWithPointsTo).pointsTo()) + then debug = name.(ControlFlowNodeWithPointsTo).pointsTo().toString() else debug = "" select name, debug diff --git a/python/ql/test/library-tests/PointsTo/super/SuperMethodCall.ql b/python/ql/test/library-tests/PointsTo/super/SuperMethodCall.ql index 86ad5bee155f..43149df47b81 100644 --- a/python/ql/test/library-tests/PointsTo/super/SuperMethodCall.ql +++ b/python/ql/test/library-tests/PointsTo/super/SuperMethodCall.ql @@ -1,11 +1,12 @@ import python +private import LegacyPointsTo import semmle.python.pointsto.PointsTo import semmle.python.pointsto.PointsToContext import semmle.python.objects.ObjectInternal from CallNode call, SuperInstance sup, BoundMethodObjectInternal bm where - call.getFunction().inferredValue() = bm and - call.getFunction().(AttrNode).getObject().inferredValue() = sup + call.getFunction().(ControlFlowNodeWithPointsTo).inferredValue() = bm and + call.getFunction().(AttrNode).getObject().(ControlFlowNodeWithPointsTo).inferredValue() = sup select call.getLocation().getStartLine(), call.toString(), bm.getFunction().getSource().(FunctionObject).getQualifiedName() diff --git a/python/ql/test/library-tests/objects/Strings.ql b/python/ql/test/library-tests/objects/Strings.ql index eca8dec51fd3..4c79df89dafd 100644 --- a/python/ql/test/library-tests/objects/Strings.ql +++ b/python/ql/test/library-tests/objects/Strings.ql @@ -1,5 +1,6 @@ import python +private import LegacyPointsTo -from StringObject s, ControlFlowNode f +from StringObject s, ControlFlowNodeWithPointsTo f where f.refersTo(s) select f.getLocation().toString(), s.getText() diff --git a/python/ql/test/library-tests/taint/extensions/ExtensionsLib.qll b/python/ql/test/library-tests/taint/extensions/ExtensionsLib.qll index 4ae53e94a381..e6874512f5cd 100644 --- a/python/ql/test/library-tests/taint/extensions/ExtensionsLib.qll +++ b/python/ql/test/library-tests/taint/extensions/ExtensionsLib.qll @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo import semmle.python.dataflow.TaintTracking class SimpleTest extends TaintKind { @@ -30,7 +31,7 @@ predicate visit_call(CallNode call, FunctionObject func) { exists(AttrNode attr, ClassObject cls, string name | name.matches("visit\\_%") and func = cls.lookupAttribute(name) and - attr.getObject("visit").refersTo(_, cls, _) and + attr.getObject("visit").(ControlFlowNodeWithPointsTo).refersTo(_, cls, _) and attr = call.getFunction() ) } From b434ce460ee45da3e63f8c2a267cc7650ad3dcc1 Mon Sep 17 00:00:00 2001 From: Taus Date: Thu, 30 Oct 2025 11:50:07 +0000 Subject: [PATCH 02/19] Python: Get rid of `getLiteralValue` This had only two uses in our libraries, so I simply inlined the predicate body in both places. --- python/ql/lib/semmle/python/Exprs.qll | 2 -- python/ql/src/Expressions/IsComparisons.qll | 3 ++- python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql | 3 ++- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/python/ql/lib/semmle/python/Exprs.qll b/python/ql/lib/semmle/python/Exprs.qll index e288078247a9..88562cb76986 100644 --- a/python/ql/lib/semmle/python/Exprs.qll +++ b/python/ql/lib/semmle/python/Exprs.qll @@ -337,8 +337,6 @@ abstract class ImmutableLiteral extends Expr { abstract Object getLiteralObject(); abstract boolean booleanValue(); - - final Value getLiteralValue() { result.(ConstantObjectInternal).getLiteral() = this } } /** A numerical constant expression, such as `7` or `4.2` */ diff --git a/python/ql/src/Expressions/IsComparisons.qll b/python/ql/src/Expressions/IsComparisons.qll index 25058206c862..575c53a03e12 100644 --- a/python/ql/src/Expressions/IsComparisons.qll +++ b/python/ql/src/Expressions/IsComparisons.qll @@ -2,6 +2,7 @@ import python private import LegacyPointsTo +private import semmle.python.objects.ObjectInternal /** Holds if the comparison `comp` uses `is` or `is not` (represented as `op`) to compare its `left` and `right` arguments. */ predicate comparison_using_is(Compare comp, ControlFlowNode left, Cmpop op, ControlFlowNode right) { @@ -121,7 +122,7 @@ predicate invalid_portable_is_comparison(Compare comp, Cmpop op, ClassValue cls) // OK to use 'is' when comparing items from a known set of objects not exists(Expr left, Expr right, Value val | comp.compares(left, op, right) and - exists(ImmutableLiteral il | il.getLiteralValue() = val) + exists(ImmutableLiteral il | il = val.(ConstantObjectInternal).getLiteral()) | left.pointsTo(val) and right.pointsTo(val) or diff --git a/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql b/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql index e47d4a55bf5d..3c4b66f6982d 100644 --- a/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql +++ b/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql @@ -14,6 +14,7 @@ */ import python +import semmle.python.objects.ObjectInternal import semmle.python.strings predicate string_format(BinaryExpr operation, StringLiteral str, Value args, AstNode origin) { @@ -31,7 +32,7 @@ int sequence_length(Value args) { not seq.getAnElt() instanceof Starred ) or - exists(ImmutableLiteral i | i.getLiteralValue() = args | result = 1) + exists(ImmutableLiteral i | i = args.(ConstantObjectInternal).getLiteral() | result = 1) } from From b93ce986128f86ddb227149f8717f00f67c0f54b Mon Sep 17 00:00:00 2001 From: Taus Date: Thu, 30 Oct 2025 11:52:39 +0000 Subject: [PATCH 03/19] Python: Remove points-to from `Expr` --- python/ql/examples/snippets/builtin_object.ql | 3 +- .../ql/examples/snippets/catch_exception.ql | 3 +- .../snippets/conditional_expression.ql | 5 +- python/ql/examples/snippets/new_instance.ql | 3 +- python/ql/examples/snippets/print.ql | 3 +- .../ql/examples/snippets/raise_exception.ql | 3 +- python/ql/lib/LegacyPointsTo.qll | 72 +++++++++++++++++++ python/ql/lib/semmle/python/Exprs.qll | 70 +----------------- python/ql/lib/semmle/python/Metrics.qll | 4 +- .../lib/semmle/python/objects/ObjectAPI.qll | 4 +- python/ql/src/Exceptions/NotImplemented.qll | 3 +- python/ql/src/Exceptions/Raising.qll | 3 +- python/ql/src/Expressions/CallArgs.qll | 5 +- .../ExpectedMappingForFormatString.ql | 3 +- python/ql/src/Expressions/HashedButNoHash.ql | 2 +- python/ql/src/Expressions/IsComparisons.qll | 8 +-- .../ql/src/Expressions/NonCallableCalled.ql | 3 +- .../ql/src/Expressions/UnnecessaryLambda.ql | 3 +- .../WrongNumberArgumentsForFormat.ql | 7 +- .../ql/src/Functions/ExplicitReturnInInit.ql | 3 +- .../Functions/UseImplicitNoneReturnValue.ql | 7 +- python/ql/src/Imports/Cyclic.qll | 8 ++- python/ql/src/Imports/DeprecatedModule.ql | 3 +- python/ql/src/Imports/UnusedImport.ql | 5 +- .../MismatchInMultipleAssignment.ql | 3 +- .../ql/src/Statements/RedundantAssignment.ql | 7 +- python/ql/src/Statements/StatementNoEffect.ql | 11 +-- python/ql/src/Statements/UnreachableCode.ql | 7 +- .../src/Statements/UnusedExceptionObject.ql | 3 +- python/ql/src/Variables/UndefinedGlobal.ql | 3 +- python/ql/src/Variables/UninitializedLocal.ql | 3 +- python/ql/src/analysis/ImportFailure.ql | 4 +- python/ql/src/analysis/RatioOfDefinitions.ql | 3 +- .../ql/test/2/library-tests/six/pointsto.ql | 3 +- .../ql/test/3/library-tests/six/pointsto.ql | 3 +- 35 files changed, 164 insertions(+), 119 deletions(-) diff --git a/python/ql/examples/snippets/builtin_object.ql b/python/ql/examples/snippets/builtin_object.ql index 7f552a5aa796..36b2d92e0b97 100644 --- a/python/ql/examples/snippets/builtin_object.ql +++ b/python/ql/examples/snippets/builtin_object.ql @@ -8,7 +8,8 @@ */ import python +private import LegacyPointsTo -from Expr e, string name +from ExprWithPointsTo e, string name where e.pointsTo(Value::named(name)) and not name.charAt(_) = "." select e diff --git a/python/ql/examples/snippets/catch_exception.ql b/python/ql/examples/snippets/catch_exception.ql index 9d67d0056b62..b4a77f267d09 100644 --- a/python/ql/examples/snippets/catch_exception.ql +++ b/python/ql/examples/snippets/catch_exception.ql @@ -8,9 +8,10 @@ */ import python +private import LegacyPointsTo from ExceptStmt ex, ClassValue cls where cls.getName() = "MyExceptionClass" and - ex.getType().pointsTo(cls) + ex.getType().(ExprWithPointsTo).pointsTo(cls) select ex diff --git a/python/ql/examples/snippets/conditional_expression.ql b/python/ql/examples/snippets/conditional_expression.ql index 8af55ca104ff..876c34678692 100644 --- a/python/ql/examples/snippets/conditional_expression.ql +++ b/python/ql/examples/snippets/conditional_expression.ql @@ -9,10 +9,11 @@ */ import python +private import LegacyPointsTo from IfExp e, ClassObject cls1, ClassObject cls2 where - e.getBody().refersTo(_, cls1, _) and - e.getOrelse().refersTo(_, cls2, _) and + e.getBody().(ExprWithPointsTo).refersTo(_, cls1, _) and + e.getOrelse().(ExprWithPointsTo).refersTo(_, cls2, _) and cls1 != cls2 select e diff --git a/python/ql/examples/snippets/new_instance.ql b/python/ql/examples/snippets/new_instance.ql index 75a1ea635d53..b0be6f77197c 100644 --- a/python/ql/examples/snippets/new_instance.ql +++ b/python/ql/examples/snippets/new_instance.ql @@ -8,9 +8,10 @@ */ import python +private import LegacyPointsTo from Call new, ClassValue cls where cls.getName() = "MyClass" and - new.getFunc().pointsTo(cls) + new.getFunc().(ExprWithPointsTo).pointsTo(cls) select new diff --git a/python/ql/examples/snippets/print.ql b/python/ql/examples/snippets/print.ql index f0ba47eafeb3..ba4d730118d6 100644 --- a/python/ql/examples/snippets/print.ql +++ b/python/ql/examples/snippets/print.ql @@ -6,6 +6,7 @@ */ import python +private import LegacyPointsTo from AstNode print where @@ -13,5 +14,5 @@ where print instanceof Print or /* Python 3 or with `from __future__ import print_function` */ - print.(Call).getFunc().pointsTo(Value::named("print")) + print.(Call).getFunc().(ExprWithPointsTo).pointsTo(Value::named("print")) select print diff --git a/python/ql/examples/snippets/raise_exception.ql b/python/ql/examples/snippets/raise_exception.ql index 12e4f93a349c..23cf26a8c60a 100644 --- a/python/ql/examples/snippets/raise_exception.ql +++ b/python/ql/examples/snippets/raise_exception.ql @@ -8,9 +8,10 @@ */ import python +private import LegacyPointsTo from Raise raise, ClassValue ex where ex.getName() = "AnException" and - raise.getException().pointsTo(ex.getASuperType()) + raise.getException().(ExprWithPointsTo).pointsTo(ex.getASuperType()) select raise, "Don't raise instances of 'AnException'" diff --git a/python/ql/lib/LegacyPointsTo.qll b/python/ql/lib/LegacyPointsTo.qll index f195bc20a519..d5961fc02136 100644 --- a/python/ql/lib/LegacyPointsTo.qll +++ b/python/ql/lib/LegacyPointsTo.qll @@ -119,3 +119,75 @@ private predicate varHasCompletePointsToSet(SsaVariable var) { ) ) } + +/** + * An extension of `Expr` that provides points-to predicates. + */ +class ExprWithPointsTo extends Expr { + /** + * NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. + * Gets what this expression might "refer-to". Performs a combination of localized (intra-procedural) points-to + * analysis and global module-level analysis. This points-to analysis favours precision over recall. It is highly + * precise, but may not provide information for a significant number of flow-nodes. + * If the class is unimportant then use `refersTo(value)` or `refersTo(value, origin)` instead. + * NOTE: For complex dataflow, involving multiple stages of points-to analysis, it may be more precise to use + * `ControlFlowNode.refersTo(...)` instead. + */ + predicate refersTo(Object obj, ClassObject cls, AstNode origin) { + this.refersTo(_, obj, cls, origin) + } + + /** + * NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. + * Gets what this expression might "refer-to" in the given `context`. + */ + predicate refersTo(Context context, Object obj, ClassObject cls, AstNode origin) { + this.getAFlowNode() + .(ControlFlowNodeWithPointsTo) + .refersTo(context, obj, cls, origin.getAFlowNode()) + } + + /** + * NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. + * Holds if this expression might "refer-to" to `value` which is from `origin` + * Unlike `this.refersTo(value, _, origin)`, this predicate includes results + * where the class cannot be inferred. + */ + pragma[nomagic] + predicate refersTo(Object obj, AstNode origin) { + this.getAFlowNode().(ControlFlowNodeWithPointsTo).refersTo(obj, origin.getAFlowNode()) + } + + /** + * NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. + * Equivalent to `this.refersTo(value, _)` + */ + predicate refersTo(Object obj) { this.refersTo(obj, _) } + + /** + * Holds if this expression might "point-to" to `value` which is from `origin` + * in the given `context`. + */ + predicate pointsTo(Context context, Value value, AstNode origin) { + this.getAFlowNode() + .(ControlFlowNodeWithPointsTo) + .pointsTo(context, value, origin.getAFlowNode()) + } + + /** + * Holds if this expression might "point-to" to `value` which is from `origin`. + */ + predicate pointsTo(Value value, AstNode origin) { + this.getAFlowNode().(ControlFlowNodeWithPointsTo).pointsTo(value, origin.getAFlowNode()) + } + + /** + * Holds if this expression might "point-to" to `value`. + */ + predicate pointsTo(Value value) { this.pointsTo(value, _) } + + /** Gets a value that this expression might "point-to". */ + Value pointsTo() { this.pointsTo(result) } + + override string getAQlClass() { none() } +} diff --git a/python/ql/lib/semmle/python/Exprs.qll b/python/ql/lib/semmle/python/Exprs.qll index 88562cb76986..e5ee2bdb28c7 100644 --- a/python/ql/lib/semmle/python/Exprs.qll +++ b/python/ql/lib/semmle/python/Exprs.qll @@ -1,7 +1,4 @@ -import python -private import LegacyPointsTo -private import semmle.python.pointsto.PointsTo -private import semmle.python.objects.ObjectInternal +private import python private import semmle.python.internal.CachedStages /** An expression */ @@ -53,71 +50,6 @@ class Expr extends Expr_, AstNode { Expr getASubExpression() { none() } override AstNode getAChildNode() { result = this.getASubExpression() } - - /** - * NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. - * Gets what this expression might "refer-to". Performs a combination of localized (intra-procedural) points-to - * analysis and global module-level analysis. This points-to analysis favours precision over recall. It is highly - * precise, but may not provide information for a significant number of flow-nodes. - * If the class is unimportant then use `refersTo(value)` or `refersTo(value, origin)` instead. - * NOTE: For complex dataflow, involving multiple stages of points-to analysis, it may be more precise to use - * `ControlFlowNode.refersTo(...)` instead. - */ - predicate refersTo(Object obj, ClassObject cls, AstNode origin) { - this.refersTo(_, obj, cls, origin) - } - - /** - * NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. - * Gets what this expression might "refer-to" in the given `context`. - */ - predicate refersTo(Context context, Object obj, ClassObject cls, AstNode origin) { - this.getAFlowNode() - .(ControlFlowNodeWithPointsTo) - .refersTo(context, obj, cls, origin.getAFlowNode()) - } - - /** - * NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. - * Holds if this expression might "refer-to" to `value` which is from `origin` - * Unlike `this.refersTo(value, _, origin)`, this predicate includes results - * where the class cannot be inferred. - */ - pragma[nomagic] - predicate refersTo(Object obj, AstNode origin) { - this.getAFlowNode().(ControlFlowNodeWithPointsTo).refersTo(obj, origin.getAFlowNode()) - } - - /** - * NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. - * Equivalent to `this.refersTo(value, _)` - */ - predicate refersTo(Object obj) { this.refersTo(obj, _) } - - /** - * Holds if this expression might "point-to" to `value` which is from `origin` - * in the given `context`. - */ - predicate pointsTo(Context context, Value value, AstNode origin) { - this.getAFlowNode() - .(ControlFlowNodeWithPointsTo) - .pointsTo(context, value, origin.getAFlowNode()) - } - - /** - * Holds if this expression might "point-to" to `value` which is from `origin`. - */ - predicate pointsTo(Value value, AstNode origin) { - this.getAFlowNode().(ControlFlowNodeWithPointsTo).pointsTo(value, origin.getAFlowNode()) - } - - /** - * Holds if this expression might "point-to" to `value`. - */ - predicate pointsTo(Value value) { this.pointsTo(value, _) } - - /** Gets a value that this expression might "point-to". */ - Value pointsTo() { this.pointsTo(result) } } /** An assignment expression, such as `x := y` */ diff --git a/python/ql/lib/semmle/python/Metrics.qll b/python/ql/lib/semmle/python/Metrics.qll index 16d89711eea3..dcc5cf959d93 100644 --- a/python/ql/lib/semmle/python/Metrics.qll +++ b/python/ql/lib/semmle/python/Metrics.qll @@ -124,7 +124,7 @@ class ClassMetrics extends Class { ) or exists(Function f, Call c, ClassObject cls | c.getScope() = f and f.getScope() = this | - c.getFunc().refersTo(cls) and + c.getFunc().(ExprWithPointsTo).refersTo(cls) and cls.getPyClass() = other ) ) @@ -293,7 +293,7 @@ class ModuleMetrics extends Module { ) or exists(Function f, Call c, ClassObject cls | c.getScope() = f and f.getScope() = this | - c.getFunc().refersTo(cls) and + c.getFunc().(ExprWithPointsTo).refersTo(cls) and cls.getPyClass().getEnclosingModule() = other ) ) diff --git a/python/ql/lib/semmle/python/objects/ObjectAPI.qll b/python/ql/lib/semmle/python/objects/ObjectAPI.qll index 26c57a78c179..45247c5d9d44 100644 --- a/python/ql/lib/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/lib/semmle/python/objects/ObjectAPI.qll @@ -697,7 +697,9 @@ abstract class FunctionValue extends CallableValue { exists(ClassValue cls, string name | cls.declaredAttribute(name) = this and name != "__new__" and - exists(Expr expr, AstNode origin | expr.pointsTo(this, origin) | not origin instanceof Lambda) + exists(ExprWithPointsTo expr, AstNode origin | expr.pointsTo(this, origin) | + not origin instanceof Lambda + ) ) } diff --git a/python/ql/src/Exceptions/NotImplemented.qll b/python/ql/src/Exceptions/NotImplemented.qll index 2186a7b5f30b..498165d29826 100644 --- a/python/ql/src/Exceptions/NotImplemented.qll +++ b/python/ql/src/Exceptions/NotImplemented.qll @@ -1,7 +1,8 @@ import python +private import LegacyPointsTo /** Holds if `notimpl` refers to `NotImplemented` or `NotImplemented()` in the `raise` statement */ -predicate use_of_not_implemented_in_raise(Raise raise, Expr notimpl) { +predicate use_of_not_implemented_in_raise(Raise raise, ExprWithPointsTo notimpl) { notimpl.pointsTo(Value::named("NotImplemented")) and ( notimpl = raise.getException() or diff --git a/python/ql/src/Exceptions/Raising.qll b/python/ql/src/Exceptions/Raising.qll index c81494811875..c509c41819d6 100644 --- a/python/ql/src/Exceptions/Raising.qll +++ b/python/ql/src/Exceptions/Raising.qll @@ -1,8 +1,9 @@ import python +private import LegacyPointsTo /** Whether the raise statement 'r' raises 'type' from origin 'orig' */ predicate type_or_typeof(Raise r, ClassValue type, AstNode orig) { - exists(Expr exception | exception = r.getRaised() | + exists(ExprWithPointsTo exception | exception = r.getRaised() | exception.pointsTo(type, orig) or not exists(ClassValue exc_type | exception.pointsTo(exc_type)) and diff --git a/python/ql/src/Expressions/CallArgs.qll b/python/ql/src/Expressions/CallArgs.qll index d2f94ca7cf08..709915afbc61 100644 --- a/python/ql/src/Expressions/CallArgs.qll +++ b/python/ql/src/Expressions/CallArgs.qll @@ -1,12 +1,13 @@ /** INTERNAL - Methods used by queries that test whether functions are invoked correctly. */ import python +private import LegacyPointsTo import Testing.Mox private int varargs_length_objectapi(Call call) { not exists(call.getStarargs()) and result = 0 or - exists(TupleObject t | call.getStarargs().refersTo(t) | result = t.getLength()) + exists(TupleObject t | call.getStarargs().(ExprWithPointsTo).refersTo(t) | result = t.getLength()) or result = count(call.getStarargs().(List).getAnElt()) } @@ -14,7 +15,7 @@ private int varargs_length_objectapi(Call call) { private int varargs_length(Call call) { not exists(call.getStarargs()) and result = 0 or - exists(TupleValue t | call.getStarargs().pointsTo(t) | result = t.length()) + exists(TupleValue t | call.getStarargs().(ExprWithPointsTo).pointsTo(t) | result = t.length()) or result = count(call.getStarargs().(List).getAnElt()) } diff --git a/python/ql/src/Expressions/ExpectedMappingForFormatString.ql b/python/ql/src/Expressions/ExpectedMappingForFormatString.ql index 4342062270b7..c11ab58688ea 100644 --- a/python/ql/src/Expressions/ExpectedMappingForFormatString.ql +++ b/python/ql/src/Expressions/ExpectedMappingForFormatString.ql @@ -12,9 +12,10 @@ */ import python +private import LegacyPointsTo import semmle.python.strings -from Expr e, ClassValue t +from ExprWithPointsTo e, ClassValue t where exists(BinaryExpr b | b.getOp() instanceof Mod and diff --git a/python/ql/src/Expressions/HashedButNoHash.ql b/python/ql/src/Expressions/HashedButNoHash.ql index 795865987603..705806bf3605 100644 --- a/python/ql/src/Expressions/HashedButNoHash.ql +++ b/python/ql/src/Expressions/HashedButNoHash.ql @@ -72,7 +72,7 @@ predicate is_unhashable(ControlFlowNodeWithPointsTo f, ClassValue cls, ControlFl predicate typeerror_is_caught(ControlFlowNode f) { exists(Try try | try.getBody().contains(f.getNode()) and - try.getAHandler().getType().pointsTo(ClassValue::typeError()) + try.getAHandler().getType().(ExprWithPointsTo).pointsTo(ClassValue::typeError()) ) } diff --git a/python/ql/src/Expressions/IsComparisons.qll b/python/ql/src/Expressions/IsComparisons.qll index 575c53a03e12..1ed4534bd234 100644 --- a/python/ql/src/Expressions/IsComparisons.qll +++ b/python/ql/src/Expressions/IsComparisons.qll @@ -76,12 +76,12 @@ private predicate universally_interned_value(Expr e) { } /** Holds if the expression `e` points to an interned constant in CPython. */ -predicate cpython_interned_constant(Expr e) { +predicate cpython_interned_constant(ExprWithPointsTo e) { exists(Expr const | e.pointsTo(_, const) | cpython_interned_value(const)) } /** Holds if the expression `e` points to a value that can be reasonably expected to be interned across all implementations of Python. */ -predicate universally_interned_constant(Expr e) { +predicate universally_interned_constant(ExprWithPointsTo e) { exists(Expr const | e.pointsTo(_, const) | universally_interned_value(const)) } @@ -120,7 +120,7 @@ predicate invalid_portable_is_comparison(Compare comp, Cmpop op, ClassValue cls) ) ) and // OK to use 'is' when comparing items from a known set of objects - not exists(Expr left, Expr right, Value val | + not exists(ExprWithPointsTo left, ExprWithPointsTo right, Value val | comp.compares(left, op, right) and exists(ImmutableLiteral il | il = val.(ConstantObjectInternal).getLiteral()) | @@ -134,7 +134,7 @@ predicate invalid_portable_is_comparison(Compare comp, Cmpop op, ClassValue cls) ) ) and // OK to use 'is' when comparing with a member of an enum - not exists(Expr left, Expr right, AstNode origin | + not exists(ExprWithPointsTo left, ExprWithPointsTo right, AstNode origin | comp.compares(left, op, right) and enum_member(origin) | diff --git a/python/ql/src/Expressions/NonCallableCalled.ql b/python/ql/src/Expressions/NonCallableCalled.ql index 2740dbe5fb26..2e593f88ca50 100644 --- a/python/ql/src/Expressions/NonCallableCalled.ql +++ b/python/ql/src/Expressions/NonCallableCalled.ql @@ -12,9 +12,10 @@ */ import python +private import LegacyPointsTo import Exceptions.NotImplemented -from Call c, Value v, ClassValue t, Expr f, AstNode origin +from Call c, Value v, ClassValue t, ExprWithPointsTo f, AstNode origin where f = c.getFunc() and f.pointsTo(v, origin) and diff --git a/python/ql/src/Expressions/UnnecessaryLambda.ql b/python/ql/src/Expressions/UnnecessaryLambda.ql index 5ba2dd171240..770dde6fece4 100644 --- a/python/ql/src/Expressions/UnnecessaryLambda.ql +++ b/python/ql/src/Expressions/UnnecessaryLambda.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo /* f consists of a single return statement, whose value is a call. The arguments of the call are exactly the parameters of f */ predicate simple_wrapper(Lambda l, Expr wrapped) { @@ -39,7 +40,7 @@ predicate simple_wrapper(Lambda l, Expr wrapped) { } /* The expression called will refer to the same object if evaluated when the lambda is created or when the lambda is executed. */ -predicate unnecessary_lambda(Lambda l, Expr e) { +predicate unnecessary_lambda(Lambda l, ExprWithPointsTo e) { simple_wrapper(l, e) and ( /* plain class */ diff --git a/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql b/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql index 3c4b66f6982d..d7b27e5c3d75 100644 --- a/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql +++ b/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql @@ -14,20 +14,21 @@ */ import python +import LegacyPointsTo import semmle.python.objects.ObjectInternal import semmle.python.strings predicate string_format(BinaryExpr operation, StringLiteral str, Value args, AstNode origin) { operation.getOp() instanceof Mod and exists(Context ctx | - operation.getLeft().pointsTo(ctx, _, str) and - operation.getRight().pointsTo(ctx, args, origin) + operation.getLeft().(ExprWithPointsTo).pointsTo(ctx, _, str) and + operation.getRight().(ExprWithPointsTo).pointsTo(ctx, args, origin) ) } int sequence_length(Value args) { /* Guess length of sequence */ - exists(Tuple seq | seq.pointsTo(args, _) | + exists(Tuple seq | seq.(ExprWithPointsTo).pointsTo(args, _) | result = strictcount(seq.getAnElt()) and not seq.getAnElt() instanceof Starred ) diff --git a/python/ql/src/Functions/ExplicitReturnInInit.ql b/python/ql/src/Functions/ExplicitReturnInInit.ql index c4deea6111c6..f1300afbfd0a 100644 --- a/python/ql/src/Functions/ExplicitReturnInInit.ql +++ b/python/ql/src/Functions/ExplicitReturnInInit.ql @@ -12,8 +12,9 @@ */ import python +private import LegacyPointsTo -from Return r, Expr rv +from Return r, ExprWithPointsTo rv where exists(Function init | init.isInitMethod() and r.getScope() = init) and r.getValue() = rv and diff --git a/python/ql/src/Functions/UseImplicitNoneReturnValue.ql b/python/ql/src/Functions/UseImplicitNoneReturnValue.ql index aeac382f6380..4a8b8edd6235 100644 --- a/python/ql/src/Functions/UseImplicitNoneReturnValue.ql +++ b/python/ql/src/Functions/UseImplicitNoneReturnValue.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo import Testing.Mox predicate is_used(Call c) { @@ -31,10 +32,12 @@ from Call c, FunctionValue func where /* Call result is used, but callee is a procedure */ is_used(c) and - c.getFunc().pointsTo(func) and + c.getFunc().(ExprWithPointsTo).pointsTo(func) and func.getScope().isProcedure() and /* All callees are procedures */ - forall(FunctionValue callee | c.getFunc().pointsTo(callee) | callee.getScope().isProcedure()) and + forall(FunctionValue callee | c.getFunc().(ExprWithPointsTo).pointsTo(callee) | + callee.getScope().isProcedure() + ) and /* Mox return objects have an `AndReturn` method */ not useOfMoxInModule(c.getEnclosingModule()) select c, "The result of $@ is used even though it is always None.", func, func.getQualifiedName() diff --git a/python/ql/src/Imports/Cyclic.qll b/python/ql/src/Imports/Cyclic.qll index dd25f06d0e5d..720ea8f00481 100644 --- a/python/ql/src/Imports/Cyclic.qll +++ b/python/ql/src/Imports/Cyclic.qll @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo predicate is_import_time(Stmt s) { not s.getScope+() instanceof Function } @@ -21,7 +22,7 @@ predicate circular_import(ModuleValue m1, ModuleValue m2) { ModuleValue stmt_imports(ImportingStmt s) { exists(string name | result.importedAs(name) and not name = "__main__" | name = s.getAnImportedModuleName() and - s.getASubExpression().pointsTo(result) and + s.getASubExpression().(ExprWithPointsTo).pointsTo(result) and not result.isPackage() ) } @@ -57,7 +58,7 @@ predicate import_time_transitive_import(ModuleValue base, Stmt imp, ModuleValue * Returns import-time usages of module 'm' in module 'enclosing' */ predicate import_time_module_use(ModuleValue m, ModuleValue enclosing, Expr use, string attr) { - exists(Expr mod | + exists(ExprWithPointsTo mod | use.getEnclosingModule() = enclosing.getScope() and not use.getScope+() instanceof Function and mod.pointsTo(m) and @@ -90,7 +91,8 @@ predicate is_used_in_annotation(Expr use) { */ predicate is_annotation_with_from_future_import_annotations(Expr use) { exists(ImportMember i | i.getScope() = use.getEnclosingModule() | - i.getModule().pointsTo().getName() = "__future__" and i.getName() = "annotations" + i.getModule().(ExprWithPointsTo).pointsTo().getName() = "__future__" and + i.getName() = "annotations" ) and is_used_in_annotation(use) } diff --git a/python/ql/src/Imports/DeprecatedModule.ql b/python/ql/src/Imports/DeprecatedModule.ql index 5f5a8af3ae9a..3d529943fb8f 100644 --- a/python/ql/src/Imports/DeprecatedModule.ql +++ b/python/ql/src/Imports/DeprecatedModule.ql @@ -11,6 +11,7 @@ */ import python +private import LegacyPointsTo /** * Holds if the module `name` was deprecated in Python version `major`.`minor`, @@ -79,7 +80,7 @@ where name = imp.getName() and deprecated_module(name, instead, _, _) and not exists(Try try, ExceptStmt except | except = try.getAHandler() | - except.getType().pointsTo(ClassValue::importError()) and + except.getType().(ExprWithPointsTo).pointsTo(ClassValue::importError()) and except.containsInScope(imp) ) select imp, deprecation_message(name) + replacement_message(name) diff --git a/python/ql/src/Imports/UnusedImport.ql b/python/ql/src/Imports/UnusedImport.ql index 020356901652..370daf405fe7 100644 --- a/python/ql/src/Imports/UnusedImport.ql +++ b/python/ql/src/Imports/UnusedImport.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo import Variables.Definition import semmle.python.ApiGraphs @@ -94,7 +95,7 @@ private string typehint_annotation_in_module(Module module_scope) { or annotation = any(FunctionExpr f).getReturns().getASubExpression*() | - annotation.pointsTo(Value::forString(result)) and + annotation.(ExprWithPointsTo).pointsTo(Value::forString(result)) and annotation.getEnclosingModule() = module_scope ) } @@ -144,7 +145,7 @@ predicate unused_import(Import imp, Variable name) { not is_pytest_fixture(imp, name) and // Only consider import statements that actually point-to something (possibly an unknown module). // If this is not the case, it's likely that the import statement never gets executed. - imp.getAName().getValue().pointsTo(_) + imp.getAName().getValue().(ExprWithPointsTo).pointsTo(_) } from Stmt s, Variable name diff --git a/python/ql/src/Statements/MismatchInMultipleAssignment.ql b/python/ql/src/Statements/MismatchInMultipleAssignment.ql index 188bdd7b9156..c44d8e348c66 100644 --- a/python/ql/src/Statements/MismatchInMultipleAssignment.ql +++ b/python/ql/src/Statements/MismatchInMultipleAssignment.ql @@ -13,6 +13,7 @@ */ import python +private import LegacyPointsTo private int len(ExprList el) { result = count(el.getAnItem()) } @@ -41,7 +42,7 @@ predicate mismatched_tuple_rhs(Assign a, int lcount, int rcount, Location loc) { a.getATarget().(Tuple).getElts() = l or a.getATarget().(List).getElts() = l ) and - a.getValue().pointsTo(r, origin) and + a.getValue().(ExprWithPointsTo).pointsTo(r, origin) and loc = origin.getLocation() and lcount = len(l) and rcount = r.length() and diff --git a/python/ql/src/Statements/RedundantAssignment.ql b/python/ql/src/Statements/RedundantAssignment.ql index 42561905bacd..357364c41b2f 100644 --- a/python/ql/src/Statements/RedundantAssignment.ql +++ b/python/ql/src/Statements/RedundantAssignment.ql @@ -13,6 +13,7 @@ */ import python +private import LegacyPointsTo predicate assignment(AssignStmt a, Expr left, Expr right) { a.getATarget() = left and a.getValue() = right @@ -57,7 +58,9 @@ predicate same_name(Name n1, Name n2) { not maybe_defined_in_outer_scope(n2) } -ClassValue value_type(Attribute a) { a.getObject().pointsTo().getClass() = result } +ClassValue value_type(Attribute a) { + a.getObject().(ExprWithPointsTo).pointsTo().getClass() = result +} predicate is_property_access(Attribute a) { value_type(a).lookup(a.getName()) instanceof PropertyValue @@ -87,7 +90,7 @@ predicate pyflakes_commented(AssignStmt assignment) { predicate side_effecting_lhs(Attribute lhs) { exists(ClassValue cls, ClassValue decl | - lhs.getObject().pointsTo().getClass() = cls and + lhs.getObject().(ExprWithPointsTo).pointsTo().getClass() = cls and decl = cls.getASuperType() and not decl.isBuiltin() | diff --git a/python/ql/src/Statements/StatementNoEffect.ql b/python/ql/src/Statements/StatementNoEffect.ql index a5806e7082dd..222907f24e33 100644 --- a/python/ql/src/Statements/StatementNoEffect.ql +++ b/python/ql/src/Statements/StatementNoEffect.ql @@ -13,10 +13,11 @@ */ import python +private import LegacyPointsTo predicate understood_attribute(Attribute attr, ClassValue cls, ClassValue attr_cls) { exists(string name | attr.getName() = name | - attr.getObject().pointsTo().getClass() = cls and + attr.getObject().(ExprWithPointsTo).pointsTo().getClass() = cls and cls.attr(name).getClass() = attr_cls ) } @@ -30,7 +31,7 @@ predicate side_effecting_attribute(Attribute attr) { } predicate maybe_side_effecting_attribute(Attribute attr) { - not understood_attribute(attr, _, _) and not attr.pointsTo(_) + not understood_attribute(attr, _, _) and not attr.(ExprWithPointsTo).pointsTo(_) or side_effecting_attribute(attr) } @@ -68,7 +69,7 @@ predicate side_effecting_binary(Expr b) { pragma[nomagic] private predicate binary_operator_special_method( - BinaryExpr b, Expr sub, ClassValue cls, string method_name + BinaryExpr b, ExprWithPointsTo sub, ClassValue cls, string method_name ) { method_name = special_method() and sub = b.getLeft() and @@ -77,7 +78,9 @@ private predicate binary_operator_special_method( } pragma[nomagic] -private predicate comparison_special_method(Compare b, Expr sub, ClassValue cls, string method_name) { +private predicate comparison_special_method( + Compare b, ExprWithPointsTo sub, ClassValue cls, string method_name +) { exists(Cmpop op | b.compares(sub, op, _) and method_name = op.getSpecialMethodName() diff --git a/python/ql/src/Statements/UnreachableCode.ql b/python/ql/src/Statements/UnreachableCode.ql index 98c99ac12185..55582ed2f061 100644 --- a/python/ql/src/Statements/UnreachableCode.ql +++ b/python/ql/src/Statements/UnreachableCode.ql @@ -13,6 +13,7 @@ */ import python +private import LegacyPointsTo predicate typing_import(ImportingStmt is) { exists(Module m | @@ -33,7 +34,11 @@ predicate unique_yield(Stmt s) { /** Holds if `contextlib.suppress` may be used in the same scope as `s` */ predicate suppression_in_scope(Stmt s) { exists(With w | - w.getContextExpr().(Call).getFunc().pointsTo(Value::named("contextlib.suppress")) and + w.getContextExpr() + .(Call) + .getFunc() + .(ExprWithPointsTo) + .pointsTo(Value::named("contextlib.suppress")) and w.getScope() = s.getScope() ) } diff --git a/python/ql/src/Statements/UnusedExceptionObject.ql b/python/ql/src/Statements/UnusedExceptionObject.ql index 90724b9f1671..9a6a3650b7e6 100644 --- a/python/ql/src/Statements/UnusedExceptionObject.ql +++ b/python/ql/src/Statements/UnusedExceptionObject.ql @@ -12,10 +12,11 @@ */ import python +private import LegacyPointsTo from Call call, ClassValue ex where - call.getFunc().pointsTo(ex) and + call.getFunc().(ExprWithPointsTo).pointsTo(ex) and ex.getASuperType() = ClassValue::exception() and exists(ExprStmt s | s.getValue() = call) select call, "Instantiating an exception, but not raising it, has no effect." diff --git a/python/ql/src/Variables/UndefinedGlobal.ql b/python/ql/src/Variables/UndefinedGlobal.ql index f88f5504df81..3ea1c0d38eb6 100644 --- a/python/ql/src/Variables/UndefinedGlobal.ql +++ b/python/ql/src/Variables/UndefinedGlobal.ql @@ -11,6 +11,7 @@ */ import python +private import LegacyPointsTo import Variables.MonkeyPatched import Loop import semmle.python.pointsto.PointsTo @@ -95,7 +96,7 @@ predicate undefined_use(Name u) { not contains_unknown_import_star(u.getEnclosingModule()) and not use_of_exec(u.getEnclosingModule()) and not exists(u.getVariable().getAStore()) and - not u.pointsTo(_) and + not u.(ExprWithPointsTo).pointsTo(_) and not probably_defined_in_loop(u) } diff --git a/python/ql/src/Variables/UninitializedLocal.ql b/python/ql/src/Variables/UninitializedLocal.ql index a6ac7d490ce6..d4d94f5a4f37 100644 --- a/python/ql/src/Variables/UninitializedLocal.ql +++ b/python/ql/src/Variables/UninitializedLocal.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo import Undefined import semmle.python.pointsto.PointsTo @@ -30,7 +31,7 @@ predicate uninitialized_local(NameNode use) { predicate explicitly_guarded(NameNode u) { exists(Try t | t.getBody().contains(u.getNode()) and - t.getAHandler().getType().pointsTo(ClassValue::nameError()) + t.getAHandler().getType().(ExprWithPointsTo).pointsTo(ClassValue::nameError()) ) } diff --git a/python/ql/src/analysis/ImportFailure.ql b/python/ql/src/analysis/ImportFailure.ql index 9dd6ac52adcf..c9289a8b474a 100644 --- a/python/ql/src/analysis/ImportFailure.ql +++ b/python/ql/src/analysis/ImportFailure.ql @@ -54,7 +54,7 @@ string os_specific_import(ImportExpr ie) { string get_os() { py_flags_versioned("sys.platform", result, major_version().toString()) } predicate ok_to_fail(ImportExpr ie) { - alternative_import(ie).refersTo(_) + alternative_import(ie).(ExprWithPointsTo).refersTo(_) or os_specific_import(ie) != get_os() } @@ -80,7 +80,7 @@ class VersionGuard extends ConditionBlock { from ImportExpr ie where - not ie.refersTo(_) and + not ie.(ExprWithPointsTo).refersTo(_) and exists(Context c | c.appliesTo(ie.getAFlowNode())) and not ok_to_fail(ie) and not exists(VersionGuard guard | guard.controls(ie.getAFlowNode().getBasicBlock(), _)) diff --git a/python/ql/src/analysis/RatioOfDefinitions.ql b/python/ql/src/analysis/RatioOfDefinitions.ql index 562deb750051..84b8d7602ec7 100644 --- a/python/ql/src/analysis/RatioOfDefinitions.ql +++ b/python/ql/src/analysis/RatioOfDefinitions.ql @@ -3,9 +3,10 @@ */ import python +private import LegacyPointsTo import analysis.DefinitionTracking -predicate want_to_have_definition(Expr e) { +predicate want_to_have_definition(ExprWithPointsTo e) { /* not builtin object like len, tuple, etc. */ not exists(Value builtin | e.pointsTo(builtin) and builtin.isBuiltin()) and ( diff --git a/python/ql/test/2/library-tests/six/pointsto.ql b/python/ql/test/2/library-tests/six/pointsto.ql index cca7eeede109..66a9d449a768 100644 --- a/python/ql/test/2/library-tests/six/pointsto.ql +++ b/python/ql/test/2/library-tests/six/pointsto.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo string longname(Expr e) { result = e.(Name).getId() @@ -6,6 +7,6 @@ string longname(Expr e) { exists(Attribute a | a = e | result = longname(a.getObject()) + "." + a.getName()) } -from Expr e, Value v +from ExprWithPointsTo e, Value v where e.pointsTo(v) and e.getLocation().getFile().getShortName() = "test.py" select longname(e), v.toString() diff --git a/python/ql/test/3/library-tests/six/pointsto.ql b/python/ql/test/3/library-tests/six/pointsto.ql index cca7eeede109..66a9d449a768 100644 --- a/python/ql/test/3/library-tests/six/pointsto.ql +++ b/python/ql/test/3/library-tests/six/pointsto.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo string longname(Expr e) { result = e.(Name).getId() @@ -6,6 +7,6 @@ string longname(Expr e) { exists(Attribute a | a = e | result = longname(a.getObject()) + "." + a.getName()) } -from Expr e, Value v +from ExprWithPointsTo e, Value v where e.pointsTo(v) and e.getLocation().getFile().getShortName() = "test.py" select longname(e), v.toString() From 820d8e76c44dc4dd4b22be36c61275629d22e38f Mon Sep 17 00:00:00 2001 From: Taus Date: Thu, 30 Oct 2025 12:04:31 +0000 Subject: [PATCH 04/19] Python: Remove points-to from `Module` --- python/ql/lib/LegacyPointsTo.qll | 17 +++++++++++++++++ python/ql/lib/semmle/python/Module.qll | 10 ---------- python/ql/src/Variables/UnusedModuleVariable.ql | 3 ++- python/ql/test/extractor-tests/exports/Test.ql | 3 ++- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/python/ql/lib/LegacyPointsTo.qll b/python/ql/lib/LegacyPointsTo.qll index d5961fc02136..3e6758546018 100644 --- a/python/ql/lib/LegacyPointsTo.qll +++ b/python/ql/lib/LegacyPointsTo.qll @@ -21,6 +21,7 @@ private import python private import semmle.python.pointsto.PointsTo +private import semmle.python.objects.Modules /** * An extension of `ControlFlowNode` that provides points-to predicates. @@ -191,3 +192,19 @@ class ExprWithPointsTo extends Expr { override string getAQlClass() { none() } } + +/** + * An extension of `Module` that provides points-to related methods. + */ +class ModuleWithPointsTo extends Module { + /** Gets a name exported by this module, that is the names that will be added to a namespace by 'from this-module import *' */ + string getAnExport() { + py_exports(this, result) + or + exists(ModuleObjectInternal mod | mod.getSource() = this.getEntryNode() | + mod.(ModuleValue).exports(result) + ) + } + + override string getAQlClass() { none() } +} diff --git a/python/ql/lib/semmle/python/Module.qll b/python/ql/lib/semmle/python/Module.qll index 307433fe95bc..666217874b79 100644 --- a/python/ql/lib/semmle/python/Module.qll +++ b/python/ql/lib/semmle/python/Module.qll @@ -1,5 +1,4 @@ import python -private import semmle.python.objects.Modules private import semmle.python.internal.CachedStages /** @@ -66,15 +65,6 @@ class Module extends Module_, Scope, AstNode { /** Whether this module is a package initializer */ predicate isPackageInit() { this.getName().matches("%\\_\\_init\\_\\_") and not this.isPackage() } - /** Gets a name exported by this module, that is the names that will be added to a namespace by 'from this-module import *' */ - string getAnExport() { - py_exports(this, result) - or - exists(ModuleObjectInternal mod | mod.getSource() = this.getEntryNode() | - mod.(ModuleValue).exports(result) - ) - } - /** Gets the source file for this module */ File getFile() { py_module_path(this, result) } diff --git a/python/ql/src/Variables/UnusedModuleVariable.ql b/python/ql/src/Variables/UnusedModuleVariable.ql index 855ca27a7417..24d6559d6fea 100644 --- a/python/ql/src/Variables/UnusedModuleVariable.ql +++ b/python/ql/src/Variables/UnusedModuleVariable.ql @@ -13,6 +13,7 @@ */ import python +private import LegacyPointsTo import Definition /** @@ -58,7 +59,7 @@ predicate unused_global(Name unused, GlobalVariable v) { // indirectly defn.getBasicBlock().reachesExit() and u.getScope() != unused.getScope() ) and - not unused.getEnclosingModule().getAnExport() = v.getId() and + not unused.getEnclosingModule().(ModuleWithPointsTo).getAnExport() = v.getId() and not exists(unused.getParentNode().(ClassDef).getDefinedClass().getADecorator()) and not exists(unused.getParentNode().(FunctionDef).getDefinedFunction().getADecorator()) and unused.defines(v) and diff --git a/python/ql/test/extractor-tests/exports/Test.ql b/python/ql/test/extractor-tests/exports/Test.ql index 50bc0a4ab56d..b04a904197ca 100644 --- a/python/ql/test/extractor-tests/exports/Test.ql +++ b/python/ql/test/extractor-tests/exports/Test.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo -from Module m +from ModuleWithPointsTo m select m.toString(), m.getAnExport().toString() From e702d3bfc86df03ef53f12b89bebfd97ff42a06e Mon Sep 17 00:00:00 2001 From: Taus Date: Thu, 30 Oct 2025 15:16:51 +0000 Subject: [PATCH 05/19] Python: Add change note I wasn't entirely sure if this should be classified as `deprecated` or `breaking`, but seeing as these changes technically _could_ break existing queries (requiring a small rewrite), I opted for the latter. --- .../2025-10-30-remove-points-to-from-cfg-and-expr.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 python/ql/lib/change-notes/2025-10-30-remove-points-to-from-cfg-and-expr.md diff --git a/python/ql/lib/change-notes/2025-10-30-remove-points-to-from-cfg-and-expr.md b/python/ql/lib/change-notes/2025-10-30-remove-points-to-from-cfg-and-expr.md new file mode 100644 index 000000000000..9b8eef6bcbae --- /dev/null +++ b/python/ql/lib/change-notes/2025-10-30-remove-points-to-from-cfg-and-expr.md @@ -0,0 +1,5 @@ +--- +category: breaking +--- + +- The classes `ControlFlowNode`, `Expr`, and `Module` no longer expose predicates that invoke the points-to analysis. To access these predicates, import the module `LegacyPointsTo` and follow the instructions given therein. From 05684b6eb518e33d3ad97b4460f09f0c7766d87f Mon Sep 17 00:00:00 2001 From: Taus Date: Thu, 30 Oct 2025 16:37:28 +0000 Subject: [PATCH 06/19] Python: Remove points-to references from `python.qll` For now, these have just been made into `private` imports. After doing this, I went through all of the (now not compiling) files and added in private imports to the modules that they actually depended on. I also added an explicit import of `LegacyPointsTo` (even though it may be unnecessary) in cases where the points-to dependency was somewhat surprising (and one we want to get rid of). This was primarily inside the various SSA layers. For modules inside `semmle.python.{types, objects, pointsto}` I did not bother, as these are fairly clearly related to points-to. --- python/ql/lib/LegacyPointsTo.qll | 18 +++++++++++-- python/ql/lib/analysis/DefinitionTracking.qll | 1 - python/ql/lib/python.qll | 26 +++++++++---------- python/ql/lib/semmle/python/Flow.qll | 1 + python/ql/lib/semmle/python/Metrics.qll | 3 +++ python/ql/lib/semmle/python/SSA.qll | 1 + python/ql/lib/semmle/python/SelfAttribute.qll | 1 + .../new/internal/ImportResolution.qll | 1 + .../python/dataflow/old/Configuration.qll | 2 +- .../python/dataflow/old/Implementation.qll | 1 - .../python/dataflow/old/StateTracking.qll | 4 +-- .../python/dataflow/old/TaintTracking.qll | 1 - .../python/dependencies/DependencyKind.qll | 1 + .../python/dependencies/TechInventory.qll | 1 + .../ql/lib/semmle/python/essa/Definitions.qll | 4 ++- python/ql/lib/semmle/python/essa/Essa.qll | 2 ++ .../lib/semmle/python/essa/SsaDefinitions.qll | 1 + .../ql/lib/semmle/python/libraries/Zope.qll | 2 +- .../lib/semmle/python/objects/Constants.qll | 1 + .../lib/semmle/python/objects/Descriptors.qll | 1 + .../lib/semmle/python/objects/Instances.qll | 2 ++ .../ql/lib/semmle/python/objects/Modules.qll | 1 + .../lib/semmle/python/objects/ObjectAPI.qll | 3 --- .../ql/lib/semmle/python/objects/TObject.qll | 1 + python/ql/lib/semmle/python/pointsto/Base.qll | 20 ++------------ .../lib/semmle/python/pointsto/CallGraph.qll | 2 ++ .../lib/semmle/python/pointsto/PointsTo.qll | 6 +++++ .../python/pointsto/PointsToContext.qll | 2 ++ .../ql/lib/semmle/python/types/Builtins.qll | 1 + .../lib/semmle/python/types/ClassObject.qll | 4 +++ .../lib/semmle/python/types/Descriptors.qll | 3 +++ .../ql/lib/semmle/python/types/Extensions.qll | 1 + .../semmle/python/types/FunctionObject.qll | 3 --- .../ql/lib/semmle/python/types/ModuleKind.qll | 1 + .../lib/semmle/python/types/ModuleObject.qll | 3 +++ python/ql/lib/semmle/python/types/Object.qll | 3 ++- .../semmle/python/values/StringAttributes.qll | 3 --- .../src/Expressions/ContainsNonContainer.ql | 1 - python/ql/src/Expressions/IsComparisons.qll | 1 + .../ql/src/Statements/RedundantAssignment.ql | 1 + python/ql/src/Variables/UndefinedGlobal.ql | 1 - python/ql/src/Variables/UninitializedLocal.ql | 1 - python/ql/src/analysis/Efficiency.ql | 2 -- 43 files changed, 82 insertions(+), 57 deletions(-) diff --git a/python/ql/lib/LegacyPointsTo.qll b/python/ql/lib/LegacyPointsTo.qll index 3e6758546018..b4f9f012fa71 100644 --- a/python/ql/lib/LegacyPointsTo.qll +++ b/python/ql/lib/LegacyPointsTo.qll @@ -20,8 +20,22 @@ */ private import python -private import semmle.python.pointsto.PointsTo -private import semmle.python.objects.Modules +import semmle.python.pointsto.Base +import semmle.python.pointsto.Context +import semmle.python.pointsto.PointsTo +import semmle.python.pointsto.PointsToContext +import semmle.python.objects.Modules +import semmle.python.objects.ObjectAPI +import semmle.python.objects.ObjectInternal +import semmle.python.types.Object +import semmle.python.types.ClassObject +import semmle.python.types.FunctionObject +import semmle.python.types.ModuleObject +import semmle.python.types.Exceptions +import semmle.python.types.Properties +import semmle.python.types.ImportTime +import semmle.python.types.Descriptors +import semmle.python.SelfAttribute /** * An extension of `ControlFlowNode` that provides points-to predicates. diff --git a/python/ql/lib/analysis/DefinitionTracking.qll b/python/ql/lib/analysis/DefinitionTracking.qll index 53f8e791cd8b..c019e92c0ca3 100644 --- a/python/ql/lib/analysis/DefinitionTracking.qll +++ b/python/ql/lib/analysis/DefinitionTracking.qll @@ -4,7 +4,6 @@ import python private import LegacyPointsTo -import semmle.python.pointsto.PointsTo import IDEContextual private newtype TDefinition = diff --git a/python/ql/lib/python.qll b/python/ql/lib/python.qll index b08f0ae35bb1..d127e297dbb4 100644 --- a/python/ql/lib/python.qll +++ b/python/ql/lib/python.qll @@ -19,22 +19,22 @@ import semmle.python.Constants import semmle.python.Scope import semmle.python.Comment import semmle.python.GuardedControlFlow -import semmle.python.types.ImportTime -import semmle.python.types.Object -import semmle.python.types.ClassObject -import semmle.python.types.FunctionObject -import semmle.python.types.ModuleObject -import semmle.python.types.Version -import semmle.python.types.Descriptors +private import semmle.python.types.ImportTime +private import semmle.python.types.Object +private import semmle.python.types.ClassObject +private import semmle.python.types.FunctionObject +private import semmle.python.types.ModuleObject +private import semmle.python.types.Version +private import semmle.python.types.Descriptors import semmle.python.SSA -import semmle.python.SelfAttribute -import semmle.python.types.Properties +private import semmle.python.SelfAttribute +private import semmle.python.types.Properties import semmle.python.xml.XML import semmle.python.essa.Essa -import semmle.python.pointsto.Base -import semmle.python.pointsto.Context -import semmle.python.pointsto.CallGraph -import semmle.python.objects.ObjectAPI +private import semmle.python.pointsto.Base +private import semmle.python.pointsto.Context +private import semmle.python.pointsto.CallGraph +private import semmle.python.objects.ObjectAPI import semmle.python.Unit import site private import semmle.python.Overlay diff --git a/python/ql/lib/semmle/python/Flow.qll b/python/ql/lib/semmle/python/Flow.qll index 496c1abc52a1..6574979f9c8c 100644 --- a/python/ql/lib/semmle/python/Flow.qll +++ b/python/ql/lib/semmle/python/Flow.qll @@ -1,6 +1,7 @@ import python private import semmle.python.internal.CachedStages private import codeql.controlflow.BasicBlock as BB +private import LegacyPointsTo /* * Note about matching parent and child nodes and CFG splitting: diff --git a/python/ql/lib/semmle/python/Metrics.qll b/python/ql/lib/semmle/python/Metrics.qll index dcc5cf959d93..f36454cccd51 100644 --- a/python/ql/lib/semmle/python/Metrics.qll +++ b/python/ql/lib/semmle/python/Metrics.qll @@ -1,5 +1,8 @@ import python private import LegacyPointsTo +private import semmle.python.types.FunctionObject +private import semmle.python.types.ClassObject +private import semmle.python.SelfAttribute /** The metrics for a function */ class FunctionMetrics extends Function { diff --git a/python/ql/lib/semmle/python/SSA.qll b/python/ql/lib/semmle/python/SSA.qll index 98cd39a4c43c..a139f22dfc6f 100644 --- a/python/ql/lib/semmle/python/SSA.qll +++ b/python/ql/lib/semmle/python/SSA.qll @@ -1,6 +1,7 @@ /** SSA library */ import python +private import LegacyPointsTo /** * A single static assignment variable. diff --git a/python/ql/lib/semmle/python/SelfAttribute.qll b/python/ql/lib/semmle/python/SelfAttribute.qll index 01a110999baf..90ef2b38401a 100644 --- a/python/ql/lib/semmle/python/SelfAttribute.qll +++ b/python/ql/lib/semmle/python/SelfAttribute.qll @@ -5,6 +5,7 @@ import python private import semmle.python.pointsto.Filters +private import LegacyPointsTo /** * An attribute access where the left hand side of the attribute expression diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/ImportResolution.qll b/python/ql/lib/semmle/python/dataflow/new/internal/ImportResolution.qll index e1290b7758c4..f3943f53f860 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/ImportResolution.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/ImportResolution.qll @@ -9,6 +9,7 @@ private import semmle.python.dataflow.new.DataFlow private import semmle.python.dataflow.new.internal.ImportStar private import semmle.python.dataflow.new.TypeTracking private import semmle.python.dataflow.new.internal.DataFlowPrivate +private import semmle.python.essa.SsaDefinitions /** * Python modules and the way imports are resolved are... complicated. Here's a crash course in how diff --git a/python/ql/lib/semmle/python/dataflow/old/Configuration.qll b/python/ql/lib/semmle/python/dataflow/old/Configuration.qll index 7d03e6c562fa..f0e33169cf27 100644 --- a/python/ql/lib/semmle/python/dataflow/old/Configuration.qll +++ b/python/ql/lib/semmle/python/dataflow/old/Configuration.qll @@ -1,6 +1,6 @@ import python import semmle.python.dataflow.TaintTracking -private import semmle.python.objects.ObjectInternal +private import LegacyPointsTo private import semmle.python.dataflow.Implementation module TaintTracking { diff --git a/python/ql/lib/semmle/python/dataflow/old/Implementation.qll b/python/ql/lib/semmle/python/dataflow/old/Implementation.qll index 83476db803c6..eb7e5fdc9a5c 100644 --- a/python/ql/lib/semmle/python/dataflow/old/Implementation.qll +++ b/python/ql/lib/semmle/python/dataflow/old/Implementation.qll @@ -1,7 +1,6 @@ import python private import LegacyPointsTo import semmle.python.dataflow.TaintTracking -private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.Filters as Filters import semmle.python.dataflow.Legacy diff --git a/python/ql/lib/semmle/python/dataflow/old/StateTracking.qll b/python/ql/lib/semmle/python/dataflow/old/StateTracking.qll index 2ca9be0dfb94..0eeb103ee552 100644 --- a/python/ql/lib/semmle/python/dataflow/old/StateTracking.qll +++ b/python/ql/lib/semmle/python/dataflow/old/StateTracking.qll @@ -9,9 +9,7 @@ */ import python -private import semmle.python.pointsto.PointsTo -private import semmle.python.pointsto.PointsToContext -private import semmle.python.objects.ObjectInternal +private import LegacyPointsTo /** A state that should be tracked. */ abstract class TrackableState extends string { diff --git a/python/ql/lib/semmle/python/dataflow/old/TaintTracking.qll b/python/ql/lib/semmle/python/dataflow/old/TaintTracking.qll index 15459a310438..8dfa344f458f 100644 --- a/python/ql/lib/semmle/python/dataflow/old/TaintTracking.qll +++ b/python/ql/lib/semmle/python/dataflow/old/TaintTracking.qll @@ -89,7 +89,6 @@ import python private import LegacyPointsTo private import semmle.python.pointsto.Filters as Filters -private import semmle.python.objects.ObjectInternal private import semmle.python.dataflow.Implementation import semmle.python.dataflow.Configuration diff --git a/python/ql/lib/semmle/python/dependencies/DependencyKind.qll b/python/ql/lib/semmle/python/dependencies/DependencyKind.qll index 2e4fab1af0b6..4ceda85ff417 100644 --- a/python/ql/lib/semmle/python/dependencies/DependencyKind.qll +++ b/python/ql/lib/semmle/python/dependencies/DependencyKind.qll @@ -1,4 +1,5 @@ import semmle.python.dependencies.Dependencies +private import LegacyPointsTo /** * A library describing an abstract mechanism for representing dependency categories. diff --git a/python/ql/lib/semmle/python/dependencies/TechInventory.qll b/python/ql/lib/semmle/python/dependencies/TechInventory.qll index 20a938b86d06..2c29a05c48b2 100644 --- a/python/ql/lib/semmle/python/dependencies/TechInventory.qll +++ b/python/ql/lib/semmle/python/dependencies/TechInventory.qll @@ -1,6 +1,7 @@ import python import semmle.python.dependencies.Dependencies import semmle.python.dependencies.DependencyKind +private import LegacyPointsTo /** * Combine the source-file and package into a single string: diff --git a/python/ql/lib/semmle/python/essa/Definitions.qll b/python/ql/lib/semmle/python/essa/Definitions.qll index 9c0df69c28e5..d9426fc5612e 100644 --- a/python/ql/lib/semmle/python/essa/Definitions.qll +++ b/python/ql/lib/semmle/python/essa/Definitions.qll @@ -1,5 +1,4 @@ import python - /* * Classification of variables. These should be non-overlapping and complete. * @@ -12,6 +11,9 @@ import python * Escaping globals -- Global variables that have definitions and at least one of those definitions is in another scope. */ +private import LegacyPointsTo +private import semmle.python.essa.SsaDefinitions + /** A source language variable, to be converted into a set of SSA variables. */ abstract class SsaSourceVariable extends @py_variable { SsaSourceVariable() { diff --git a/python/ql/lib/semmle/python/essa/Essa.qll b/python/ql/lib/semmle/python/essa/Essa.qll index cf2aca1e2ac4..1b83f8df6ac1 100644 --- a/python/ql/lib/semmle/python/essa/Essa.qll +++ b/python/ql/lib/semmle/python/essa/Essa.qll @@ -6,6 +6,8 @@ import python private import SsaCompute import semmle.python.essa.Definitions private import semmle.python.internal.CachedStages +private import LegacyPointsTo +private import semmle.python.essa.SsaDefinitions /** An (enhanced) SSA variable derived from `SsaSourceVariable`. */ class EssaVariable extends TEssaDefinition { diff --git a/python/ql/lib/semmle/python/essa/SsaDefinitions.qll b/python/ql/lib/semmle/python/essa/SsaDefinitions.qll index 0c1c8836f4e5..2b15f1a2ab2c 100644 --- a/python/ql/lib/semmle/python/essa/SsaDefinitions.qll +++ b/python/ql/lib/semmle/python/essa/SsaDefinitions.qll @@ -5,6 +5,7 @@ import python private import semmle.python.internal.CachedStages +private import LegacyPointsTo cached module SsaSource { diff --git a/python/ql/lib/semmle/python/libraries/Zope.qll b/python/ql/lib/semmle/python/libraries/Zope.qll index fea3cecf4182..defea3e47204 100644 --- a/python/ql/lib/semmle/python/libraries/Zope.qll +++ b/python/ql/lib/semmle/python/libraries/Zope.qll @@ -1,7 +1,7 @@ /** Utilities for handling the zope libraries */ import python -private import semmle.python.pointsto.PointsTo +private import LegacyPointsTo /** A method that belongs to a sub-class of `zope.interface.Interface` */ class ZopeInterfaceMethodValue extends PythonFunctionValue { diff --git a/python/ql/lib/semmle/python/objects/Constants.qll b/python/ql/lib/semmle/python/objects/Constants.qll index 31b63399ff44..49221df5b67b 100644 --- a/python/ql/lib/semmle/python/objects/Constants.qll +++ b/python/ql/lib/semmle/python/objects/Constants.qll @@ -5,6 +5,7 @@ private import semmle.python.pointsto.PointsTo private import semmle.python.pointsto.MRO private import semmle.python.pointsto.PointsToContext private import semmle.python.types.Builtins +private import semmle.python.objects.ObjectAPI /** * A constant. diff --git a/python/ql/lib/semmle/python/objects/Descriptors.qll b/python/ql/lib/semmle/python/objects/Descriptors.qll index 2c18708e16a8..5cb855ee5cac 100644 --- a/python/ql/lib/semmle/python/objects/Descriptors.qll +++ b/python/ql/lib/semmle/python/objects/Descriptors.qll @@ -5,6 +5,7 @@ private import semmle.python.pointsto.PointsTo private import semmle.python.pointsto.PointsToContext private import semmle.python.pointsto.MRO private import semmle.python.types.Builtins +private import semmle.python.pointsto.Context /** A property object. */ class PropertyInternal extends ObjectInternal, TProperty { diff --git a/python/ql/lib/semmle/python/objects/Instances.qll b/python/ql/lib/semmle/python/objects/Instances.qll index 0b4187b69283..2ae00502902c 100644 --- a/python/ql/lib/semmle/python/objects/Instances.qll +++ b/python/ql/lib/semmle/python/objects/Instances.qll @@ -5,6 +5,8 @@ private import semmle.python.pointsto.PointsTo private import semmle.python.pointsto.MRO private import semmle.python.pointsto.PointsToContext private import semmle.python.types.Builtins +private import semmle.python.pointsto.Context +private import semmle.python.pointsto.Base /** A class representing instances */ abstract class InstanceObject extends ObjectInternal { diff --git a/python/ql/lib/semmle/python/objects/Modules.qll b/python/ql/lib/semmle/python/objects/Modules.qll index e523ad0b70a6..8c5653fa2a3e 100644 --- a/python/ql/lib/semmle/python/objects/Modules.qll +++ b/python/ql/lib/semmle/python/objects/Modules.qll @@ -5,6 +5,7 @@ private import semmle.python.pointsto.PointsTo private import semmle.python.pointsto.MRO private import semmle.python.pointsto.PointsToContext private import semmle.python.types.Builtins +private import semmle.python.types.ImportTime /** A class representing modules */ abstract class ModuleObjectInternal extends ObjectInternal { diff --git a/python/ql/lib/semmle/python/objects/ObjectAPI.qll b/python/ql/lib/semmle/python/objects/ObjectAPI.qll index 45247c5d9d44..a5d4d91cc7ab 100644 --- a/python/ql/lib/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/lib/semmle/python/objects/ObjectAPI.qll @@ -6,9 +6,6 @@ import python private import LegacyPointsTo private import TObject -private import semmle.python.objects.ObjectInternal -private import semmle.python.pointsto.PointsTo -private import semmle.python.pointsto.PointsToContext private import semmle.python.pointsto.MRO private import semmle.python.types.Builtins diff --git a/python/ql/lib/semmle/python/objects/TObject.qll b/python/ql/lib/semmle/python/objects/TObject.qll index 12b4dc901c39..c041827ff5a9 100644 --- a/python/ql/lib/semmle/python/objects/TObject.qll +++ b/python/ql/lib/semmle/python/objects/TObject.qll @@ -6,6 +6,7 @@ private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo private import semmle.python.pointsto.PointsToContext private import semmle.python.internal.CachedStages +private import semmle.python.pointsto.Context /** * Internal type backing `ObjectInternal` and `Value` diff --git a/python/ql/lib/semmle/python/pointsto/Base.qll b/python/ql/lib/semmle/python/pointsto/Base.qll index 56dc633eb9c8..bf159c4b559d 100644 --- a/python/ql/lib/semmle/python/pointsto/Base.qll +++ b/python/ql/lib/semmle/python/pointsto/Base.qll @@ -12,6 +12,8 @@ import python import semmle.python.essa.SsaDefinitions private import semmle.python.types.Builtins private import semmle.python.internal.CachedStages +private import semmle.python.types.Object +private import semmle.python.types.ClassObject /* * The following predicates exist in order to provide @@ -42,24 +44,6 @@ private predicate class_defines_name(Class cls, string name) { exists(SsaVariable var | name = var.getId() and var.getAUse() = cls.getANormalExit()) } -/** Hold if `expr` is a test (a branch) and `use` is within that test */ -predicate test_contains(ControlFlowNode expr, ControlFlowNode use) { - expr.getNode() instanceof Expr and - expr.isBranch() and - expr.getAChild*() = use -} - -/** Holds if `f` is an import of the form `from .[...] import ...` and the enclosing scope is an __init__ module */ -predicate import_from_dot_in_init(ImportExprNode f) { - f.getScope() = any(Module m).getInitModule() and - ( - f.getNode().getLevel() = 1 and - not exists(f.getNode().getName()) - or - f.getNode().getImportedModuleName() = f.getEnclosingModule().getPackage().getName() - ) -} - /** Gets the pseudo-object representing the value referred to by an undefined variable */ Object undefinedVariable() { py_special_objects(result, "_semmle_undefined_value") } diff --git a/python/ql/lib/semmle/python/pointsto/CallGraph.qll b/python/ql/lib/semmle/python/pointsto/CallGraph.qll index da2254395886..734a55402541 100644 --- a/python/ql/lib/semmle/python/pointsto/CallGraph.qll +++ b/python/ql/lib/semmle/python/pointsto/CallGraph.qll @@ -11,6 +11,8 @@ import python private import semmle.python.pointsto.PointsToContext +private import semmle.python.types.FunctionObject +private import semmle.python.pointsto.Context private newtype TTInvocation = TInvocation(FunctionObject f, Context c) { diff --git a/python/ql/lib/semmle/python/pointsto/PointsTo.qll b/python/ql/lib/semmle/python/pointsto/PointsTo.qll index 56e8f6d6a63e..cca9d35bfd9f 100644 --- a/python/ql/lib/semmle/python/pointsto/PointsTo.qll +++ b/python/ql/lib/semmle/python/pointsto/PointsTo.qll @@ -7,6 +7,12 @@ private import semmle.python.pointsto.MRO private import semmle.python.types.Builtins private import semmle.python.types.Extensions private import semmle.python.internal.CachedStages +private import semmle.python.types.Object +private import semmle.python.types.FunctionObject +private import semmle.python.types.ClassObject +private import semmle.python.pointsto.Base +private import semmle.python.pointsto.Context +private import semmle.python.types.ImportTime /* Use this version for speed */ class CfgOrigin extends @py_object { diff --git a/python/ql/lib/semmle/python/pointsto/PointsToContext.qll b/python/ql/lib/semmle/python/pointsto/PointsToContext.qll index d68ce93e5761..fb005b8f0466 100644 --- a/python/ql/lib/semmle/python/pointsto/PointsToContext.qll +++ b/python/ql/lib/semmle/python/pointsto/PointsToContext.qll @@ -1,6 +1,8 @@ import python private import semmle.python.pointsto.PointsTo private import semmle.python.objects.ObjectInternal +private import semmle.python.types.ImportTime +private import semmle.python.types.Version /* * A note on 'cost'. Cost doesn't represent the cost to compute, diff --git a/python/ql/lib/semmle/python/types/Builtins.qll b/python/ql/lib/semmle/python/types/Builtins.qll index e6a21e1b717b..796397f72cd6 100644 --- a/python/ql/lib/semmle/python/types/Builtins.qll +++ b/python/ql/lib/semmle/python/types/Builtins.qll @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo class Builtin extends @py_cobject { Builtin() { diff --git a/python/ql/lib/semmle/python/types/ClassObject.qll b/python/ql/lib/semmle/python/types/ClassObject.qll index 6954a83463c6..e12954ce5477 100644 --- a/python/ql/lib/semmle/python/types/ClassObject.qll +++ b/python/ql/lib/semmle/python/types/ClassObject.qll @@ -6,6 +6,10 @@ private import semmle.python.pointsto.PointsTo private import semmle.python.pointsto.MRO private import semmle.python.types.Builtins private import semmle.python.objects.ObjectInternal +private import semmle.python.types.Object +private import semmle.python.types.FunctionObject +private import semmle.python.SelfAttribute +private import semmle.python.types.ImportTime /** * A class whose instances represents Python classes. diff --git a/python/ql/lib/semmle/python/types/Descriptors.qll b/python/ql/lib/semmle/python/types/Descriptors.qll index 6a5743c444a8..7a81142a4f24 100644 --- a/python/ql/lib/semmle/python/types/Descriptors.qll +++ b/python/ql/lib/semmle/python/types/Descriptors.qll @@ -1,5 +1,8 @@ import python private import semmle.python.objects.ObjectInternal +private import semmle.python.types.Object +private import semmle.python.types.FunctionObject +private import semmle.python.pointsto.Context /** A class method object. Either a decorated function or an explicit call to classmethod(f) */ class ClassMethodObject extends Object { diff --git a/python/ql/lib/semmle/python/types/Extensions.qll b/python/ql/lib/semmle/python/types/Extensions.qll index f6c824f9ab2f..d292f568fb97 100644 --- a/python/ql/lib/semmle/python/types/Extensions.qll +++ b/python/ql/lib/semmle/python/types/Extensions.qll @@ -16,6 +16,7 @@ private import semmle.python.pointsto.PointsToContext private import semmle.python.objects.TObject /* Make ObjectInternal visible to save extra imports in user code */ import semmle.python.objects.ObjectInternal +import semmle.python.pointsto.Context abstract class PointsToExtension extends @py_flow_node { string toString() { result = "PointsToExtension with missing toString" } diff --git a/python/ql/lib/semmle/python/types/FunctionObject.qll b/python/ql/lib/semmle/python/types/FunctionObject.qll index 72ddb9411fb1..7ff0f37ca9a3 100644 --- a/python/ql/lib/semmle/python/types/FunctionObject.qll +++ b/python/ql/lib/semmle/python/types/FunctionObject.qll @@ -1,10 +1,7 @@ import python private import LegacyPointsTo -import semmle.python.types.Exceptions -private import semmle.python.pointsto.PointsTo private import semmle.python.objects.Callables private import semmle.python.libraries.Zope -private import semmle.python.objects.ObjectInternal private import semmle.python.types.Builtins /** A function object, whether written in Python or builtin */ diff --git a/python/ql/lib/semmle/python/types/ModuleKind.qll b/python/ql/lib/semmle/python/types/ModuleKind.qll index ef44d80701ec..03b64396baea 100644 --- a/python/ql/lib/semmle/python/types/ModuleKind.qll +++ b/python/ql/lib/semmle/python/types/ModuleKind.qll @@ -1,4 +1,5 @@ import python +private import semmle.python.types.ModuleObject private predicate is_normal_module(ModuleObject m) { m instanceof BuiltinModuleObject diff --git a/python/ql/lib/semmle/python/types/ModuleObject.qll b/python/ql/lib/semmle/python/types/ModuleObject.qll index 2e6d3863801e..0dfa96e7050c 100644 --- a/python/ql/lib/semmle/python/types/ModuleObject.qll +++ b/python/ql/lib/semmle/python/types/ModuleObject.qll @@ -2,6 +2,9 @@ import python private import semmle.python.pointsto.PointsTo private import semmle.python.objects.ObjectInternal private import semmle.python.types.ModuleKind +private import semmle.python.types.Object +private import semmle.python.types.ClassObject +private import semmle.python.objects.ObjectAPI abstract class ModuleObject extends Object { ModuleValue theModule() { diff --git a/python/ql/lib/semmle/python/types/Object.qll b/python/ql/lib/semmle/python/types/Object.qll index 1e0868648be0..4c1a19501647 100644 --- a/python/ql/lib/semmle/python/types/Object.qll +++ b/python/ql/lib/semmle/python/types/Object.qll @@ -1,8 +1,9 @@ import python private import LegacyPointsTo -private import semmle.python.objects.ObjectInternal private import semmle.python.types.Builtins private import semmle.python.internal.CachedStages +private import semmle.python.types.Descriptors +private import semmle.python.pointsto.Base cached private predicate is_an_object(@py_object obj) { diff --git a/python/ql/lib/semmle/python/values/StringAttributes.qll b/python/ql/lib/semmle/python/values/StringAttributes.qll index e94540dbf204..e914730ef8ba 100644 --- a/python/ql/lib/semmle/python/values/StringAttributes.qll +++ b/python/ql/lib/semmle/python/values/StringAttributes.qll @@ -1,8 +1,5 @@ import python private import LegacyPointsTo -private import semmle.python.types.Object -private import semmle.python.types.ClassObject -private import semmle.python.types.FunctionObject predicate string_attribute_all(ControlFlowNodeWithPointsTo n, string attr) { (n.getNode() instanceof Unicode or n.getNode() instanceof Bytes) and diff --git a/python/ql/src/Expressions/ContainsNonContainer.ql b/python/ql/src/Expressions/ContainsNonContainer.ql index fd2123dd436e..de8c38795675 100644 --- a/python/ql/src/Expressions/ContainsNonContainer.ql +++ b/python/ql/src/Expressions/ContainsNonContainer.ql @@ -13,7 +13,6 @@ import python private import LegacyPointsTo -import semmle.python.pointsto.PointsTo predicate rhs_in_expr(ControlFlowNode rhs, Compare cmp) { exists(Cmpop op, int i | cmp.getOp(i) = op and cmp.getComparator(i) = rhs.getNode() | diff --git a/python/ql/src/Expressions/IsComparisons.qll b/python/ql/src/Expressions/IsComparisons.qll index 1ed4534bd234..052407f7111b 100644 --- a/python/ql/src/Expressions/IsComparisons.qll +++ b/python/ql/src/Expressions/IsComparisons.qll @@ -3,6 +3,7 @@ import python private import LegacyPointsTo private import semmle.python.objects.ObjectInternal +private import semmle.python.objects.ObjectAPI /** Holds if the comparison `comp` uses `is` or `is not` (represented as `op`) to compare its `left` and `right` arguments. */ predicate comparison_using_is(Compare comp, ControlFlowNode left, Cmpop op, ControlFlowNode right) { diff --git a/python/ql/src/Statements/RedundantAssignment.ql b/python/ql/src/Statements/RedundantAssignment.ql index 357364c41b2f..e3f58995fa14 100644 --- a/python/ql/src/Statements/RedundantAssignment.ql +++ b/python/ql/src/Statements/RedundantAssignment.ql @@ -14,6 +14,7 @@ import python private import LegacyPointsTo +private import semmle.python.objects.ObjectAPI predicate assignment(AssignStmt a, Expr left, Expr right) { a.getATarget() = left and a.getValue() = right diff --git a/python/ql/src/Variables/UndefinedGlobal.ql b/python/ql/src/Variables/UndefinedGlobal.ql index 3ea1c0d38eb6..bfe816d5c589 100644 --- a/python/ql/src/Variables/UndefinedGlobal.ql +++ b/python/ql/src/Variables/UndefinedGlobal.ql @@ -14,7 +14,6 @@ import python private import LegacyPointsTo import Variables.MonkeyPatched import Loop -import semmle.python.pointsto.PointsTo predicate guarded_against_name_error(Name u) { exists(Try t | t.getBody().getAnItem().contains(u) | diff --git a/python/ql/src/Variables/UninitializedLocal.ql b/python/ql/src/Variables/UninitializedLocal.ql index d4d94f5a4f37..48332e01af3c 100644 --- a/python/ql/src/Variables/UninitializedLocal.ql +++ b/python/ql/src/Variables/UninitializedLocal.ql @@ -14,7 +14,6 @@ import python private import LegacyPointsTo import Undefined -import semmle.python.pointsto.PointsTo predicate uninitialized_local(NameNode use) { exists(FastLocalVariable local | use.uses(local) or use.deletes(local) | diff --git a/python/ql/src/analysis/Efficiency.ql b/python/ql/src/analysis/Efficiency.ql index 37cb5c973879..d8ed85f2a2bb 100644 --- a/python/ql/src/analysis/Efficiency.ql +++ b/python/ql/src/analysis/Efficiency.ql @@ -5,8 +5,6 @@ import python private import LegacyPointsTo -import semmle.python.pointsto.PointsTo -import semmle.python.pointsto.PointsToContext predicate trivial(ControlFlowNode f) { f.getNode() instanceof Parameter From 6fdeef0ca601ec39596ee4caa5d368f0a5b5fa4d Mon Sep 17 00:00:00 2001 From: Taus Date: Thu, 30 Oct 2025 16:44:25 +0000 Subject: [PATCH 07/19] Python: Get rid of some `get...Object` methods This frees `Class.qll`, `Exprs.qll`, and `Function.qll` from the clutches of points-to. For the somewhat complicated setup with `getLiteralObject` (an abstract method), I opted for a slightly ugly but workable solution of just defining a predicate on `ImmutableLiteral` that inlines each predicate body, special-cased to the specific instance to which it applies. --- python/ql/lib/LegacyPointsTo.qll | 63 +++++++++++++++++++ python/ql/lib/semmle/python/Class.qll | 3 - python/ql/lib/semmle/python/Exprs.qll | 43 +------------ python/ql/lib/semmle/python/Function.qll | 3 - .../lib/semmle/python/types/ClassObject.qll | 2 +- .../2/extractor-tests/normalise/Numbers.ql | 3 +- .../test/2/library-tests/objects/Literals.ql | 3 +- .../ql/test/library-tests/objects/Literals.ql | 3 +- 8 files changed, 72 insertions(+), 51 deletions(-) diff --git a/python/ql/lib/LegacyPointsTo.qll b/python/ql/lib/LegacyPointsTo.qll index b4f9f012fa71..16d7c7685303 100644 --- a/python/ql/lib/LegacyPointsTo.qll +++ b/python/ql/lib/LegacyPointsTo.qll @@ -222,3 +222,66 @@ class ModuleWithPointsTo extends Module { override string getAQlClass() { none() } } + +/** + * An extension of `Function` that provides points-to related methods. + */ +class FunctionWithPointsTo extends Function { + /** Gets the FunctionObject corresponding to this function */ + FunctionObject getFunctionObject() { result.getOrigin() = this.getDefinition() } + + override string getAQlClass() { none() } +} + +/** + * An extension of `Class` that provides points-to related methods. + */ +class ClassWithPointsTo extends Class { + /** Gets the ClassObject corresponding to this class */ + ClassObject getClassObject() { result.getOrigin() = this.getParent() } + + override string getAQlClass() { none() } +} + +Object getLiteralObject(ImmutableLiteral l) { + l instanceof IntegerLiteral and + ( + py_cobjecttypes(result, theIntType()) and py_cobjectnames(result, l.(Num).getN()) + or + py_cobjecttypes(result, theLongType()) and py_cobjectnames(result, l.(Num).getN()) + ) + or + l instanceof FloatLiteral and + py_cobjecttypes(result, theFloatType()) and + py_cobjectnames(result, l.(Num).getN()) + or + l instanceof ImaginaryLiteral and + py_cobjecttypes(result, theComplexType()) and + py_cobjectnames(result, l.(Num).getN()) + or + l instanceof NegativeIntegerLiteral and + ( + (py_cobjecttypes(result, theIntType()) or py_cobjecttypes(result, theLongType())) and + py_cobjectnames(result, "-" + l.(UnaryExpr).getOperand().(IntegerLiteral).getN()) + ) + or + l instanceof Bytes and + py_cobjecttypes(result, theBytesType()) and + py_cobjectnames(result, l.(Bytes).quotedString()) + or + l instanceof Unicode and + py_cobjecttypes(result, theUnicodeType()) and + py_cobjectnames(result, l.(Unicode).quotedString()) + or + l instanceof True and + name_consts(l, "True") and + result = theTrueObject() + or + l instanceof False and + name_consts(l, "False") and + result = theFalseObject() + or + l instanceof None and + name_consts(l, "None") and + result = theNoneObject() +} diff --git a/python/ql/lib/semmle/python/Class.qll b/python/ql/lib/semmle/python/Class.qll index 58a6504b547c..dd7da9ee0419 100644 --- a/python/ql/lib/semmle/python/Class.qll +++ b/python/ql/lib/semmle/python/Class.qll @@ -141,9 +141,6 @@ class Class extends Class_, Scope, AstNode { /** Gets the metaclass expression */ Expr getMetaClass() { result = this.getParent().getMetaClass() } - /** Gets the ClassObject corresponding to this class */ - ClassObject getClassObject() { result.getOrigin() = this.getParent() } - /** Gets the nth base of this class definition. */ Expr getBase(int index) { result = this.getParent().getBase(index) } diff --git a/python/ql/lib/semmle/python/Exprs.qll b/python/ql/lib/semmle/python/Exprs.qll index e5ee2bdb28c7..203e63f611f3 100644 --- a/python/ql/lib/semmle/python/Exprs.qll +++ b/python/ql/lib/semmle/python/Exprs.qll @@ -240,17 +240,12 @@ class Bytes extends StringLiteral { /* syntax: b"hello" */ Bytes() { not this.isUnicode() } - override Object getLiteralObject() { - py_cobjecttypes(result, theBytesType()) and - py_cobjectnames(result, this.quotedString()) - } - /** * The extractor puts quotes into the name of each string (to prevent "0" clashing with 0). * The following predicate help us match up a string/byte literals in the source * which the equivalent object. */ - private string quotedString() { + string quotedString() { exists(string b_unquoted | b_unquoted = this.getS() | result = "b'" + b_unquoted + "'") } } @@ -266,8 +261,6 @@ class Ellipsis extends Ellipsis_ { * Consists of string (both unicode and byte) literals and numeric literals. */ abstract class ImmutableLiteral extends Expr { - abstract Object getLiteralObject(); - abstract boolean booleanValue(); } @@ -292,12 +285,6 @@ class IntegerLiteral extends Num { override string toString() { result = "IntegerLiteral" } - override Object getLiteralObject() { - py_cobjecttypes(result, theIntType()) and py_cobjectnames(result, this.getN()) - or - py_cobjecttypes(result, theLongType()) and py_cobjectnames(result, this.getN()) - } - override boolean booleanValue() { this.getValue() = 0 and result = false or @@ -317,10 +304,6 @@ class FloatLiteral extends Num { override string toString() { result = "FloatLiteral" } - override Object getLiteralObject() { - py_cobjecttypes(result, theFloatType()) and py_cobjectnames(result, this.getN()) - } - override boolean booleanValue() { this.getValue() = 0.0 and result = false or @@ -343,10 +326,6 @@ class ImaginaryLiteral extends Num { override string toString() { result = "ImaginaryLiteral" } - override Object getLiteralObject() { - py_cobjecttypes(result, theComplexType()) and py_cobjectnames(result, this.getN()) - } - override boolean booleanValue() { this.getValue() = 0.0 and result = false or @@ -365,11 +344,6 @@ class NegativeIntegerLiteral extends ImmutableLiteral, UnaryExpr { override boolean booleanValue() { result = this.getOperand().(IntegerLiteral).booleanValue() } - override Object getLiteralObject() { - (py_cobjecttypes(result, theIntType()) or py_cobjecttypes(result, theLongType())) and - py_cobjectnames(result, "-" + this.getOperand().(IntegerLiteral).getN()) - } - /** * Gets the (integer) value of this constant. Will not return a result if the value does not fit into * a 32 bit signed value @@ -385,11 +359,6 @@ class Unicode extends StringLiteral { /* syntax: "hello" */ Unicode() { this.isUnicode() } - override Object getLiteralObject() { - py_cobjecttypes(result, theUnicodeType()) and - py_cobjectnames(result, this.quotedString()) - } - /** * Gets the quoted representation fo this string. * @@ -593,12 +562,10 @@ class StringLiteral extends Str_, ImmutableLiteral { this.getText() != "" and result = true } - override Object getLiteralObject() { none() } - override string toString() { result = "StringLiteral" } } -private predicate name_consts(Name_ n, string id) { +predicate name_consts(Name_ n, string id) { exists(Variable v | py_variables(v, n) and id = v.getId() | id = "True" or id = "False" or id = "None" ) @@ -627,8 +594,6 @@ class True extends BooleanLiteral { /* syntax: True */ True() { name_consts(this, "True") } - override Object getLiteralObject() { name_consts(this, "True") and result = theTrueObject() } - override boolean booleanValue() { result = true } } @@ -637,8 +602,6 @@ class False extends BooleanLiteral { /* syntax: False */ False() { name_consts(this, "False") } - override Object getLiteralObject() { name_consts(this, "False") and result = theFalseObject() } - override boolean booleanValue() { result = false } } @@ -647,8 +610,6 @@ class None extends NameConstant { /* syntax: None */ None() { name_consts(this, "None") } - override Object getLiteralObject() { name_consts(this, "None") and result = theNoneObject() } - override boolean booleanValue() { result = false } } diff --git a/python/ql/lib/semmle/python/Function.qll b/python/ql/lib/semmle/python/Function.qll index 589d7f471611..a5d122c3de7e 100644 --- a/python/ql/lib/semmle/python/Function.qll +++ b/python/ql/lib/semmle/python/Function.qll @@ -87,9 +87,6 @@ class Function extends Function_, Scope, AstNode { /** Gets the metrics for this function */ FunctionMetrics getMetrics() { result = this } - /** Gets the FunctionObject corresponding to this function */ - FunctionObject getFunctionObject() { result.getOrigin() = this.getDefinition() } - /** * Whether this function is a procedure, that is, it has no explicit return statement and always returns None. * Note that generator and async functions are not procedures as they return generators and coroutines respectively. diff --git a/python/ql/lib/semmle/python/types/ClassObject.qll b/python/ql/lib/semmle/python/types/ClassObject.qll index e12954ce5477..98551d6d5d76 100644 --- a/python/ql/lib/semmle/python/types/ClassObject.qll +++ b/python/ql/lib/semmle/python/types/ClassObject.qll @@ -92,7 +92,7 @@ class ClassObject extends Object { } /** Gets the scope associated with this class, if it is not a builtin class */ - Class getPyClass() { result.getClassObject() = this } + ClassWithPointsTo getPyClass() { result.getClassObject() = this } /** Returns an attribute declared on this class (not on a super-class) */ Object declaredAttribute(string name) { diff --git a/python/ql/test/2/extractor-tests/normalise/Numbers.ql b/python/ql/test/2/extractor-tests/normalise/Numbers.ql index 2a7706002799..9447141ab6af 100644 --- a/python/ql/test/2/extractor-tests/normalise/Numbers.ql +++ b/python/ql/test/2/extractor-tests/normalise/Numbers.ql @@ -7,10 +7,11 @@ */ import python +private import LegacyPointsTo from NumericObject n where - exists(IntegerLiteral i | i.getLiteralObject() = n | + exists(IntegerLiteral i | getLiteralObject(i) = n | i.getEnclosingModule().getFile().getShortName() = "test.py" ) select n.toString(), n.repr() diff --git a/python/ql/test/2/library-tests/objects/Literals.ql b/python/ql/test/2/library-tests/objects/Literals.ql index a7f10b358ff1..d5aee013f251 100644 --- a/python/ql/test/2/library-tests/objects/Literals.ql +++ b/python/ql/test/2/library-tests/objects/Literals.ql @@ -1,5 +1,6 @@ /* Test that there are no literals that do not have a corresponding object. */ import python +private import LegacyPointsTo string repr(Expr e) { result = e.(Num).getN() or @@ -8,5 +9,5 @@ string repr(Expr e) { } from ImmutableLiteral l -where not exists(l.getLiteralObject()) +where not exists(getLiteralObject(l)) select l.getLocation().getStartLine(), repr(l) diff --git a/python/ql/test/library-tests/objects/Literals.ql b/python/ql/test/library-tests/objects/Literals.ql index a7f10b358ff1..d5aee013f251 100644 --- a/python/ql/test/library-tests/objects/Literals.ql +++ b/python/ql/test/library-tests/objects/Literals.ql @@ -1,5 +1,6 @@ /* Test that there are no literals that do not have a corresponding object. */ import python +private import LegacyPointsTo string repr(Expr e) { result = e.(Num).getN() or @@ -8,5 +9,5 @@ string repr(Expr e) { } from ImmutableLiteral l -where not exists(l.getLiteralObject()) +where not exists(getLiteralObject(l)) select l.getLocation().getStartLine(), repr(l) From 06ef98574b5aa26e64a284cc94a28a2e49c63b74 Mon Sep 17 00:00:00 2001 From: Taus Date: Thu, 30 Oct 2025 16:46:33 +0000 Subject: [PATCH 08/19] Python: Move some non-points-to methods out of points-to These methods were in `pointsto.Base` but did not actually interact with the points-to machinery directly, so they were easy to move out. --- python/ql/lib/semmle/python/essa/Definitions.qll | 11 +++++++++++ python/ql/lib/semmle/python/essa/SsaDefinitions.qll | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/python/ql/lib/semmle/python/essa/Definitions.qll b/python/ql/lib/semmle/python/essa/Definitions.qll index d9426fc5612e..17b4e622ea13 100644 --- a/python/ql/lib/semmle/python/essa/Definitions.qll +++ b/python/ql/lib/semmle/python/essa/Definitions.qll @@ -276,6 +276,17 @@ class ModuleVariable extends SsaSourceVariable instanceof GlobalVariable { override CallNode redefinedAtCallSite() { none() } } +/** Holds if `f` is an import of the form `from .[...] import ...` and the enclosing scope is an __init__ module */ +private predicate import_from_dot_in_init(ImportExprNode f) { + f.getScope() = any(Module m).getInitModule() and + ( + f.getNode().getLevel() = 1 and + not exists(f.getNode().getName()) + or + f.getNode().getImportedModuleName() = f.getEnclosingModule().getPackage().getName() + ) +} + class NonEscapingGlobalVariable extends ModuleVariable { NonEscapingGlobalVariable() { this instanceof GlobalVariable and diff --git a/python/ql/lib/semmle/python/essa/SsaDefinitions.qll b/python/ql/lib/semmle/python/essa/SsaDefinitions.qll index 2b15f1a2ab2c..b263287d05d9 100644 --- a/python/ql/lib/semmle/python/essa/SsaDefinitions.qll +++ b/python/ql/lib/semmle/python/essa/SsaDefinitions.qll @@ -7,6 +7,13 @@ import python private import semmle.python.internal.CachedStages private import LegacyPointsTo +/** Hold if `expr` is a test (a branch) and `use` is within that test */ +predicate test_contains(ControlFlowNode expr, ControlFlowNode use) { + expr.getNode() instanceof Expr and + expr.isBranch() and + expr.getAChild*() = use +} + cached module SsaSource { /** Holds if `v` is used as the receiver in a method call. */ From 08a695ab00366f15a43da657ceca34a5ebc7e64a Mon Sep 17 00:00:00 2001 From: Taus Date: Thu, 30 Oct 2025 23:00:14 +0000 Subject: [PATCH 09/19] Python: Fix example snippets One might argue that these should be rewritten entirely to use more modern APIs, but for now I'll be content with just having them compile properly. --- python/ql/examples/snippets/call.ql | 1 + python/ql/examples/snippets/extend_class.ql | 1 + python/ql/examples/snippets/method_call.ql | 1 + python/ql/examples/snippets/mutualrecursion.ql | 1 + python/ql/examples/snippets/override_method.ql | 1 + python/ql/examples/snippets/recursion.ql | 1 + 6 files changed, 6 insertions(+) diff --git a/python/ql/examples/snippets/call.ql b/python/ql/examples/snippets/call.ql index b326024a33c9..0c68bbd69b97 100644 --- a/python/ql/examples/snippets/call.ql +++ b/python/ql/examples/snippets/call.ql @@ -7,6 +7,7 @@ */ import python +private import LegacyPointsTo from Value len, CallNode call where len.getName() = "len" and len.getACall() = call diff --git a/python/ql/examples/snippets/extend_class.ql b/python/ql/examples/snippets/extend_class.ql index 805929ab709a..8efc1b8241a8 100644 --- a/python/ql/examples/snippets/extend_class.ql +++ b/python/ql/examples/snippets/extend_class.ql @@ -11,6 +11,7 @@ */ import python +private import LegacyPointsTo from ClassObject sub, ClassObject base where diff --git a/python/ql/examples/snippets/method_call.ql b/python/ql/examples/snippets/method_call.ql index f78a9e43be00..c331b7c8beff 100644 --- a/python/ql/examples/snippets/method_call.ql +++ b/python/ql/examples/snippets/method_call.ql @@ -7,6 +7,7 @@ */ import python +private import LegacyPointsTo from AstNode call, PythonFunctionValue method where diff --git a/python/ql/examples/snippets/mutualrecursion.ql b/python/ql/examples/snippets/mutualrecursion.ql index 0cd445b6e3bc..040dbae99d46 100644 --- a/python/ql/examples/snippets/mutualrecursion.ql +++ b/python/ql/examples/snippets/mutualrecursion.ql @@ -7,6 +7,7 @@ */ import python +private import LegacyPointsTo from FunctionObject m, FunctionObject n where m != n and m.getACallee() = n and n.getACallee() = m diff --git a/python/ql/examples/snippets/override_method.ql b/python/ql/examples/snippets/override_method.ql index 2b601d59df74..40c2eed85317 100644 --- a/python/ql/examples/snippets/override_method.ql +++ b/python/ql/examples/snippets/override_method.ql @@ -7,6 +7,7 @@ */ import python +private import LegacyPointsTo from FunctionObject override, FunctionObject base where diff --git a/python/ql/examples/snippets/recursion.ql b/python/ql/examples/snippets/recursion.ql index b986a265db5d..7e0770f3927c 100644 --- a/python/ql/examples/snippets/recursion.ql +++ b/python/ql/examples/snippets/recursion.ql @@ -7,6 +7,7 @@ */ import python +private import LegacyPointsTo from PythonFunctionValue f where f.getACall().getScope() = f.getScope() From 8adfde3ac4509e6b866648c24d529787ea892e59 Mon Sep 17 00:00:00 2001 From: Taus Date: Thu, 30 Oct 2025 23:06:26 +0000 Subject: [PATCH 10/19] Python: Fix query tests Mostly just adding `private import LegacyPointsTo`. Sometimes getting rid of other imports that are superceded by that module. --- python/ql/src/Classes/ClassAttributes.qll | 2 +- python/ql/src/Classes/ConflictingAttributesInBaseClasses.ql | 1 + python/ql/src/Classes/DefineEqualsWhenAddingAttributes.ql | 1 + python/ql/src/Classes/InconsistentMRO.ql | 1 + python/ql/src/Classes/MaybeUndefinedClassAttribute.ql | 1 + python/ql/src/Classes/MutatingDescriptor.ql | 1 + python/ql/src/Classes/OverwritingAttributeInSuperClass.ql | 1 + python/ql/src/Classes/PropertyInOldStyleClass.ql | 1 + python/ql/src/Classes/ShouldBeContextManager.ql | 1 + python/ql/src/Classes/SlotsInOldStyleClass.ql | 1 + python/ql/src/Classes/SuperInOldStyleClass.ql | 1 + python/ql/src/Classes/UndefinedClassAttribute.ql | 1 + python/ql/src/Classes/UselessClass.ql | 1 + .../ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql | 1 + .../ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql | 1 + python/ql/src/Exceptions/IllegalExceptionHandlerType.ql | 1 + python/ql/src/Exceptions/IllegalRaise.ql | 1 + python/ql/src/Expressions/IsComparisons.qll | 2 -- python/ql/src/Expressions/NonPortableComparisonUsingIs.ql | 1 + python/ql/src/Expressions/RedundantComparison.qll | 1 + python/ql/src/Expressions/WrongNameForArgumentInCall.ql | 1 + python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql | 1 - python/ql/src/Expressions/WrongNumberArgumentsInCall.ql | 1 + python/ql/src/Functions/DeprecatedSliceMethod.ql | 1 + python/ql/src/Functions/IncorrectlyOverriddenMethod.ql | 1 + .../ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql | 1 + python/ql/src/Functions/IterReturnsNonIterator.ql | 1 + python/ql/src/Functions/OverlyComplexDelMethod.ql | 1 + python/ql/src/Functions/ReturnValueIgnored.ql | 2 +- python/ql/src/Imports/CyclicImport.ql | 1 + python/ql/src/Imports/ModuleImportsItself.ql | 1 + python/ql/src/Imports/ModuleLevelCyclicImport.ql | 1 + python/ql/src/Imports/UnintentionalImport.ql | 1 + .../Metrics/Dependencies/ExternalDependenciesSourceLinks.ql | 1 + python/ql/src/Metrics/DirectImports.ql | 1 + python/ql/src/Metrics/TransitiveImports.ql | 1 + python/ql/src/Statements/DocStrings.ql | 1 + python/ql/src/Statements/RedundantAssignment.ql | 1 - python/ql/src/Statements/SideEffectInAssert.ql | 1 + python/ql/src/Statements/TopLevelPrint.ql | 1 + python/ql/src/Statements/UnnecessaryDelete.ql | 1 + python/ql/src/Variables/Undefined.qll | 1 + python/ql/src/Variables/UndefinedPlaceHolder.ql | 1 + python/ql/src/Variables/UnusedParameter.ql | 1 + python/ql/src/analysis/CallGraphEfficiency.ql | 3 +-- python/ql/src/analysis/CallGraphMarginalEfficiency.ql | 3 +-- python/ql/src/analysis/ContextEfficiency.ql | 3 +-- python/ql/src/analysis/ContextMarginalEfficiency.ql | 3 +-- python/ql/src/analysis/CrossProjectDefinitions.qll | 2 +- python/ql/src/analysis/FailedInference.ql | 2 +- python/ql/src/analysis/TypeHierarchyFailure.ql | 1 + python/ql/src/meta/analysis-quality/CallGraphQuality.qll | 1 + 52 files changed, 49 insertions(+), 16 deletions(-) diff --git a/python/ql/src/Classes/ClassAttributes.qll b/python/ql/src/Classes/ClassAttributes.qll index 25a026273932..4063bc7042ef 100644 --- a/python/ql/src/Classes/ClassAttributes.qll +++ b/python/ql/src/Classes/ClassAttributes.qll @@ -1,5 +1,5 @@ import python -private import semmle.python.pointsto.PointsTo +private import LegacyPointsTo /** A helper class for UndefinedClassAttribute.ql and MaybeUndefinedClassAttribute.ql */ class CheckClass extends ClassObject { diff --git a/python/ql/src/Classes/ConflictingAttributesInBaseClasses.ql b/python/ql/src/Classes/ConflictingAttributesInBaseClasses.ql index 947c547c0500..478444eadc8b 100644 --- a/python/ql/src/Classes/ConflictingAttributesInBaseClasses.ql +++ b/python/ql/src/Classes/ConflictingAttributesInBaseClasses.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo predicate does_nothing(PyFunctionObject f) { not exists(Stmt s | s.getScope() = f.getFunction() | diff --git a/python/ql/src/Classes/DefineEqualsWhenAddingAttributes.ql b/python/ql/src/Classes/DefineEqualsWhenAddingAttributes.ql index f6829b237a8e..14fa0a72647e 100644 --- a/python/ql/src/Classes/DefineEqualsWhenAddingAttributes.ql +++ b/python/ql/src/Classes/DefineEqualsWhenAddingAttributes.ql @@ -13,6 +13,7 @@ import python import Equality +private import LegacyPointsTo predicate class_stores_to_attribute(ClassValue cls, SelfAttributeStore store, string name) { exists(FunctionValue f | diff --git a/python/ql/src/Classes/InconsistentMRO.ql b/python/ql/src/Classes/InconsistentMRO.ql index b479f86ec557..aa319d56114e 100644 --- a/python/ql/src/Classes/InconsistentMRO.ql +++ b/python/ql/src/Classes/InconsistentMRO.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo ClassObject left_base(ClassObject type, ClassObject base) { exists(int i | i > 0 and type.getBaseType(i) = base and result = type.getBaseType(i - 1)) diff --git a/python/ql/src/Classes/MaybeUndefinedClassAttribute.ql b/python/ql/src/Classes/MaybeUndefinedClassAttribute.ql index 9818aaece3cd..6c4138f4f57d 100644 --- a/python/ql/src/Classes/MaybeUndefinedClassAttribute.ql +++ b/python/ql/src/Classes/MaybeUndefinedClassAttribute.ql @@ -12,6 +12,7 @@ import python import ClassAttributes +private import LegacyPointsTo predicate guarded_by_other_attribute(SelfAttributeRead a, CheckClass c) { c.sometimesDefines(a.getName()) and diff --git a/python/ql/src/Classes/MutatingDescriptor.ql b/python/ql/src/Classes/MutatingDescriptor.ql index aad468f8e3c3..c69f8868fd2b 100644 --- a/python/ql/src/Classes/MutatingDescriptor.ql +++ b/python/ql/src/Classes/MutatingDescriptor.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo predicate mutates_descriptor(ClassObject cls, SelfAttributeStore s) { cls.isDescriptorType() and diff --git a/python/ql/src/Classes/OverwritingAttributeInSuperClass.ql b/python/ql/src/Classes/OverwritingAttributeInSuperClass.ql index 699e4387a144..89d33d548146 100644 --- a/python/ql/src/Classes/OverwritingAttributeInSuperClass.ql +++ b/python/ql/src/Classes/OverwritingAttributeInSuperClass.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo class InitCallStmt extends ExprStmt { InitCallStmt() { diff --git a/python/ql/src/Classes/PropertyInOldStyleClass.ql b/python/ql/src/Classes/PropertyInOldStyleClass.ql index 6e1b9a063c04..2fd7b1d14cf2 100644 --- a/python/ql/src/Classes/PropertyInOldStyleClass.ql +++ b/python/ql/src/Classes/PropertyInOldStyleClass.ql @@ -11,6 +11,7 @@ */ import python +private import LegacyPointsTo from PropertyObject prop, ClassObject cls where cls.declaredAttribute(_) = prop and not cls.failedInference() and not cls.isNewStyle() diff --git a/python/ql/src/Classes/ShouldBeContextManager.ql b/python/ql/src/Classes/ShouldBeContextManager.ql index 2423206e3cfc..6aec0f0e0ab0 100644 --- a/python/ql/src/Classes/ShouldBeContextManager.ql +++ b/python/ql/src/Classes/ShouldBeContextManager.ql @@ -14,6 +14,7 @@ */ import python +private import LegacyPointsTo from ClassValue c where not c.isBuiltin() and not c.isContextManager() and exists(c.declaredAttribute("__del__")) diff --git a/python/ql/src/Classes/SlotsInOldStyleClass.ql b/python/ql/src/Classes/SlotsInOldStyleClass.ql index bb229edc8d31..2f91a88cf64e 100644 --- a/python/ql/src/Classes/SlotsInOldStyleClass.ql +++ b/python/ql/src/Classes/SlotsInOldStyleClass.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo from ClassObject c where not c.isNewStyle() and c.declaresAttribute("__slots__") and not c.failedInference() diff --git a/python/ql/src/Classes/SuperInOldStyleClass.ql b/python/ql/src/Classes/SuperInOldStyleClass.ql index deba0889449e..a6a272b1b3b7 100644 --- a/python/ql/src/Classes/SuperInOldStyleClass.ql +++ b/python/ql/src/Classes/SuperInOldStyleClass.ql @@ -11,6 +11,7 @@ */ import python +private import LegacyPointsTo predicate uses_of_super_in_old_style_class(Call s) { exists(Function f, ClassObject c | diff --git a/python/ql/src/Classes/UndefinedClassAttribute.ql b/python/ql/src/Classes/UndefinedClassAttribute.ql index 748c46818208..38dcb9b4a7d7 100644 --- a/python/ql/src/Classes/UndefinedClassAttribute.ql +++ b/python/ql/src/Classes/UndefinedClassAttribute.ql @@ -12,6 +12,7 @@ import python import ClassAttributes +private import LegacyPointsTo predicate undefined_class_attribute(SelfAttributeRead a, CheckClass c, int line, string name) { name = a.getName() and diff --git a/python/ql/src/Classes/UselessClass.ql b/python/ql/src/Classes/UselessClass.ql index 7e33660dafc4..740c74bf96d9 100644 --- a/python/ql/src/Classes/UselessClass.ql +++ b/python/ql/src/Classes/UselessClass.ql @@ -13,6 +13,7 @@ */ import python +private import LegacyPointsTo predicate fewer_than_two_public_methods(Class cls, int methods) { (methods = 0 or methods = 1) and diff --git a/python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql b/python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql index 1de99ebdbf61..5b50855dcdf7 100644 --- a/python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql +++ b/python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql @@ -16,6 +16,7 @@ import python import Expressions.CallArgs +private import LegacyPointsTo from Call call, ClassValue cls, string name, FunctionValue init where diff --git a/python/ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql b/python/ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql index 8518905f3a90..263a1a336a1a 100644 --- a/python/ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql +++ b/python/ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql @@ -15,6 +15,7 @@ import python import Expressions.CallArgs +private import LegacyPointsTo from Call call, ClassValue cls, string too, string should, int limit, FunctionValue init where diff --git a/python/ql/src/Exceptions/IllegalExceptionHandlerType.ql b/python/ql/src/Exceptions/IllegalExceptionHandlerType.ql index 2bf97b469ee0..b5446dccbfc9 100644 --- a/python/ql/src/Exceptions/IllegalExceptionHandlerType.ql +++ b/python/ql/src/Exceptions/IllegalExceptionHandlerType.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo from ExceptFlowNode ex, Value t, ClassValue c, ControlFlowNode origin, string what where diff --git a/python/ql/src/Exceptions/IllegalRaise.ql b/python/ql/src/Exceptions/IllegalRaise.ql index 04319e246ed1..f9f263552b18 100644 --- a/python/ql/src/Exceptions/IllegalRaise.ql +++ b/python/ql/src/Exceptions/IllegalRaise.ql @@ -14,6 +14,7 @@ import python import Raising import Exceptions.NotImplemented +private import LegacyPointsTo from Raise r, ClassValue t where diff --git a/python/ql/src/Expressions/IsComparisons.qll b/python/ql/src/Expressions/IsComparisons.qll index 052407f7111b..cb052ceca765 100644 --- a/python/ql/src/Expressions/IsComparisons.qll +++ b/python/ql/src/Expressions/IsComparisons.qll @@ -2,8 +2,6 @@ import python private import LegacyPointsTo -private import semmle.python.objects.ObjectInternal -private import semmle.python.objects.ObjectAPI /** Holds if the comparison `comp` uses `is` or `is not` (represented as `op`) to compare its `left` and `right` arguments. */ predicate comparison_using_is(Compare comp, ControlFlowNode left, Cmpop op, ControlFlowNode right) { diff --git a/python/ql/src/Expressions/NonPortableComparisonUsingIs.ql b/python/ql/src/Expressions/NonPortableComparisonUsingIs.ql index 894cc78c8f44..d705bea07658 100644 --- a/python/ql/src/Expressions/NonPortableComparisonUsingIs.ql +++ b/python/ql/src/Expressions/NonPortableComparisonUsingIs.ql @@ -13,6 +13,7 @@ import python import IsComparisons +private import LegacyPointsTo from Compare comp, Cmpop op, ClassValue c where diff --git a/python/ql/src/Expressions/RedundantComparison.qll b/python/ql/src/Expressions/RedundantComparison.qll index a0d4f906501a..dc40a89c784f 100644 --- a/python/ql/src/Expressions/RedundantComparison.qll +++ b/python/ql/src/Expressions/RedundantComparison.qll @@ -1,6 +1,7 @@ /** Helper functions for queries that test redundant comparisons. */ import python +private import LegacyPointsTo /** A comparison where the left and right hand sides appear to be identical. */ class RedundantComparison extends Compare { diff --git a/python/ql/src/Expressions/WrongNameForArgumentInCall.ql b/python/ql/src/Expressions/WrongNameForArgumentInCall.ql index 21403c51c610..f267df13e19a 100644 --- a/python/ql/src/Expressions/WrongNameForArgumentInCall.ql +++ b/python/ql/src/Expressions/WrongNameForArgumentInCall.ql @@ -16,6 +16,7 @@ import python import Expressions.CallArgs +private import LegacyPointsTo from Call call, FunctionObject func, string name where diff --git a/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql b/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql index d7b27e5c3d75..cf741d4cf64e 100644 --- a/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql +++ b/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql @@ -15,7 +15,6 @@ import python import LegacyPointsTo -import semmle.python.objects.ObjectInternal import semmle.python.strings predicate string_format(BinaryExpr operation, StringLiteral str, Value args, AstNode origin) { diff --git a/python/ql/src/Expressions/WrongNumberArgumentsInCall.ql b/python/ql/src/Expressions/WrongNumberArgumentsInCall.ql index bde54558c9bd..35d9341fb050 100644 --- a/python/ql/src/Expressions/WrongNumberArgumentsInCall.ql +++ b/python/ql/src/Expressions/WrongNumberArgumentsInCall.ql @@ -13,6 +13,7 @@ */ import python +private import LegacyPointsTo import CallArgs from Call call, FunctionValue func, string too, string should, int limit diff --git a/python/ql/src/Functions/DeprecatedSliceMethod.ql b/python/ql/src/Functions/DeprecatedSliceMethod.ql index af596f704cd9..3e9cdb681d9a 100644 --- a/python/ql/src/Functions/DeprecatedSliceMethod.ql +++ b/python/ql/src/Functions/DeprecatedSliceMethod.ql @@ -10,6 +10,7 @@ */ import python +private import LegacyPointsTo predicate slice_method_name(string name) { name = "__getslice__" or name = "__setslice__" or name = "__delslice__" diff --git a/python/ql/src/Functions/IncorrectlyOverriddenMethod.ql b/python/ql/src/Functions/IncorrectlyOverriddenMethod.ql index a4e3bd6e0ce4..0a640d462397 100644 --- a/python/ql/src/Functions/IncorrectlyOverriddenMethod.ql +++ b/python/ql/src/Functions/IncorrectlyOverriddenMethod.ql @@ -14,6 +14,7 @@ import python import Expressions.CallArgs +private import LegacyPointsTo from Call call, FunctionValue func, FunctionValue overridden, string problem where diff --git a/python/ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql b/python/ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql index 6b31795d94ea..18cbddaff318 100644 --- a/python/ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql +++ b/python/ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql @@ -14,6 +14,7 @@ import python import Expressions.CallArgs +private import LegacyPointsTo from Call call, FunctionValue func, FunctionValue overriding, string problem where diff --git a/python/ql/src/Functions/IterReturnsNonIterator.ql b/python/ql/src/Functions/IterReturnsNonIterator.ql index 367332cf49a7..082347263147 100644 --- a/python/ql/src/Functions/IterReturnsNonIterator.ql +++ b/python/ql/src/Functions/IterReturnsNonIterator.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo from ClassValue iterable, FunctionValue iter, ClassValue iterator where diff --git a/python/ql/src/Functions/OverlyComplexDelMethod.ql b/python/ql/src/Functions/OverlyComplexDelMethod.ql index b93dc4af3c34..d9fa3e750e65 100644 --- a/python/ql/src/Functions/OverlyComplexDelMethod.ql +++ b/python/ql/src/Functions/OverlyComplexDelMethod.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo from FunctionValue method where diff --git a/python/ql/src/Functions/ReturnValueIgnored.ql b/python/ql/src/Functions/ReturnValueIgnored.ql index d8f81534b8ad..3716b989d891 100644 --- a/python/ql/src/Functions/ReturnValueIgnored.ql +++ b/python/ql/src/Functions/ReturnValueIgnored.ql @@ -14,7 +14,7 @@ */ import python -import semmle.python.objects.Callables +private import LegacyPointsTo predicate meaningful_return_value(Expr val) { val instanceof Name diff --git a/python/ql/src/Imports/CyclicImport.ql b/python/ql/src/Imports/CyclicImport.ql index 9e4a153a110d..464d906db980 100644 --- a/python/ql/src/Imports/CyclicImport.ql +++ b/python/ql/src/Imports/CyclicImport.ql @@ -13,6 +13,7 @@ import python import Cyclic +private import LegacyPointsTo from ModuleValue m1, ModuleValue m2, Stmt imp where diff --git a/python/ql/src/Imports/ModuleImportsItself.ql b/python/ql/src/Imports/ModuleImportsItself.ql index 72d223da3dbb..97fb68791d1a 100644 --- a/python/ql/src/Imports/ModuleImportsItself.ql +++ b/python/ql/src/Imports/ModuleImportsItself.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo predicate modules_imports_itself(ImportingStmt i, ModuleValue m) { i.getEnclosingModule() = m.getScope() and diff --git a/python/ql/src/Imports/ModuleLevelCyclicImport.ql b/python/ql/src/Imports/ModuleLevelCyclicImport.ql index 7d9b0cc31c74..7910cb76823e 100644 --- a/python/ql/src/Imports/ModuleLevelCyclicImport.ql +++ b/python/ql/src/Imports/ModuleLevelCyclicImport.ql @@ -14,6 +14,7 @@ import python import Cyclic +private import LegacyPointsTo // This is a potentially crashing bug if // 1. the imports in the whole cycle are lexically outside a def (and so executed at import time) diff --git a/python/ql/src/Imports/UnintentionalImport.ql b/python/ql/src/Imports/UnintentionalImport.ql index 1faf3bb55f3d..7b22865cd89e 100644 --- a/python/ql/src/Imports/UnintentionalImport.ql +++ b/python/ql/src/Imports/UnintentionalImport.ql @@ -13,6 +13,7 @@ */ import python +private import LegacyPointsTo predicate import_star(ImportStar imp, ModuleValue exporter) { exporter.importedAs(imp.getImportedModuleName()) diff --git a/python/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql b/python/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql index 98bb4e63cc37..60dbcdcc7fcb 100644 --- a/python/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql +++ b/python/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql @@ -8,6 +8,7 @@ import python import semmle.python.dependencies.TechInventory +private import LegacyPointsTo /* * This query creates the source links for the ExternalDependencies.ql query. diff --git a/python/ql/src/Metrics/DirectImports.ql b/python/ql/src/Metrics/DirectImports.ql index 240cd65e687d..e383d4b36572 100644 --- a/python/ql/src/Metrics/DirectImports.ql +++ b/python/ql/src/Metrics/DirectImports.ql @@ -11,6 +11,7 @@ */ import python +private import LegacyPointsTo from ModuleValue m, int n where n = count(ModuleValue imp | imp = m.getAnImportedModule()) diff --git a/python/ql/src/Metrics/TransitiveImports.ql b/python/ql/src/Metrics/TransitiveImports.ql index a46a7a163029..364840fbcb9e 100644 --- a/python/ql/src/Metrics/TransitiveImports.ql +++ b/python/ql/src/Metrics/TransitiveImports.ql @@ -11,6 +11,7 @@ */ import python +private import LegacyPointsTo from ModuleValue m, int n where n = count(ModuleValue imp | imp = m.getAnImportedModule+() and imp != m) diff --git a/python/ql/src/Statements/DocStrings.ql b/python/ql/src/Statements/DocStrings.ql index 903207f7ccb7..d7df570a7ef4 100644 --- a/python/ql/src/Statements/DocStrings.ql +++ b/python/ql/src/Statements/DocStrings.ql @@ -17,6 +17,7 @@ */ import python +private import LegacyPointsTo predicate needs_docstring(Scope s) { s.isPublic() and diff --git a/python/ql/src/Statements/RedundantAssignment.ql b/python/ql/src/Statements/RedundantAssignment.ql index e3f58995fa14..357364c41b2f 100644 --- a/python/ql/src/Statements/RedundantAssignment.ql +++ b/python/ql/src/Statements/RedundantAssignment.ql @@ -14,7 +14,6 @@ import python private import LegacyPointsTo -private import semmle.python.objects.ObjectAPI predicate assignment(AssignStmt a, Expr left, Expr right) { a.getATarget() = left and a.getValue() = right diff --git a/python/ql/src/Statements/SideEffectInAssert.ql b/python/ql/src/Statements/SideEffectInAssert.ql index 92cb95d702bf..902b6c4c9c16 100644 --- a/python/ql/src/Statements/SideEffectInAssert.ql +++ b/python/ql/src/Statements/SideEffectInAssert.ql @@ -13,6 +13,7 @@ */ import python +private import LegacyPointsTo predicate func_with_side_effects(Expr e) { exists(string name | name = e.(Attribute).getName() or name = e.(Name).getId() | diff --git a/python/ql/src/Statements/TopLevelPrint.ql b/python/ql/src/Statements/TopLevelPrint.ql index 2d481421b7e8..12095f7a484d 100644 --- a/python/ql/src/Statements/TopLevelPrint.ql +++ b/python/ql/src/Statements/TopLevelPrint.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo predicate main_eq_name(If i) { exists(Name n, StringLiteral m, Compare c | diff --git a/python/ql/src/Statements/UnnecessaryDelete.ql b/python/ql/src/Statements/UnnecessaryDelete.ql index 808a3f3a0d3d..c7b80ecc66ac 100644 --- a/python/ql/src/Statements/UnnecessaryDelete.ql +++ b/python/ql/src/Statements/UnnecessaryDelete.ql @@ -13,6 +13,7 @@ */ import python +private import LegacyPointsTo predicate isInsideLoop(AstNode node) { node.getParentNode() instanceof While diff --git a/python/ql/src/Variables/Undefined.qll b/python/ql/src/Variables/Undefined.qll index 58deee4dc59f..42437a81340b 100644 --- a/python/ql/src/Variables/Undefined.qll +++ b/python/ql/src/Variables/Undefined.qll @@ -1,6 +1,7 @@ import python import Loop import semmle.python.dataflow.TaintTracking +private import LegacyPointsTo /** A marker for "uninitialized". */ class Uninitialized extends TaintKind { diff --git a/python/ql/src/Variables/UndefinedPlaceHolder.ql b/python/ql/src/Variables/UndefinedPlaceHolder.ql index b0eeeda871ac..11bf3b6d0bec 100644 --- a/python/ql/src/Variables/UndefinedPlaceHolder.ql +++ b/python/ql/src/Variables/UndefinedPlaceHolder.ql @@ -13,6 +13,7 @@ import python import Variables.MonkeyPatched +private import LegacyPointsTo /* Local variable part */ predicate initialized_as_local(PlaceHolder use) { diff --git a/python/ql/src/Variables/UnusedParameter.ql b/python/ql/src/Variables/UnusedParameter.ql index 7228974b7c73..1efb984fd0bb 100644 --- a/python/ql/src/Variables/UnusedParameter.ql +++ b/python/ql/src/Variables/UnusedParameter.ql @@ -14,6 +14,7 @@ import python import Definition +private import LegacyPointsTo predicate unused_parameter(FunctionValue f, LocalVariable v) { v.isParameter() and diff --git a/python/ql/src/analysis/CallGraphEfficiency.ql b/python/ql/src/analysis/CallGraphEfficiency.ql index 5e36823b8ac7..3990b68ecc69 100644 --- a/python/ql/src/analysis/CallGraphEfficiency.ql +++ b/python/ql/src/analysis/CallGraphEfficiency.ql @@ -4,8 +4,7 @@ */ import python -import semmle.python.pointsto.PointsTo -import semmle.python.pointsto.PointsToContext +private import LegacyPointsTo from int total_facts, int total_size, int depth, float efficiency where diff --git a/python/ql/src/analysis/CallGraphMarginalEfficiency.ql b/python/ql/src/analysis/CallGraphMarginalEfficiency.ql index 394bf379eeb0..f2e931c411c4 100644 --- a/python/ql/src/analysis/CallGraphMarginalEfficiency.ql +++ b/python/ql/src/analysis/CallGraphMarginalEfficiency.ql @@ -4,8 +4,7 @@ */ import python -import semmle.python.pointsto.PointsTo -import semmle.python.pointsto.PointsToContext +private import LegacyPointsTo from int total_facts, int total_size, int depth, float efficiency where diff --git a/python/ql/src/analysis/ContextEfficiency.ql b/python/ql/src/analysis/ContextEfficiency.ql index 205091ba1e32..76ca78fc867c 100644 --- a/python/ql/src/analysis/ContextEfficiency.ql +++ b/python/ql/src/analysis/ContextEfficiency.ql @@ -4,8 +4,7 @@ */ import python -import semmle.python.pointsto.PointsTo -import semmle.python.pointsto.PointsToContext +private import LegacyPointsTo from int total_facts, int total_size, int depth, float efficiency where diff --git a/python/ql/src/analysis/ContextMarginalEfficiency.ql b/python/ql/src/analysis/ContextMarginalEfficiency.ql index 755ccad683c6..c87de8c6ebe5 100644 --- a/python/ql/src/analysis/ContextMarginalEfficiency.ql +++ b/python/ql/src/analysis/ContextMarginalEfficiency.ql @@ -4,8 +4,7 @@ */ import python -import semmle.python.pointsto.PointsTo -import semmle.python.pointsto.PointsToContext +private import LegacyPointsTo int depth(ControlFlowNode f, Object value, ClassObject cls) { exists(PointsToContext ctx | diff --git a/python/ql/src/analysis/CrossProjectDefinitions.qll b/python/ql/src/analysis/CrossProjectDefinitions.qll index 84fd8215712a..64b30f566f15 100644 --- a/python/ql/src/analysis/CrossProjectDefinitions.qll +++ b/python/ql/src/analysis/CrossProjectDefinitions.qll @@ -3,7 +3,7 @@ */ import python -import semmle.python.pointsto.PointsTo +private import LegacyPointsTo private newtype TSymbol = TModule(Module m) or diff --git a/python/ql/src/analysis/FailedInference.ql b/python/ql/src/analysis/FailedInference.ql index 192cf696fbf1..feae8fdc5ee2 100644 --- a/python/ql/src/analysis/FailedInference.ql +++ b/python/ql/src/analysis/FailedInference.ql @@ -1,5 +1,5 @@ import python -import semmle.python.pointsto.PointsTo +private import LegacyPointsTo from ClassValue cls, string reason where Types::failedInference(cls, reason) diff --git a/python/ql/src/analysis/TypeHierarchyFailure.ql b/python/ql/src/analysis/TypeHierarchyFailure.ql index c4c910057436..c6ad4be98226 100644 --- a/python/ql/src/analysis/TypeHierarchyFailure.ql +++ b/python/ql/src/analysis/TypeHierarchyFailure.ql @@ -8,6 +8,7 @@ */ import python +private import LegacyPointsTo from Class cls, string reason where exists(ClassObject c | c.getPyClass() = cls | c.failedInference(reason)) diff --git a/python/ql/src/meta/analysis-quality/CallGraphQuality.qll b/python/ql/src/meta/analysis-quality/CallGraphQuality.qll index a8e7a3b340ae..679b39ddc8d4 100644 --- a/python/ql/src/meta/analysis-quality/CallGraphQuality.qll +++ b/python/ql/src/meta/analysis-quality/CallGraphQuality.qll @@ -5,6 +5,7 @@ import python import meta.MetaMetrics +private import LegacyPointsTo newtype TTarget = TFunction(Function func) or From 8af57dbed78ec6e8c3f979c0650d8ebf91390879 Mon Sep 17 00:00:00 2001 From: Taus Date: Thu, 30 Oct 2025 23:07:25 +0000 Subject: [PATCH 11/19] Python: Fix Python 2 tests --- python/ql/test/2/extractor-tests/import_depth/test.ql | 1 + python/ql/test/2/extractor-tests/object_hash/Success.ql | 1 + .../ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql | 1 + python/ql/test/2/library-tests/ControlFlow/Exceptions/Known.ql | 1 + .../ql/test/2/library-tests/ControlFlow/Exceptions/Likely.ql | 1 + .../ql/test/2/library-tests/ControlFlow/Exceptions/Unknown.ql | 1 + python/ql/test/2/library-tests/PointsTo/import_time/Pruned.ql | 3 +-- python/ql/test/2/library-tests/PointsTo/metaclass/test.ql | 1 + python/ql/test/2/library-tests/classes/attr/class_attr.ql | 1 + python/ql/test/2/library-tests/classes/attr/class_has_attr.ql | 1 + python/ql/test/2/library-tests/classes/attr/list_attr.ql | 1 + python/ql/test/2/library-tests/classes/mro/mro.ql | 1 + .../test/2/library-tests/modules/general/moduleobject_test.ql | 1 + .../library-tests/modules/package_members/module_attributes.ql | 1 + .../2/library-tests/modules/package_members/module_exports.ql | 1 + .../library-tests/modules/package_members/module_import_as.ql | 1 + python/ql/test/2/library-tests/modules/usage/ModuleUsage.ql | 1 + python/ql/test/2/library-tests/types/classes/mro_test.ql | 1 + python/ql/test/2/library-tests/types/classes/new_style.ql | 1 + python/ql/test/2/library-tests/types/exceptions/ExitRaises.ql | 1 + python/ql/test/2/library-tests/types/exceptions/Raises.ql | 1 + python/ql/test/2/library-tests/types/functions/Calls.ql | 1 + python/ql/test/2/library-tests/types/functions/Never.ql | 1 + python/ql/test/2/library-tests/types/functions/ReturnTypes.ql | 1 + .../test/2/library-tests/types/properties/BuiltinProperties.ql | 1 + 25 files changed, 25 insertions(+), 2 deletions(-) diff --git a/python/ql/test/2/extractor-tests/import_depth/test.ql b/python/ql/test/2/extractor-tests/import_depth/test.ql index ef626455fad9..4f007e99468e 100644 --- a/python/ql/test/2/extractor-tests/import_depth/test.ql +++ b/python/ql/test/2/extractor-tests/import_depth/test.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ModuleObject m /* Exclude the builtins module as it has a different name under 2 and 3. */ diff --git a/python/ql/test/2/extractor-tests/object_hash/Success.ql b/python/ql/test/2/extractor-tests/object_hash/Success.ql index 9cff9ee4b73a..55e38e56b934 100644 --- a/python/ql/test/2/extractor-tests/object_hash/Success.ql +++ b/python/ql/test/2/extractor-tests/object_hash/Success.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo where exists(theSysModuleObject()) select 1 diff --git a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql index 620944de5b90..60989ff86452 100644 --- a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql +++ b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ExceptFlowNode ex, Value val where ex.handledException(val, _, _) diff --git a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Known.ql b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Known.ql index 56498054f51a..b773a172ee3d 100644 --- a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Known.ql +++ b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Known.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from RaisingNode r select r.getLocation().getStartLine(), r.toString(), r.getARaisedType().toString() diff --git a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Likely.ql b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Likely.ql index f8e4a4b7dacd..00cf5a7d2afc 100644 --- a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Likely.ql +++ b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Likely.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ControlFlowNode r, ControlFlowNode s where diff --git a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Unknown.ql b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Unknown.ql index 29bad86bf0f7..fe0fa6b01586 100644 --- a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Unknown.ql +++ b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Unknown.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from RaisingNode r where r.raisesUnknownType() diff --git a/python/ql/test/2/library-tests/PointsTo/import_time/Pruned.ql b/python/ql/test/2/library-tests/PointsTo/import_time/Pruned.ql index e77849860c7c..ba8df441caf4 100644 --- a/python/ql/test/2/library-tests/PointsTo/import_time/Pruned.ql +++ b/python/ql/test/2/library-tests/PointsTo/import_time/Pruned.ql @@ -1,6 +1,5 @@ import python -import semmle.python.pointsto.PointsTo -import semmle.python.pointsto.PointsToContext +private import LegacyPointsTo from ControlFlowNode f, Location l, Context c where diff --git a/python/ql/test/2/library-tests/PointsTo/metaclass/test.ql b/python/ql/test/2/library-tests/PointsTo/metaclass/test.ql index 68eec976105c..0644e4cdf74a 100644 --- a/python/ql/test/2/library-tests/PointsTo/metaclass/test.ql +++ b/python/ql/test/2/library-tests/PointsTo/metaclass/test.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls where not cls.isC() diff --git a/python/ql/test/2/library-tests/classes/attr/class_attr.ql b/python/ql/test/2/library-tests/classes/attr/class_attr.ql index 197ab1a1e5eb..1c9c5513a1d7 100644 --- a/python/ql/test/2/library-tests/classes/attr/class_attr.ql +++ b/python/ql/test/2/library-tests/classes/attr/class_attr.ql @@ -5,6 +5,7 @@ */ import python +private import LegacyPointsTo from ClassObject cls, int line, string name, Object obj where diff --git a/python/ql/test/2/library-tests/classes/attr/class_has_attr.ql b/python/ql/test/2/library-tests/classes/attr/class_has_attr.ql index be8272d1bd6b..24724f4d8593 100644 --- a/python/ql/test/2/library-tests/classes/attr/class_has_attr.ql +++ b/python/ql/test/2/library-tests/classes/attr/class_has_attr.ql @@ -5,6 +5,7 @@ */ import python +private import LegacyPointsTo from ClassObject cls, int line, string name where diff --git a/python/ql/test/2/library-tests/classes/attr/list_attr.ql b/python/ql/test/2/library-tests/classes/attr/list_attr.ql index c38694d58835..ad708711df47 100644 --- a/python/ql/test/2/library-tests/classes/attr/list_attr.ql +++ b/python/ql/test/2/library-tests/classes/attr/list_attr.ql @@ -5,6 +5,7 @@ */ import python +private import LegacyPointsTo from ClassObject cls, string name, Object what where diff --git a/python/ql/test/2/library-tests/classes/mro/mro.ql b/python/ql/test/2/library-tests/classes/mro/mro.ql index 0c4cf077adba..6a4d21921a1e 100644 --- a/python/ql/test/2/library-tests/classes/mro/mro.ql +++ b/python/ql/test/2/library-tests/classes/mro/mro.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls, ClassObject l, ClassObject r where diff --git a/python/ql/test/2/library-tests/modules/general/moduleobject_test.ql b/python/ql/test/2/library-tests/modules/general/moduleobject_test.ql index 50f79a57aedb..27394e03096c 100644 --- a/python/ql/test/2/library-tests/modules/general/moduleobject_test.ql +++ b/python/ql/test/2/library-tests/modules/general/moduleobject_test.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ModuleObject m, string name where m.getName() = "package" or m.getName() = "confused_elements" diff --git a/python/ql/test/2/library-tests/modules/package_members/module_attributes.ql b/python/ql/test/2/library-tests/modules/package_members/module_attributes.ql index 6c16450f3134..f7755b92e12a 100644 --- a/python/ql/test/2/library-tests/modules/package_members/module_attributes.ql +++ b/python/ql/test/2/library-tests/modules/package_members/module_attributes.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ModuleObject m, string name where not m.isC() diff --git a/python/ql/test/2/library-tests/modules/package_members/module_exports.ql b/python/ql/test/2/library-tests/modules/package_members/module_exports.ql index bcfc0c60bfb7..d04ef3bc9f31 100644 --- a/python/ql/test/2/library-tests/modules/package_members/module_exports.ql +++ b/python/ql/test/2/library-tests/modules/package_members/module_exports.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ModuleObject m, string name where not m.isC() and m.exports(name) diff --git a/python/ql/test/2/library-tests/modules/package_members/module_import_as.ql b/python/ql/test/2/library-tests/modules/package_members/module_import_as.ql index 50ded7b41244..97cc2e866652 100644 --- a/python/ql/test/2/library-tests/modules/package_members/module_import_as.ql +++ b/python/ql/test/2/library-tests/modules/package_members/module_import_as.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ModuleObject m, string name where not m.isC() and m.importedAs(name) diff --git a/python/ql/test/2/library-tests/modules/usage/ModuleUsage.ql b/python/ql/test/2/library-tests/modules/usage/ModuleUsage.ql index 5f776e2374e6..0469f804ab33 100644 --- a/python/ql/test/2/library-tests/modules/usage/ModuleUsage.ql +++ b/python/ql/test/2/library-tests/modules/usage/ModuleUsage.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ModuleValue mv, string usage where diff --git a/python/ql/test/2/library-tests/types/classes/mro_test.ql b/python/ql/test/2/library-tests/types/classes/mro_test.ql index fa2ac44d4d2a..8d68b5b08fe0 100644 --- a/python/ql/test/2/library-tests/types/classes/mro_test.ql +++ b/python/ql/test/2/library-tests/types/classes/mro_test.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls where not cls.isC() diff --git a/python/ql/test/2/library-tests/types/classes/new_style.ql b/python/ql/test/2/library-tests/types/classes/new_style.ql index 2af405653292..fdd8fac80a83 100644 --- a/python/ql/test/2/library-tests/types/classes/new_style.ql +++ b/python/ql/test/2/library-tests/types/classes/new_style.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls, string style where diff --git a/python/ql/test/2/library-tests/types/exceptions/ExitRaises.ql b/python/ql/test/2/library-tests/types/exceptions/ExitRaises.ql index 415db290a05d..5bf1ae1da00b 100644 --- a/python/ql/test/2/library-tests/types/exceptions/ExitRaises.ql +++ b/python/ql/test/2/library-tests/types/exceptions/ExitRaises.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from RaisingNode r, Scope s, ClassObject cls where r.viableExceptionalExit_objectapi(s, cls) diff --git a/python/ql/test/2/library-tests/types/exceptions/Raises.ql b/python/ql/test/2/library-tests/types/exceptions/Raises.ql index 2415c7079670..e4f9a6664d55 100644 --- a/python/ql/test/2/library-tests/types/exceptions/Raises.ql +++ b/python/ql/test/2/library-tests/types/exceptions/Raises.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from PyFunctionObject f, string type where diff --git a/python/ql/test/2/library-tests/types/functions/Calls.ql b/python/ql/test/2/library-tests/types/functions/Calls.ql index 6fc188753e55..5eaeb4559b0c 100644 --- a/python/ql/test/2/library-tests/types/functions/Calls.ql +++ b/python/ql/test/2/library-tests/types/functions/Calls.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from FunctionObject func, ControlFlowNode call where func.getACall() = call diff --git a/python/ql/test/2/library-tests/types/functions/Never.ql b/python/ql/test/2/library-tests/types/functions/Never.ql index 1e43ead7dce7..932121d058ea 100644 --- a/python/ql/test/2/library-tests/types/functions/Never.ql +++ b/python/ql/test/2/library-tests/types/functions/Never.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from FunctionObject func where func.neverReturns() diff --git a/python/ql/test/2/library-tests/types/functions/ReturnTypes.ql b/python/ql/test/2/library-tests/types/functions/ReturnTypes.ql index beb955e11881..d35deea34bfe 100644 --- a/python/ql/test/2/library-tests/types/functions/ReturnTypes.ql +++ b/python/ql/test/2/library-tests/types/functions/ReturnTypes.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from PyFunctionObject func, ClassObject ret_type where func.getAnInferredReturnType() = ret_type diff --git a/python/ql/test/2/library-tests/types/properties/BuiltinProperties.ql b/python/ql/test/2/library-tests/types/properties/BuiltinProperties.ql index 24766db9f2eb..9ab0b5e4bbdc 100644 --- a/python/ql/test/2/library-tests/types/properties/BuiltinProperties.ql +++ b/python/ql/test/2/library-tests/types/properties/BuiltinProperties.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls, string name, BuiltinPropertyObject p where From 102070071cd00b0725552e28dff23405e58f7b81 Mon Sep 17 00:00:00 2001 From: Taus Date: Thu, 30 Oct 2025 23:08:11 +0000 Subject: [PATCH 12/19] Python: Fix Python 3 tests --- python/ql/test/3/extractor-tests/import_depth/test.ql | 1 + .../ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql | 1 + python/ql/test/3/library-tests/ControlFlow/Exceptions/Known.ql | 1 + python/ql/test/3/library-tests/ControlFlow/Exceptions/Likely.ql | 1 + .../ql/test/3/library-tests/ControlFlow/Exceptions/Unknown.ql | 1 + .../ql/test/3/library-tests/PointsTo/consts/BooleanConstants.ql | 2 +- python/ql/test/3/library-tests/PointsTo/inheritance/Calls.ql | 1 + python/ql/test/3/library-tests/PointsTo/metaclass/test.ql | 1 + .../PointsTo/regressions/subprocess-assert/ClassValue.ql | 1 + python/ql/test/3/library-tests/classes/attr/class_attr.ql | 1 + python/ql/test/3/library-tests/classes/attr/class_has_attr.ql | 1 + python/ql/test/3/library-tests/classes/meta/meta_obj.ql | 1 + python/ql/test/3/library-tests/classes/mro/mro.ql | 1 + python/ql/test/3/library-tests/classes/mro/mro_index.ql | 1 + .../test/3/library-tests/modules/general/moduleobject_test.ql | 1 + .../library-tests/modules/package_members/module_attributes.ql | 1 + .../3/library-tests/modules/package_members/module_exports.ql | 1 + .../3/library-tests/modules/package_members/module_import_as.ql | 1 + python/ql/test/3/library-tests/modules/usage/ModuleUsage.ql | 1 + python/ql/test/3/library-tests/types/classes/mro_test.ql | 1 + python/ql/test/3/library-tests/types/exceptions/Raises.ql | 1 + python/ql/test/3/library-tests/types/exceptions/Viable.ql | 1 + python/ql/test/3/library-tests/types/functions/Calls.ql | 1 + python/ql/test/3/library-tests/types/functions/Never.ql | 1 + python/ql/test/3/library-tests/types/functions/ReturnTypes.ql | 1 + python/ql/test/3/library-tests/types/namespaces/NameSpace.ql | 1 + .../test/3/library-tests/types/properties/BuiltinProperties.ql | 1 + 27 files changed, 27 insertions(+), 1 deletion(-) diff --git a/python/ql/test/3/extractor-tests/import_depth/test.ql b/python/ql/test/3/extractor-tests/import_depth/test.ql index ef626455fad9..4f007e99468e 100644 --- a/python/ql/test/3/extractor-tests/import_depth/test.ql +++ b/python/ql/test/3/extractor-tests/import_depth/test.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ModuleObject m /* Exclude the builtins module as it has a different name under 2 and 3. */ diff --git a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql index 620944de5b90..60989ff86452 100644 --- a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql +++ b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ExceptFlowNode ex, Value val where ex.handledException(val, _, _) diff --git a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Known.ql b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Known.ql index 56498054f51a..b773a172ee3d 100644 --- a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Known.ql +++ b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Known.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from RaisingNode r select r.getLocation().getStartLine(), r.toString(), r.getARaisedType().toString() diff --git a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Likely.ql b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Likely.ql index f8e4a4b7dacd..00cf5a7d2afc 100644 --- a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Likely.ql +++ b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Likely.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ControlFlowNode r, ControlFlowNode s where diff --git a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Unknown.ql b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Unknown.ql index 29bad86bf0f7..fe0fa6b01586 100644 --- a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Unknown.ql +++ b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Unknown.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from RaisingNode r where r.raisesUnknownType() diff --git a/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.ql b/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.ql index 4299e11d660f..242fb5bc781e 100644 --- a/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.ql +++ b/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.ql @@ -1,5 +1,5 @@ import python -import semmle.python.pointsto.PointsTo +private import LegacyPointsTo from ControlFlowNode f, Context c, boolean b where diff --git a/python/ql/test/3/library-tests/PointsTo/inheritance/Calls.ql b/python/ql/test/3/library-tests/PointsTo/inheritance/Calls.ql index f91d207fc708..3f111d6e08a8 100644 --- a/python/ql/test/3/library-tests/PointsTo/inheritance/Calls.ql +++ b/python/ql/test/3/library-tests/PointsTo/inheritance/Calls.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from Call c, FunctionObject f where f.getACall().getNode() = c diff --git a/python/ql/test/3/library-tests/PointsTo/metaclass/test.ql b/python/ql/test/3/library-tests/PointsTo/metaclass/test.ql index 68eec976105c..0644e4cdf74a 100644 --- a/python/ql/test/3/library-tests/PointsTo/metaclass/test.ql +++ b/python/ql/test/3/library-tests/PointsTo/metaclass/test.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls where not cls.isC() diff --git a/python/ql/test/3/library-tests/PointsTo/regressions/subprocess-assert/ClassValue.ql b/python/ql/test/3/library-tests/PointsTo/regressions/subprocess-assert/ClassValue.ql index bc666b4f2060..479ae6e59656 100644 --- a/python/ql/test/3/library-tests/PointsTo/regressions/subprocess-assert/ClassValue.ql +++ b/python/ql/test/3/library-tests/PointsTo/regressions/subprocess-assert/ClassValue.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo // as used in semmle.python.filters.Tests from ClassValue c, string base diff --git a/python/ql/test/3/library-tests/classes/attr/class_attr.ql b/python/ql/test/3/library-tests/classes/attr/class_attr.ql index 197ab1a1e5eb..1c9c5513a1d7 100644 --- a/python/ql/test/3/library-tests/classes/attr/class_attr.ql +++ b/python/ql/test/3/library-tests/classes/attr/class_attr.ql @@ -5,6 +5,7 @@ */ import python +private import LegacyPointsTo from ClassObject cls, int line, string name, Object obj where diff --git a/python/ql/test/3/library-tests/classes/attr/class_has_attr.ql b/python/ql/test/3/library-tests/classes/attr/class_has_attr.ql index be8272d1bd6b..24724f4d8593 100644 --- a/python/ql/test/3/library-tests/classes/attr/class_has_attr.ql +++ b/python/ql/test/3/library-tests/classes/attr/class_has_attr.ql @@ -5,6 +5,7 @@ */ import python +private import LegacyPointsTo from ClassObject cls, int line, string name where diff --git a/python/ql/test/3/library-tests/classes/meta/meta_obj.ql b/python/ql/test/3/library-tests/classes/meta/meta_obj.ql index e85127a9305f..af46400ce00d 100644 --- a/python/ql/test/3/library-tests/classes/meta/meta_obj.ql +++ b/python/ql/test/3/library-tests/classes/meta/meta_obj.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls where not cls.isC() diff --git a/python/ql/test/3/library-tests/classes/mro/mro.ql b/python/ql/test/3/library-tests/classes/mro/mro.ql index 576d6a75afde..86934f52c115 100644 --- a/python/ql/test/3/library-tests/classes/mro/mro.ql +++ b/python/ql/test/3/library-tests/classes/mro/mro.ql @@ -5,6 +5,7 @@ */ import python +private import LegacyPointsTo from ClassObject cls, ClassObject l, ClassObject r where diff --git a/python/ql/test/3/library-tests/classes/mro/mro_index.ql b/python/ql/test/3/library-tests/classes/mro/mro_index.ql index da40776044ee..6a65d27b716a 100644 --- a/python/ql/test/3/library-tests/classes/mro/mro_index.ql +++ b/python/ql/test/3/library-tests/classes/mro/mro_index.ql @@ -5,6 +5,7 @@ */ import python +private import LegacyPointsTo from ClassObject cls, ClassObject sup, int index where diff --git a/python/ql/test/3/library-tests/modules/general/moduleobject_test.ql b/python/ql/test/3/library-tests/modules/general/moduleobject_test.ql index a3a1ac6b1859..db5b72e4dc4a 100644 --- a/python/ql/test/3/library-tests/modules/general/moduleobject_test.ql +++ b/python/ql/test/3/library-tests/modules/general/moduleobject_test.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ModuleObject m, string name where not m.isC() and not m.getName() = "__future__" diff --git a/python/ql/test/3/library-tests/modules/package_members/module_attributes.ql b/python/ql/test/3/library-tests/modules/package_members/module_attributes.ql index 6c16450f3134..f7755b92e12a 100644 --- a/python/ql/test/3/library-tests/modules/package_members/module_attributes.ql +++ b/python/ql/test/3/library-tests/modules/package_members/module_attributes.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ModuleObject m, string name where not m.isC() diff --git a/python/ql/test/3/library-tests/modules/package_members/module_exports.ql b/python/ql/test/3/library-tests/modules/package_members/module_exports.ql index bcfc0c60bfb7..d04ef3bc9f31 100644 --- a/python/ql/test/3/library-tests/modules/package_members/module_exports.ql +++ b/python/ql/test/3/library-tests/modules/package_members/module_exports.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ModuleObject m, string name where not m.isC() and m.exports(name) diff --git a/python/ql/test/3/library-tests/modules/package_members/module_import_as.ql b/python/ql/test/3/library-tests/modules/package_members/module_import_as.ql index 50ded7b41244..97cc2e866652 100644 --- a/python/ql/test/3/library-tests/modules/package_members/module_import_as.ql +++ b/python/ql/test/3/library-tests/modules/package_members/module_import_as.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ModuleObject m, string name where not m.isC() and m.importedAs(name) diff --git a/python/ql/test/3/library-tests/modules/usage/ModuleUsage.ql b/python/ql/test/3/library-tests/modules/usage/ModuleUsage.ql index 5f776e2374e6..0469f804ab33 100644 --- a/python/ql/test/3/library-tests/modules/usage/ModuleUsage.ql +++ b/python/ql/test/3/library-tests/modules/usage/ModuleUsage.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ModuleValue mv, string usage where diff --git a/python/ql/test/3/library-tests/types/classes/mro_test.ql b/python/ql/test/3/library-tests/types/classes/mro_test.ql index 04b65ae2befb..4dc9bc153a27 100644 --- a/python/ql/test/3/library-tests/types/classes/mro_test.ql +++ b/python/ql/test/3/library-tests/types/classes/mro_test.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls, ClassObject sup where not cls.isC() diff --git a/python/ql/test/3/library-tests/types/exceptions/Raises.ql b/python/ql/test/3/library-tests/types/exceptions/Raises.ql index 2415c7079670..e4f9a6664d55 100644 --- a/python/ql/test/3/library-tests/types/exceptions/Raises.ql +++ b/python/ql/test/3/library-tests/types/exceptions/Raises.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from PyFunctionObject f, string type where diff --git a/python/ql/test/3/library-tests/types/exceptions/Viable.ql b/python/ql/test/3/library-tests/types/exceptions/Viable.ql index bf00a0675d63..589e2630bb91 100644 --- a/python/ql/test/3/library-tests/types/exceptions/Viable.ql +++ b/python/ql/test/3/library-tests/types/exceptions/Viable.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from RaisingNode r, ControlFlowNode n, ClassObject ex where r.viableExceptionEdge_objectapi(n, ex) diff --git a/python/ql/test/3/library-tests/types/functions/Calls.ql b/python/ql/test/3/library-tests/types/functions/Calls.ql index 6fc188753e55..5eaeb4559b0c 100644 --- a/python/ql/test/3/library-tests/types/functions/Calls.ql +++ b/python/ql/test/3/library-tests/types/functions/Calls.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from FunctionObject func, ControlFlowNode call where func.getACall() = call diff --git a/python/ql/test/3/library-tests/types/functions/Never.ql b/python/ql/test/3/library-tests/types/functions/Never.ql index 1e43ead7dce7..932121d058ea 100644 --- a/python/ql/test/3/library-tests/types/functions/Never.ql +++ b/python/ql/test/3/library-tests/types/functions/Never.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from FunctionObject func where func.neverReturns() diff --git a/python/ql/test/3/library-tests/types/functions/ReturnTypes.ql b/python/ql/test/3/library-tests/types/functions/ReturnTypes.ql index beb955e11881..d35deea34bfe 100644 --- a/python/ql/test/3/library-tests/types/functions/ReturnTypes.ql +++ b/python/ql/test/3/library-tests/types/functions/ReturnTypes.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from PyFunctionObject func, ClassObject ret_type where func.getAnInferredReturnType() = ret_type diff --git a/python/ql/test/3/library-tests/types/namespaces/NameSpace.ql b/python/ql/test/3/library-tests/types/namespaces/NameSpace.ql index 38241e8fabca..f41d977d47b4 100644 --- a/python/ql/test/3/library-tests/types/namespaces/NameSpace.ql +++ b/python/ql/test/3/library-tests/types/namespaces/NameSpace.ql @@ -6,6 +6,7 @@ */ import python +private import LegacyPointsTo from Scope s, string name, Object val where diff --git a/python/ql/test/3/library-tests/types/properties/BuiltinProperties.ql b/python/ql/test/3/library-tests/types/properties/BuiltinProperties.ql index 24766db9f2eb..9ab0b5e4bbdc 100644 --- a/python/ql/test/3/library-tests/types/properties/BuiltinProperties.ql +++ b/python/ql/test/3/library-tests/types/properties/BuiltinProperties.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls, string name, BuiltinPropertyObject p where From 058e9754667860c5a3e4a5e4449c81810ff500ee Mon Sep 17 00:00:00 2001 From: Taus Date: Thu, 30 Oct 2025 23:08:43 +0000 Subject: [PATCH 13/19] Python: Fix extractor/experimental tests --- .../experimental/library-tests/CallGraph/InlineCallGraphTest.ql | 1 + python/ql/test/extractor-tests/double-import/ModuleNames.ql | 1 + python/ql/test/extractor-tests/unicode_decoding/test.ql | 1 + 3 files changed, 3 insertions(+) diff --git a/python/ql/test/experimental/library-tests/CallGraph/InlineCallGraphTest.ql b/python/ql/test/experimental/library-tests/CallGraph/InlineCallGraphTest.ql index 1771727dbbca..5cdbd9e6a4e5 100644 --- a/python/ql/test/experimental/library-tests/CallGraph/InlineCallGraphTest.ql +++ b/python/ql/test/experimental/library-tests/CallGraph/InlineCallGraphTest.ql @@ -1,6 +1,7 @@ import python import utils.test.InlineExpectationsTest private import semmle.python.dataflow.new.internal.DataFlowDispatch as TT +private import LegacyPointsTo /** Holds when `call` is resolved to `callable` using points-to based call-graph. */ predicate pointsToCallEdge(CallNode call, Function callable) { diff --git a/python/ql/test/extractor-tests/double-import/ModuleNames.ql b/python/ql/test/extractor-tests/double-import/ModuleNames.ql index 54aa78e23a3e..6d25cf91f700 100644 --- a/python/ql/test/extractor-tests/double-import/ModuleNames.ql +++ b/python/ql/test/extractor-tests/double-import/ModuleNames.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from Container path, string name where exists(ModuleValue m | m.getPath() = path and m.getName() = name) diff --git a/python/ql/test/extractor-tests/unicode_decoding/test.ql b/python/ql/test/extractor-tests/unicode_decoding/test.ql index b2d51b10d224..4e0937a07c44 100644 --- a/python/ql/test/extractor-tests/unicode_decoding/test.ql +++ b/python/ql/test/extractor-tests/unicode_decoding/test.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from Object o, string s where From 03da5ab693bd2dd8bdff528be0a85135a950785c Mon Sep 17 00:00:00 2001 From: Taus Date: Thu, 30 Oct 2025 23:10:15 +0000 Subject: [PATCH 14/19] Python: Fix library tests --- python/ql/test/library-tests/PointsTo/api/ClassValue.ql | 1 + python/ql/test/library-tests/PointsTo/api/Constants.ql | 1 + python/ql/test/library-tests/PointsTo/api/QualifedNames.ql | 1 + python/ql/test/library-tests/PointsTo/api/Value.ql | 1 + python/ql/test/library-tests/PointsTo/calls/GetACall.ql | 1 + .../test/library-tests/PointsTo/calls/getArgumentForCall.ql | 1 + .../library-tests/PointsTo/calls/getNamedArgumentForCall.ql | 1 + python/ql/test/library-tests/PointsTo/calls/getParameter.ql | 1 + .../test/library-tests/PointsTo/calls/getParameterByName.ql | 1 + python/ql/test/library-tests/PointsTo/decorators/Values.ql | 3 +-- python/ql/test/library-tests/PointsTo/functions/Calls.ql | 1 + .../ql/test/library-tests/PointsTo/functions/NeverReturns.ql | 1 + python/ql/test/library-tests/PointsTo/functions/test.ql | 1 + python/ql/test/library-tests/PointsTo/general/Util.qll | 1 + python/ql/test/library-tests/PointsTo/global/Global.ql | 4 +--- .../ql/test/library-tests/PointsTo/inheritance/BaseTypes.ql | 1 + python/ql/test/library-tests/PointsTo/inheritance/Calls.ql | 1 + python/ql/test/library-tests/PointsTo/inheritance/Declares.ql | 1 + .../ql/test/library-tests/PointsTo/inheritance/MetaClass.ql | 1 + .../ql/test/library-tests/PointsTo/inheritance/SuperTypes.ql | 1 + python/ql/test/library-tests/PointsTo/metaclass/Failed.ql | 1 + python/ql/test/library-tests/PointsTo/metaclass/Style.ql | 1 + python/ql/test/library-tests/PointsTo/metaclass/test.ql | 2 +- python/ql/test/library-tests/PointsTo/new/Call.ql | 1 + python/ql/test/library-tests/PointsTo/new/ClassMethod.ql | 1 + python/ql/test/library-tests/PointsTo/new/NameSpace.ql | 1 + python/ql/test/library-tests/PointsTo/new/PointsToMissing.ql | 2 +- python/ql/test/library-tests/PointsTo/new/PointsToUnknown.ql | 2 +- .../ql/test/library-tests/PointsTo/new/PointsToWithContext.ql | 3 +-- python/ql/test/library-tests/PointsTo/new/PointsToWithType.ql | 2 +- python/ql/test/library-tests/PointsTo/new/Reachable.ql | 2 +- python/ql/test/library-tests/PointsTo/new/SSA.ql | 3 +-- .../test/library-tests/PointsTo/new/SourceEdgeDefinitions.ql | 1 - .../test/library-tests/PointsTo/new/SourceNodeDefinitions.ql | 1 - python/ql/test/library-tests/PointsTo/new/SsaAttr.ql | 3 +-- python/ql/test/library-tests/PointsTo/new/SsaUses.ql | 1 - python/ql/test/library-tests/PointsTo/new/TestEvaluate.ql | 3 +-- python/ql/test/library-tests/PointsTo/new/Util.qll | 2 +- python/ql/test/library-tests/PointsTo/new/VarUses.ql | 2 +- .../PointsTo/regressions/missing/metaclass/getACall.ql | 1 + .../module-imports/conflict-stdlib/LocalModuleWithRef.ql | 1 + .../module-imports/conflict-stdlib/ModuleWithLocalRef.ql | 1 + python/ql/test/library-tests/PointsTo/returns/Test.ql | 1 + python/ql/test/library-tests/PointsTo/subclass/Checks.ql | 2 +- python/ql/test/library-tests/attributes/SelfAttribute.ql | 1 + python/ql/test/library-tests/classes/abstract/Abstract.ql | 1 + python/ql/test/library-tests/classes/attr/class_attr.ql | 1 + .../ql/test/library-tests/classes/attr/class_defined_attr.ql | 1 + .../ql/test/library-tests/classes/attr/class_defines_attr.ql | 1 + python/ql/test/library-tests/classes/attr/class_has_attr.ql | 1 + python/ql/test/library-tests/classes/attr/hash.ql | 1 + python/ql/test/library-tests/classes/mro/C3.ql | 1 + python/ql/test/library-tests/dependencies/Dependencies.ql | 1 + python/ql/test/library-tests/descriptors/Descriptors.ql | 1 + python/ql/test/library-tests/descriptors/Methods.ql | 1 + python/ql/test/library-tests/descriptors/Properties.ql | 1 + python/ql/test/library-tests/exceptions/Handles.ql | 1 + python/ql/test/library-tests/exceptions/Legal.ql | 1 + .../ql/test/library-tests/modules/duplicate_name/Modules.ql | 1 + python/ql/test/library-tests/objects/Name.ql | 1 + python/ql/test/library-tests/overrides/FunctionOverrides.ql | 1 + python/ql/test/library-tests/state_tracking/Test.ql | 1 + python/ql/test/library-tests/taint/config/TaintLib.qll | 1 + python/ql/test/library-tests/taint/config/TaintedArgument.ql | 1 + python/ql/test/library-tests/taint/general/ModuleAttribute.ql | 1 + python/ql/test/library-tests/taint/general/TaintLib.qll | 1 + python/ql/test/library-tests/types/attributes/Test.ql | 1 + .../ql/test/library-tests/types/classattr/ClassAttribute.ql | 1 + python/ql/test/library-tests/types/classattr/ClassMember.ql | 1 + .../ql/test/library-tests/types/classattr/SpecialAttribute.ql | 1 + python/ql/test/library-tests/types/classes/FailedInference.ql | 2 +- python/ql/test/library-tests/types/classes/duplicate_base.ql | 1 + python/ql/test/library-tests/types/exceptions/ExitRaises.ql | 1 + python/ql/test/library-tests/types/exceptions/Handles.ql | 1 + python/ql/test/library-tests/types/exceptions/Impossible.ql | 1 + python/ql/test/library-tests/types/exceptions/LineRaises.ql | 1 + python/ql/test/library-tests/types/exceptions/Raises.ql | 1 + python/ql/test/library-tests/types/exceptions/Reraises.ql | 1 + python/ql/test/library-tests/types/exceptions/Viable.ql | 1 + python/ql/test/library-tests/types/properties/Deleters.ql | 1 + python/ql/test/library-tests/types/properties/Getters.ql | 1 + .../test/library-tests/types/properties/PythonProperties.ql | 1 + python/ql/test/library-tests/types/properties/Setters.ql | 1 + 83 files changed, 80 insertions(+), 25 deletions(-) diff --git a/python/ql/test/library-tests/PointsTo/api/ClassValue.ql b/python/ql/test/library-tests/PointsTo/api/ClassValue.ql index 230cc487ea4a..65a4c73d4a6e 100644 --- a/python/ql/test/library-tests/PointsTo/api/ClassValue.ql +++ b/python/ql/test/library-tests/PointsTo/api/ClassValue.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassValue cls, string description where diff --git a/python/ql/test/library-tests/PointsTo/api/Constants.ql b/python/ql/test/library-tests/PointsTo/api/Constants.ql index 151f6b9ce9c9..a6072a1d8e8f 100644 --- a/python/ql/test/library-tests/PointsTo/api/Constants.ql +++ b/python/ql/test/library-tests/PointsTo/api/Constants.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from string txt, Value val where diff --git a/python/ql/test/library-tests/PointsTo/api/QualifedNames.ql b/python/ql/test/library-tests/PointsTo/api/QualifedNames.ql index daafad0492ba..c756265295bb 100644 --- a/python/ql/test/library-tests/PointsTo/api/QualifedNames.ql +++ b/python/ql/test/library-tests/PointsTo/api/QualifedNames.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from FunctionValue v, string name where diff --git a/python/ql/test/library-tests/PointsTo/api/Value.ql b/python/ql/test/library-tests/PointsTo/api/Value.ql index 9c6e07394611..fadf008f6ead 100644 --- a/python/ql/test/library-tests/PointsTo/api/Value.ql +++ b/python/ql/test/library-tests/PointsTo/api/Value.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from Value val, string name where diff --git a/python/ql/test/library-tests/PointsTo/calls/GetACall.ql b/python/ql/test/library-tests/PointsTo/calls/GetACall.ql index 84f2ab4fb4ae..8c6cc76c0310 100644 --- a/python/ql/test/library-tests/PointsTo/calls/GetACall.ql +++ b/python/ql/test/library-tests/PointsTo/calls/GetACall.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ControlFlowNode call, Value func where call = func.getACall() diff --git a/python/ql/test/library-tests/PointsTo/calls/getArgumentForCall.ql b/python/ql/test/library-tests/PointsTo/calls/getArgumentForCall.ql index 7c76b9e0ce50..d388f96783cb 100644 --- a/python/ql/test/library-tests/PointsTo/calls/getArgumentForCall.ql +++ b/python/ql/test/library-tests/PointsTo/calls/getArgumentForCall.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from CallNode call, CallableValue callable, int i select call.getLocation().getStartLine(), call.toString(), callable.toString(), i, diff --git a/python/ql/test/library-tests/PointsTo/calls/getNamedArgumentForCall.ql b/python/ql/test/library-tests/PointsTo/calls/getNamedArgumentForCall.ql index 4cb3fbdf3358..7fa39194debc 100644 --- a/python/ql/test/library-tests/PointsTo/calls/getNamedArgumentForCall.ql +++ b/python/ql/test/library-tests/PointsTo/calls/getNamedArgumentForCall.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from CallNode call, CallableValue callable, string name select call.getLocation().getStartLine(), call.toString(), callable.toString(), name, diff --git a/python/ql/test/library-tests/PointsTo/calls/getParameter.ql b/python/ql/test/library-tests/PointsTo/calls/getParameter.ql index 07f12cce36fa..1cabfeb45bc0 100644 --- a/python/ql/test/library-tests/PointsTo/calls/getParameter.ql +++ b/python/ql/test/library-tests/PointsTo/calls/getParameter.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from CallableValue callable, int i select callable.toString(), i, callable.getParameter(i).toString() diff --git a/python/ql/test/library-tests/PointsTo/calls/getParameterByName.ql b/python/ql/test/library-tests/PointsTo/calls/getParameterByName.ql index d4766b680f73..20c4c77f121e 100644 --- a/python/ql/test/library-tests/PointsTo/calls/getParameterByName.ql +++ b/python/ql/test/library-tests/PointsTo/calls/getParameterByName.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from CallableValue callable, string name select callable.toString(), name, callable.getParameterByName(name).toString() diff --git a/python/ql/test/library-tests/PointsTo/decorators/Values.ql b/python/ql/test/library-tests/PointsTo/decorators/Values.ql index fc7a08db20ba..fe4b6d080f4d 100644 --- a/python/ql/test/library-tests/PointsTo/decorators/Values.ql +++ b/python/ql/test/library-tests/PointsTo/decorators/Values.ql @@ -1,6 +1,5 @@ import python -import semmle.python.pointsto.PointsTo -import semmle.python.objects.ObjectInternal +private import LegacyPointsTo from NameNode f, Context ctx, ObjectInternal v where diff --git a/python/ql/test/library-tests/PointsTo/functions/Calls.ql b/python/ql/test/library-tests/PointsTo/functions/Calls.ql index 5bc29b5aaf3d..659ba4143f63 100644 --- a/python/ql/test/library-tests/PointsTo/functions/Calls.ql +++ b/python/ql/test/library-tests/PointsTo/functions/Calls.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from CallNode call, FunctionObject func, string kind where diff --git a/python/ql/test/library-tests/PointsTo/functions/NeverReturns.ql b/python/ql/test/library-tests/PointsTo/functions/NeverReturns.ql index c576651a8e63..0a20f8e1b1f8 100644 --- a/python/ql/test/library-tests/PointsTo/functions/NeverReturns.ql +++ b/python/ql/test/library-tests/PointsTo/functions/NeverReturns.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from FunctionObject f where f.neverReturns() diff --git a/python/ql/test/library-tests/PointsTo/functions/test.ql b/python/ql/test/library-tests/PointsTo/functions/test.ql index f85e95f5fe46..01f8416c8dc1 100644 --- a/python/ql/test/library-tests/PointsTo/functions/test.ql +++ b/python/ql/test/library-tests/PointsTo/functions/test.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from Call c, FunctionObject f where diff --git a/python/ql/test/library-tests/PointsTo/general/Util.qll b/python/ql/test/library-tests/PointsTo/general/Util.qll index 1c26d7d830b9..289e71a9e6c8 100644 --- a/python/ql/test/library-tests/PointsTo/general/Util.qll +++ b/python/ql/test/library-tests/PointsTo/general/Util.qll @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo string repr(Object o) { not o instanceof StringObject and not o = theBoundMethodType() and result = o.toString() diff --git a/python/ql/test/library-tests/PointsTo/global/Global.ql b/python/ql/test/library-tests/PointsTo/global/Global.ql index f9f52b12641f..4dc6d16d3797 100644 --- a/python/ql/test/library-tests/PointsTo/global/Global.ql +++ b/python/ql/test/library-tests/PointsTo/global/Global.ql @@ -1,7 +1,5 @@ import python -import semmle.python.pointsto.PointsTo -import semmle.python.pointsto.PointsToContext -import semmle.python.objects.ObjectInternal +private import LegacyPointsTo from ControlFlowNode f, PointsToContext ctx, Value obj, ControlFlowNode orig where diff --git a/python/ql/test/library-tests/PointsTo/inheritance/BaseTypes.ql b/python/ql/test/library-tests/PointsTo/inheritance/BaseTypes.ql index f1201eba0dcf..01f69d8bb12e 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/BaseTypes.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/BaseTypes.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls, ClassObject base, int n where diff --git a/python/ql/test/library-tests/PointsTo/inheritance/Calls.ql b/python/ql/test/library-tests/PointsTo/inheritance/Calls.ql index f91d207fc708..3f111d6e08a8 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/Calls.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/Calls.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from Call c, FunctionObject f where f.getACall().getNode() = c diff --git a/python/ql/test/library-tests/PointsTo/inheritance/Declares.ql b/python/ql/test/library-tests/PointsTo/inheritance/Declares.ql index a2c762be8600..2fe61ca2d7fe 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/Declares.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/Declares.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls, string name where class_declares_attribute(cls, name) diff --git a/python/ql/test/library-tests/PointsTo/inheritance/MetaClass.ql b/python/ql/test/library-tests/PointsTo/inheritance/MetaClass.ql index 0ca907821194..a487c16e953e 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/MetaClass.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/MetaClass.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls, ClassObject meta where diff --git a/python/ql/test/library-tests/PointsTo/inheritance/SuperTypes.ql b/python/ql/test/library-tests/PointsTo/inheritance/SuperTypes.ql index 338ea118ac17..c3156eb1fa0b 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/SuperTypes.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/SuperTypes.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls, ClassObject sup where diff --git a/python/ql/test/library-tests/PointsTo/metaclass/Failed.ql b/python/ql/test/library-tests/PointsTo/metaclass/Failed.ql index a5d2afd42418..4129c99666b0 100644 --- a/python/ql/test/library-tests/PointsTo/metaclass/Failed.ql +++ b/python/ql/test/library-tests/PointsTo/metaclass/Failed.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls, string reason where diff --git a/python/ql/test/library-tests/PointsTo/metaclass/Style.ql b/python/ql/test/library-tests/PointsTo/metaclass/Style.ql index f29ba3a8b7cf..7ab5b4a329f1 100644 --- a/python/ql/test/library-tests/PointsTo/metaclass/Style.ql +++ b/python/ql/test/library-tests/PointsTo/metaclass/Style.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls, string style where diff --git a/python/ql/test/library-tests/PointsTo/metaclass/test.ql b/python/ql/test/library-tests/PointsTo/metaclass/test.ql index d08f4e37fa67..471c01599d6f 100644 --- a/python/ql/test/library-tests/PointsTo/metaclass/test.ql +++ b/python/ql/test/library-tests/PointsTo/metaclass/test.ql @@ -1,5 +1,5 @@ import python -private import semmle.python.objects.ObjectInternal +private import LegacyPointsTo /** An unknown type. Not usually visible. */ class UnknownType extends UnknownClassInternal { diff --git a/python/ql/test/library-tests/PointsTo/new/Call.ql b/python/ql/test/library-tests/PointsTo/new/Call.ql index f014001f3152..e924398ca40d 100644 --- a/python/ql/test/library-tests/PointsTo/new/Call.ql +++ b/python/ql/test/library-tests/PointsTo/new/Call.ql @@ -1,5 +1,6 @@ import python import Util +private import LegacyPointsTo from ControlFlowNode call, FunctionObject func where call = func.getACall() diff --git a/python/ql/test/library-tests/PointsTo/new/ClassMethod.ql b/python/ql/test/library-tests/PointsTo/new/ClassMethod.ql index 17f73420e05e..9eac6e3fea29 100644 --- a/python/ql/test/library-tests/PointsTo/new/ClassMethod.ql +++ b/python/ql/test/library-tests/PointsTo/new/ClassMethod.ql @@ -1,5 +1,6 @@ import python import Util +private import LegacyPointsTo from ClassMethodObject cm, CallNode call where call = cm.getACall() diff --git a/python/ql/test/library-tests/PointsTo/new/NameSpace.ql b/python/ql/test/library-tests/PointsTo/new/NameSpace.ql index 5d099f78b614..6150b94aee1b 100644 --- a/python/ql/test/library-tests/PointsTo/new/NameSpace.ql +++ b/python/ql/test/library-tests/PointsTo/new/NameSpace.ql @@ -1,5 +1,6 @@ import python import Util +private import LegacyPointsTo from Scope s, string name, Object val where diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToMissing.ql b/python/ql/test/library-tests/PointsTo/new/PointsToMissing.ql index 9e744591df23..271f35db9963 100644 --- a/python/ql/test/library-tests/PointsTo/new/PointsToMissing.ql +++ b/python/ql/test/library-tests/PointsTo/new/PointsToMissing.ql @@ -1,6 +1,6 @@ import python import Util -import semmle.python.pointsto.PointsTo +private import LegacyPointsTo /* This test should return _no_ results. */ predicate relevant_node(ControlFlowNode n) { diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToUnknown.ql b/python/ql/test/library-tests/PointsTo/new/PointsToUnknown.ql index cb91e18dafe0..2526819b76ac 100644 --- a/python/ql/test/library-tests/PointsTo/new/PointsToUnknown.ql +++ b/python/ql/test/library-tests/PointsTo/new/PointsToUnknown.ql @@ -1,6 +1,6 @@ import python import Util -import semmle.python.pointsto.PointsTo +private import LegacyPointsTo from ControlFlowNode f, ControlFlowNode x where PointsTo::pointsTo(f, _, ObjectInternal::unknown(), x) diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.ql b/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.ql index dbed1a9a7f6b..bad7589d0a20 100644 --- a/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.ql +++ b/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.ql @@ -1,7 +1,6 @@ import python import Util -import semmle.python.pointsto.PointsTo -import semmle.python.pointsto.PointsToContext +private import LegacyPointsTo from ControlFlowNode f, Object o, ClassObject c, ControlFlowNode x, PointsToContext ctx where PointsTo::points_to(f, ctx, o, c, x) diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToWithType.ql b/python/ql/test/library-tests/PointsTo/new/PointsToWithType.ql index 5747ce18fd56..20a23abced7d 100644 --- a/python/ql/test/library-tests/PointsTo/new/PointsToWithType.ql +++ b/python/ql/test/library-tests/PointsTo/new/PointsToWithType.ql @@ -1,6 +1,6 @@ import python import Util -import semmle.python.pointsto.PointsTo +private import LegacyPointsTo from ControlFlowNode f, Object o, ClassObject c, ControlFlowNode x where PointsTo::points_to(f, _, o, c, x) diff --git a/python/ql/test/library-tests/PointsTo/new/Reachable.ql b/python/ql/test/library-tests/PointsTo/new/Reachable.ql index f8b2f0585eb9..2376f13c7521 100644 --- a/python/ql/test/library-tests/PointsTo/new/Reachable.ql +++ b/python/ql/test/library-tests/PointsTo/new/Reachable.ql @@ -1,5 +1,5 @@ import python -private import semmle.python.pointsto.PointsTo +private import LegacyPointsTo import Util from ControlFlowNode f, Context ctx diff --git a/python/ql/test/library-tests/PointsTo/new/SSA.ql b/python/ql/test/library-tests/PointsTo/new/SSA.ql index 7b41f3c427eb..c919e1d4856c 100644 --- a/python/ql/test/library-tests/PointsTo/new/SSA.ql +++ b/python/ql/test/library-tests/PointsTo/new/SSA.ql @@ -1,6 +1,5 @@ import python -private import semmle.python.pointsto.PointsTo -private import semmle.python.pointsto.PointsToContext +private import LegacyPointsTo import Util predicate ssa_variable_points_to( diff --git a/python/ql/test/library-tests/PointsTo/new/SourceEdgeDefinitions.ql b/python/ql/test/library-tests/PointsTo/new/SourceEdgeDefinitions.ql index 8cf0b4c15a6f..117afe8100ef 100644 --- a/python/ql/test/library-tests/PointsTo/new/SourceEdgeDefinitions.ql +++ b/python/ql/test/library-tests/PointsTo/new/SourceEdgeDefinitions.ql @@ -1,5 +1,4 @@ import python -import semmle.python.pointsto.PointsTo import Util from SsaSourceVariable var, ControlFlowNode use, BasicBlock pred diff --git a/python/ql/test/library-tests/PointsTo/new/SourceNodeDefinitions.ql b/python/ql/test/library-tests/PointsTo/new/SourceNodeDefinitions.ql index 77f6ab0923b7..2c5867f9c4f1 100644 --- a/python/ql/test/library-tests/PointsTo/new/SourceNodeDefinitions.ql +++ b/python/ql/test/library-tests/PointsTo/new/SourceNodeDefinitions.ql @@ -1,5 +1,4 @@ import python -import semmle.python.pointsto.PointsTo import Util from SsaSourceVariable var, ControlFlowNode defn, string kind diff --git a/python/ql/test/library-tests/PointsTo/new/SsaAttr.ql b/python/ql/test/library-tests/PointsTo/new/SsaAttr.ql index 67d85c2e3bd2..c9b136f0c02c 100644 --- a/python/ql/test/library-tests/PointsTo/new/SsaAttr.ql +++ b/python/ql/test/library-tests/PointsTo/new/SsaAttr.ql @@ -1,6 +1,5 @@ import python -private import semmle.python.pointsto.PointsTo -private import semmle.python.objects.ObjectInternal +private import LegacyPointsTo import Util from EssaVariable var, string name, ObjectInternal o, Context ctx diff --git a/python/ql/test/library-tests/PointsTo/new/SsaUses.ql b/python/ql/test/library-tests/PointsTo/new/SsaUses.ql index 2a8e8f1e7506..9a250b6610f2 100644 --- a/python/ql/test/library-tests/PointsTo/new/SsaUses.ql +++ b/python/ql/test/library-tests/PointsTo/new/SsaUses.ql @@ -1,5 +1,4 @@ import python -import semmle.python.pointsto.PointsTo import Util from EssaVariable var, ControlFlowNode use diff --git a/python/ql/test/library-tests/PointsTo/new/TestEvaluate.ql b/python/ql/test/library-tests/PointsTo/new/TestEvaluate.ql index d473e4e804a3..1132f04df070 100644 --- a/python/ql/test/library-tests/PointsTo/new/TestEvaluate.ql +++ b/python/ql/test/library-tests/PointsTo/new/TestEvaluate.ql @@ -1,6 +1,5 @@ import python -import semmle.python.pointsto.PointsTo -import semmle.python.pointsto.PointsToContext +private import LegacyPointsTo import Util from diff --git a/python/ql/test/library-tests/PointsTo/new/Util.qll b/python/ql/test/library-tests/PointsTo/new/Util.qll index b83ad89d1c80..23c5aa8df7c5 100644 --- a/python/ql/test/library-tests/PointsTo/new/Util.qll +++ b/python/ql/test/library-tests/PointsTo/new/Util.qll @@ -1,5 +1,5 @@ import python -import semmle.python.objects.ObjectInternal +private import LegacyPointsTo bindingset[which] string locate(Location l, string which) { diff --git a/python/ql/test/library-tests/PointsTo/new/VarUses.ql b/python/ql/test/library-tests/PointsTo/new/VarUses.ql index 58de54d7a3d8..50b07d03be0a 100644 --- a/python/ql/test/library-tests/PointsTo/new/VarUses.ql +++ b/python/ql/test/library-tests/PointsTo/new/VarUses.ql @@ -1,5 +1,5 @@ import python -import semmle.python.pointsto.PointsTo +private import LegacyPointsTo import Util from SsaSourceVariable var, ControlFlowNode use diff --git a/python/ql/test/library-tests/PointsTo/regressions/missing/metaclass/getACall.ql b/python/ql/test/library-tests/PointsTo/regressions/missing/metaclass/getACall.ql index e555c927d6ab..5ca3c9518d60 100644 --- a/python/ql/test/library-tests/PointsTo/regressions/missing/metaclass/getACall.ql +++ b/python/ql/test/library-tests/PointsTo/regressions/missing/metaclass/getACall.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from PythonFunctionValue func select func, func.getACall() diff --git a/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/LocalModuleWithRef.ql b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/LocalModuleWithRef.ql index 5bdb99415b2a..f6bc97bf1f09 100644 --- a/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/LocalModuleWithRef.ql +++ b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/LocalModuleWithRef.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ModuleValue mv, ControlFlowNode ref, string local_external where diff --git a/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/ModuleWithLocalRef.ql b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/ModuleWithLocalRef.ql index 030211ba0bf7..1422d5731fdc 100644 --- a/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/ModuleWithLocalRef.ql +++ b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/ModuleWithLocalRef.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ModuleValue mv, ControlFlowNode ref, string in_stdlib, string local_external, string is_missing where diff --git a/python/ql/test/library-tests/PointsTo/returns/Test.ql b/python/ql/test/library-tests/PointsTo/returns/Test.ql index 8546de90f246..928e4c9672f3 100644 --- a/python/ql/test/library-tests/PointsTo/returns/Test.ql +++ b/python/ql/test/library-tests/PointsTo/returns/Test.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from PyFunctionObject f select f.toString(), f.getAnInferredReturnType().toString() diff --git a/python/ql/test/library-tests/PointsTo/subclass/Checks.ql b/python/ql/test/library-tests/PointsTo/subclass/Checks.ql index a82002b1d5f8..f9deaabbc882 100644 --- a/python/ql/test/library-tests/PointsTo/subclass/Checks.ql +++ b/python/ql/test/library-tests/PointsTo/subclass/Checks.ql @@ -1,5 +1,5 @@ import python -import semmle.python.pointsto.PointsTo +private import LegacyPointsTo from Value sup, Value cls where Expressions::requireSubClass(cls, sup) diff --git a/python/ql/test/library-tests/attributes/SelfAttribute.ql b/python/ql/test/library-tests/attributes/SelfAttribute.ql index 669931212410..79ceff3a08ad 100644 --- a/python/ql/test/library-tests/attributes/SelfAttribute.ql +++ b/python/ql/test/library-tests/attributes/SelfAttribute.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from SelfAttributeRead sa, int line, string g, string l where diff --git a/python/ql/test/library-tests/classes/abstract/Abstract.ql b/python/ql/test/library-tests/classes/abstract/Abstract.ql index bd2f98034cb4..02c764211266 100644 --- a/python/ql/test/library-tests/classes/abstract/Abstract.ql +++ b/python/ql/test/library-tests/classes/abstract/Abstract.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls, string abstract where diff --git a/python/ql/test/library-tests/classes/attr/class_attr.ql b/python/ql/test/library-tests/classes/attr/class_attr.ql index 197ab1a1e5eb..1c9c5513a1d7 100644 --- a/python/ql/test/library-tests/classes/attr/class_attr.ql +++ b/python/ql/test/library-tests/classes/attr/class_attr.ql @@ -5,6 +5,7 @@ */ import python +private import LegacyPointsTo from ClassObject cls, int line, string name, Object obj where diff --git a/python/ql/test/library-tests/classes/attr/class_defined_attr.ql b/python/ql/test/library-tests/classes/attr/class_defined_attr.ql index d7583e689c4f..4fc6f7b67d2f 100644 --- a/python/ql/test/library-tests/classes/attr/class_defined_attr.ql +++ b/python/ql/test/library-tests/classes/attr/class_defined_attr.ql @@ -5,6 +5,7 @@ */ import python +private import LegacyPointsTo from ClassObject cls, int line, string name, Object obj where diff --git a/python/ql/test/library-tests/classes/attr/class_defines_attr.ql b/python/ql/test/library-tests/classes/attr/class_defines_attr.ql index 6b266a0d40ff..71dee836a9f6 100644 --- a/python/ql/test/library-tests/classes/attr/class_defines_attr.ql +++ b/python/ql/test/library-tests/classes/attr/class_defines_attr.ql @@ -5,6 +5,7 @@ */ import python +private import LegacyPointsTo from ClassObject cls, int line, string name where diff --git a/python/ql/test/library-tests/classes/attr/class_has_attr.ql b/python/ql/test/library-tests/classes/attr/class_has_attr.ql index be8272d1bd6b..24724f4d8593 100644 --- a/python/ql/test/library-tests/classes/attr/class_has_attr.ql +++ b/python/ql/test/library-tests/classes/attr/class_has_attr.ql @@ -5,6 +5,7 @@ */ import python +private import LegacyPointsTo from ClassObject cls, int line, string name where diff --git a/python/ql/test/library-tests/classes/attr/hash.ql b/python/ql/test/library-tests/classes/attr/hash.ql index 19ac8933f695..3708e62ccddc 100644 --- a/python/ql/test/library-tests/classes/attr/hash.ql +++ b/python/ql/test/library-tests/classes/attr/hash.ql @@ -5,6 +5,7 @@ */ import python +private import LegacyPointsTo from ClassObject cls, int line, Object obj where diff --git a/python/ql/test/library-tests/classes/mro/C3.ql b/python/ql/test/library-tests/classes/mro/C3.ql index 981a55893c2f..60b4b0c1e1be 100644 --- a/python/ql/test/library-tests/classes/mro/C3.ql +++ b/python/ql/test/library-tests/classes/mro/C3.ql @@ -1,5 +1,6 @@ import python import semmle.python.pointsto.MRO +private import LegacyPointsTo from ClassValue cls where not cls.isBuiltin() diff --git a/python/ql/test/library-tests/dependencies/Dependencies.ql b/python/ql/test/library-tests/dependencies/Dependencies.ql index 12378a567d2a..6f0f6cb3bb79 100644 --- a/python/ql/test/library-tests/dependencies/Dependencies.ql +++ b/python/ql/test/library-tests/dependencies/Dependencies.ql @@ -1,5 +1,6 @@ import python import semmle.python.dependencies.Dependencies +private import LegacyPointsTo from DependencyKind dk, AstNode src, Object target where dk.isADependency(src, target) diff --git a/python/ql/test/library-tests/descriptors/Descriptors.ql b/python/ql/test/library-tests/descriptors/Descriptors.ql index e577d47b4213..7a0f196f3f6e 100644 --- a/python/ql/test/library-tests/descriptors/Descriptors.ql +++ b/python/ql/test/library-tests/descriptors/Descriptors.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls, string kind where diff --git a/python/ql/test/library-tests/descriptors/Methods.ql b/python/ql/test/library-tests/descriptors/Methods.ql index 3761ec5f7b59..49c8a3bbbffb 100644 --- a/python/ql/test/library-tests/descriptors/Methods.ql +++ b/python/ql/test/library-tests/descriptors/Methods.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo int lineof(Object o) { result = o.getOrigin().getLocation().getStartLine() } diff --git a/python/ql/test/library-tests/descriptors/Properties.ql b/python/ql/test/library-tests/descriptors/Properties.ql index 29f9e2577a0b..349d0a242f90 100644 --- a/python/ql/test/library-tests/descriptors/Properties.ql +++ b/python/ql/test/library-tests/descriptors/Properties.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from PropertyValue p, string method_name, FunctionValue method where diff --git a/python/ql/test/library-tests/exceptions/Handles.ql b/python/ql/test/library-tests/exceptions/Handles.ql index 620944de5b90..60989ff86452 100644 --- a/python/ql/test/library-tests/exceptions/Handles.ql +++ b/python/ql/test/library-tests/exceptions/Handles.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ExceptFlowNode ex, Value val where ex.handledException(val, _, _) diff --git a/python/ql/test/library-tests/exceptions/Legal.ql b/python/ql/test/library-tests/exceptions/Legal.ql index bfe47717d232..5b10854c1e1f 100644 --- a/python/ql/test/library-tests/exceptions/Legal.ql +++ b/python/ql/test/library-tests/exceptions/Legal.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls, string legal where diff --git a/python/ql/test/library-tests/modules/duplicate_name/Modules.ql b/python/ql/test/library-tests/modules/duplicate_name/Modules.ql index a6477c7d6af0..af3df6f6eca6 100644 --- a/python/ql/test/library-tests/modules/duplicate_name/Modules.ql +++ b/python/ql/test/library-tests/modules/duplicate_name/Modules.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from string name, int mcnt where mcnt = strictcount(Module m | m.getName() = name) and mcnt > 1 diff --git a/python/ql/test/library-tests/objects/Name.ql b/python/ql/test/library-tests/objects/Name.ql index c274ed345541..e4bac8bba65c 100644 --- a/python/ql/test/library-tests/objects/Name.ql +++ b/python/ql/test/library-tests/objects/Name.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from Object o, string name where diff --git a/python/ql/test/library-tests/overrides/FunctionOverrides.ql b/python/ql/test/library-tests/overrides/FunctionOverrides.ql index c719006665d3..a30ca89d6cc9 100644 --- a/python/ql/test/library-tests/overrides/FunctionOverrides.ql +++ b/python/ql/test/library-tests/overrides/FunctionOverrides.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from PythonFunctionValue f, string overriding, string overridden where diff --git a/python/ql/test/library-tests/state_tracking/Test.ql b/python/ql/test/library-tests/state_tracking/Test.ql index a0a12e8615d2..706dc73191ae 100644 --- a/python/ql/test/library-tests/state_tracking/Test.ql +++ b/python/ql/test/library-tests/state_tracking/Test.ql @@ -1,5 +1,6 @@ import python import Lib +private import LegacyPointsTo from ControlFlowNode f, TrackableState state, Context ctx, boolean sense where diff --git a/python/ql/test/library-tests/taint/config/TaintLib.qll b/python/ql/test/library-tests/taint/config/TaintLib.qll index 35eebe8ffa6a..82bc4afa72e0 100644 --- a/python/ql/test/library-tests/taint/config/TaintLib.qll +++ b/python/ql/test/library-tests/taint/config/TaintLib.qll @@ -1,5 +1,6 @@ import python import semmle.python.dataflow.TaintTracking +private import LegacyPointsTo class SimpleTest extends TaintKind { SimpleTest() { this = "simple.test" } diff --git a/python/ql/test/library-tests/taint/config/TaintedArgument.ql b/python/ql/test/library-tests/taint/config/TaintedArgument.ql index b8753b3fe00d..e3689bca0d8e 100644 --- a/python/ql/test/library-tests/taint/config/TaintedArgument.ql +++ b/python/ql/test/library-tests/taint/config/TaintedArgument.ql @@ -2,6 +2,7 @@ import python import semmle.python.dataflow.TaintTracking import TaintLib import semmle.python.dataflow.Implementation +private import LegacyPointsTo from TaintTrackingImplementation config, TaintTrackingNode src, CallNode call, diff --git a/python/ql/test/library-tests/taint/general/ModuleAttribute.ql b/python/ql/test/library-tests/taint/general/ModuleAttribute.ql index 6a4349b41001..8da8cb5048ec 100644 --- a/python/ql/test/library-tests/taint/general/ModuleAttribute.ql +++ b/python/ql/test/library-tests/taint/general/ModuleAttribute.ql @@ -1,6 +1,7 @@ import python import semmle.python.dataflow.Implementation import TaintLib +private import LegacyPointsTo from ModuleValue m, string name, TaintedNode origin, TaintTrackingImplementation impl where impl.moduleAttributeTainted(m, name, origin) diff --git a/python/ql/test/library-tests/taint/general/TaintLib.qll b/python/ql/test/library-tests/taint/general/TaintLib.qll index af3799c3b95d..eb55093ad097 100644 --- a/python/ql/test/library-tests/taint/general/TaintLib.qll +++ b/python/ql/test/library-tests/taint/general/TaintLib.qll @@ -1,5 +1,6 @@ import python import semmle.python.dataflow.TaintTracking +private import LegacyPointsTo class SimpleTest extends TaintKind { SimpleTest() { this = "simple.test" } diff --git a/python/ql/test/library-tests/types/attributes/Test.ql b/python/ql/test/library-tests/types/attributes/Test.ql index 9e066a6414bd..ba2e8995dc21 100644 --- a/python/ql/test/library-tests/types/attributes/Test.ql +++ b/python/ql/test/library-tests/types/attributes/Test.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls, ClassObject start, string name, Object val where not name.substring(0, 2) = "__" and val = cls.lookupMro(start, name) diff --git a/python/ql/test/library-tests/types/classattr/ClassAttribute.ql b/python/ql/test/library-tests/types/classattr/ClassAttribute.ql index d0633a36e3a3..fc775ebf39ba 100644 --- a/python/ql/test/library-tests/types/classattr/ClassAttribute.ql +++ b/python/ql/test/library-tests/types/classattr/ClassAttribute.ql @@ -5,6 +5,7 @@ */ import python +private import LegacyPointsTo from ClassObject cls, string name, string kind where diff --git a/python/ql/test/library-tests/types/classattr/ClassMember.ql b/python/ql/test/library-tests/types/classattr/ClassMember.ql index d1e136a51084..54f1d1a5b02c 100644 --- a/python/ql/test/library-tests/types/classattr/ClassMember.ql +++ b/python/ql/test/library-tests/types/classattr/ClassMember.ql @@ -5,6 +5,7 @@ */ import python +private import LegacyPointsTo from ClassObject cls, string name, string kind, Object o where diff --git a/python/ql/test/library-tests/types/classattr/SpecialAttribute.ql b/python/ql/test/library-tests/types/classattr/SpecialAttribute.ql index dc21b250c1ec..375e9b9880e6 100644 --- a/python/ql/test/library-tests/types/classattr/SpecialAttribute.ql +++ b/python/ql/test/library-tests/types/classattr/SpecialAttribute.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls, string name, string kind, Object o where diff --git a/python/ql/test/library-tests/types/classes/FailedInference.ql b/python/ql/test/library-tests/types/classes/FailedInference.ql index 192cf696fbf1..feae8fdc5ee2 100644 --- a/python/ql/test/library-tests/types/classes/FailedInference.ql +++ b/python/ql/test/library-tests/types/classes/FailedInference.ql @@ -1,5 +1,5 @@ import python -import semmle.python.pointsto.PointsTo +private import LegacyPointsTo from ClassValue cls, string reason where Types::failedInference(cls, reason) diff --git a/python/ql/test/library-tests/types/classes/duplicate_base.ql b/python/ql/test/library-tests/types/classes/duplicate_base.ql index 47e975c45604..7a32b545ae0d 100644 --- a/python/ql/test/library-tests/types/classes/duplicate_base.ql +++ b/python/ql/test/library-tests/types/classes/duplicate_base.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ClassObject cls where cls.hasDuplicateBases() diff --git a/python/ql/test/library-tests/types/exceptions/ExitRaises.ql b/python/ql/test/library-tests/types/exceptions/ExitRaises.ql index 32ef268332c2..6ad248f66126 100644 --- a/python/ql/test/library-tests/types/exceptions/ExitRaises.ql +++ b/python/ql/test/library-tests/types/exceptions/ExitRaises.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from RaisingNode r, Scope s, ClassObject cls where r.viableExceptionalExit_objectapi(s, cls) diff --git a/python/ql/test/library-tests/types/exceptions/Handles.ql b/python/ql/test/library-tests/types/exceptions/Handles.ql index dfdf1f9d7b29..e5a217249757 100644 --- a/python/ql/test/library-tests/types/exceptions/Handles.ql +++ b/python/ql/test/library-tests/types/exceptions/Handles.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ExceptFlowNode n, ClassObject cls where n.handles_objectapi(cls) diff --git a/python/ql/test/library-tests/types/exceptions/Impossible.ql b/python/ql/test/library-tests/types/exceptions/Impossible.ql index 787ba8898f95..acdcbb8e84fe 100644 --- a/python/ql/test/library-tests/types/exceptions/Impossible.ql +++ b/python/ql/test/library-tests/types/exceptions/Impossible.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from RaisingNode r, ControlFlowNode n, string kind where diff --git a/python/ql/test/library-tests/types/exceptions/LineRaises.ql b/python/ql/test/library-tests/types/exceptions/LineRaises.ql index de8b834e520b..94b54a27198a 100644 --- a/python/ql/test/library-tests/types/exceptions/LineRaises.ql +++ b/python/ql/test/library-tests/types/exceptions/LineRaises.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from RaisingNode r, string type where diff --git a/python/ql/test/library-tests/types/exceptions/Raises.ql b/python/ql/test/library-tests/types/exceptions/Raises.ql index 2415c7079670..e4f9a6664d55 100644 --- a/python/ql/test/library-tests/types/exceptions/Raises.ql +++ b/python/ql/test/library-tests/types/exceptions/Raises.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from PyFunctionObject f, string type where diff --git a/python/ql/test/library-tests/types/exceptions/Reraises.ql b/python/ql/test/library-tests/types/exceptions/Reraises.ql index 699eb325f8cc..8a6ade33d5ab 100644 --- a/python/ql/test/library-tests/types/exceptions/Reraises.ql +++ b/python/ql/test/library-tests/types/exceptions/Reraises.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from ReraisingNode r select r.getLocation().getStartLine(), r, r.getARaisedType().toString() diff --git a/python/ql/test/library-tests/types/exceptions/Viable.ql b/python/ql/test/library-tests/types/exceptions/Viable.ql index bf00a0675d63..589e2630bb91 100644 --- a/python/ql/test/library-tests/types/exceptions/Viable.ql +++ b/python/ql/test/library-tests/types/exceptions/Viable.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from RaisingNode r, ControlFlowNode n, ClassObject ex where r.viableExceptionEdge_objectapi(n, ex) diff --git a/python/ql/test/library-tests/types/properties/Deleters.ql b/python/ql/test/library-tests/types/properties/Deleters.ql index ad99ceb387df..ed98d02b3a85 100644 --- a/python/ql/test/library-tests/types/properties/Deleters.ql +++ b/python/ql/test/library-tests/types/properties/Deleters.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from PythonPropertyObject p select p.toString(), p.getDeleter().toString() diff --git a/python/ql/test/library-tests/types/properties/Getters.ql b/python/ql/test/library-tests/types/properties/Getters.ql index 5f232858696d..d8c54dbda097 100644 --- a/python/ql/test/library-tests/types/properties/Getters.ql +++ b/python/ql/test/library-tests/types/properties/Getters.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from PythonPropertyObject p select p.toString(), p.getGetter().toString() diff --git a/python/ql/test/library-tests/types/properties/PythonProperties.ql b/python/ql/test/library-tests/types/properties/PythonProperties.ql index 858326d6ac0c..4440c6df21e5 100644 --- a/python/ql/test/library-tests/types/properties/PythonProperties.ql +++ b/python/ql/test/library-tests/types/properties/PythonProperties.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from PythonPropertyObject p select p.toString() diff --git a/python/ql/test/library-tests/types/properties/Setters.ql b/python/ql/test/library-tests/types/properties/Setters.ql index 871e6f9145fb..5180f58552a4 100644 --- a/python/ql/test/library-tests/types/properties/Setters.ql +++ b/python/ql/test/library-tests/types/properties/Setters.ql @@ -1,4 +1,5 @@ import python +private import LegacyPointsTo from PythonPropertyObject p select p.toString(), p.getSetter().toString() From 894813257618b366c246199109823ccabe976b15 Mon Sep 17 00:00:00 2001 From: Taus Date: Fri, 31 Oct 2025 14:05:33 +0000 Subject: [PATCH 15/19] Python: Fully remove points-to from `Flow.qll` Gets rid of a bunch of predicates relating to reachability (which depended on the modelling of exceptions, which uses points-to), moving them to `LegacyPointsTo`. In the process, we gained a new class `BasicBlockWithPointsTo`. --- python/ql/lib/LegacyPointsTo.qll | 57 +++++++++++++++++++++++++ python/ql/lib/semmle/python/Flow.qll | 56 +----------------------- python/ql/lib/semmle/python/Metrics.qll | 4 +- python/ql/lib/semmle/python/SSA.qll | 2 +- 4 files changed, 62 insertions(+), 57 deletions(-) diff --git a/python/ql/lib/LegacyPointsTo.qll b/python/ql/lib/LegacyPointsTo.qll index 16d7c7685303..21afebbea5ec 100644 --- a/python/ql/lib/LegacyPointsTo.qll +++ b/python/ql/lib/LegacyPointsTo.qll @@ -107,6 +107,24 @@ class ControlFlowNodeWithPointsTo extends ControlFlowNode { // for that variable. exists(SsaVariable v | v.getAUse() = this | varHasCompletePointsToSet(v)) } + + /** Whether it is unlikely that this ControlFlowNode can be reached */ + predicate unlikelyReachable() { + not start_bb_likely_reachable(this.getBasicBlock()) + or + exists(BasicBlock b | + start_bb_likely_reachable(b) and + not end_bb_likely_reachable(b) and + // If there is an unlikely successor edge earlier in the BB + // than this node, then this node must be unreachable. + exists(ControlFlowNode p, int i, int j | + p.(RaisingNode).unlikelySuccessor(_) and + p = b.getNode(i) and + this = b.getNode(j) and + i < j + ) + ) + } } /** @@ -135,6 +153,45 @@ private predicate varHasCompletePointsToSet(SsaVariable var) { ) } +private predicate start_bb_likely_reachable(BasicBlock b) { + exists(Scope s | s.getEntryNode() = b.getNode(_)) + or + exists(BasicBlock pred | + pred = b.getAPredecessor() and + end_bb_likely_reachable(pred) and + not pred.getLastNode().(RaisingNode).unlikelySuccessor(b) + ) +} + +private predicate end_bb_likely_reachable(BasicBlock b) { + start_bb_likely_reachable(b) and + not exists(ControlFlowNode p, ControlFlowNode s | + p.(RaisingNode).unlikelySuccessor(s) and + p = b.getNode(_) and + s = b.getNode(_) and + not p = b.getLastNode() + ) +} + +/** + * An extension of `BasicBlock` that provides points-to related methods. + */ +class BasicBlockWithPointsTo extends BasicBlock { + /** + * Whether (as inferred by type inference) it is highly unlikely (or impossible) for control to flow from this to succ. + */ + predicate unlikelySuccessor(BasicBlockWithPointsTo succ) { + this.getLastNode().(RaisingNode).unlikelySuccessor(succ.firstNode()) + or + not end_bb_likely_reachable(this) and succ = this.getASuccessor() + } + + /** + * Whether (as inferred by type inference) this basic block is likely to be reachable. + */ + predicate likelyReachable() { start_bb_likely_reachable(this) } +} + /** * An extension of `Expr` that provides points-to predicates. */ diff --git a/python/ql/lib/semmle/python/Flow.qll b/python/ql/lib/semmle/python/Flow.qll index 6574979f9c8c..2994a9108887 100644 --- a/python/ql/lib/semmle/python/Flow.qll +++ b/python/ql/lib/semmle/python/Flow.qll @@ -1,7 +1,6 @@ import python private import semmle.python.internal.CachedStages private import codeql.controlflow.BasicBlock as BB -private import LegacyPointsTo /* * Note about matching parent and child nodes and CFG splitting: @@ -191,24 +190,6 @@ class ControlFlowNode extends @py_flow_node { /** Whether this node is a normal (non-exceptional) exit */ predicate isNormalExit() { py_scope_flow(this, _, 0) or py_scope_flow(this, _, 2) } - /** Whether it is unlikely that this ControlFlowNode can be reached */ - predicate unlikelyReachable() { - not start_bb_likely_reachable(this.getBasicBlock()) - or - exists(BasicBlock b | - start_bb_likely_reachable(b) and - not end_bb_likely_reachable(b) and - // If there is an unlikely successor edge earlier in the BB - // than this node, then this node must be unreachable. - exists(ControlFlowNode p, int i, int j | - p.(RaisingNode).unlikelySuccessor(_) and - p = b.getNode(i) and - this = b.getNode(j) and - i < j - ) - ) - } - /** Whether this strictly dominates other. */ pragma[inline] predicate strictlyDominates(ControlFlowNode other) { @@ -1005,7 +986,8 @@ class BasicBlock extends @py_flow_node { ) } - private ControlFlowNode firstNode() { result = this } + /** Gets the first node in this basic block */ + ControlFlowNode firstNode() { result = this } /** Gets the last node in this basic block */ ControlFlowNode getLastNode() { @@ -1094,15 +1076,6 @@ class BasicBlock extends @py_flow_node { ) } - /** - * Whether (as inferred by type inference) it is highly unlikely (or impossible) for control to flow from this to succ. - */ - predicate unlikelySuccessor(BasicBlock succ) { - this.getLastNode().(RaisingNode).unlikelySuccessor(succ.firstNode()) - or - not end_bb_likely_reachable(this) and succ = this.getASuccessor() - } - /** Holds if this basic block strictly reaches the other. Is the start of other reachable from the end of this. */ cached predicate strictlyReaches(BasicBlock other) { @@ -1113,11 +1086,6 @@ class BasicBlock extends @py_flow_node { /** Holds if this basic block reaches the other. Is the start of other reachable from the end of this. */ predicate reaches(BasicBlock other) { this = other or this.strictlyReaches(other) } - /** - * Whether (as inferred by type inference) this basic block is likely to be reachable. - */ - predicate likelyReachable() { start_bb_likely_reachable(this) } - /** * Gets the `ConditionBlock`, if any, that controls this block and * does not control any other `ConditionBlock`s that control this block. @@ -1145,26 +1113,6 @@ class BasicBlock extends @py_flow_node { } } -private predicate start_bb_likely_reachable(BasicBlock b) { - exists(Scope s | s.getEntryNode() = b.getNode(_)) - or - exists(BasicBlock pred | - pred = b.getAPredecessor() and - end_bb_likely_reachable(pred) and - not pred.getLastNode().(RaisingNode).unlikelySuccessor(b) - ) -} - -private predicate end_bb_likely_reachable(BasicBlock b) { - start_bb_likely_reachable(b) and - not exists(ControlFlowNode p, ControlFlowNode s | - p.(RaisingNode).unlikelySuccessor(s) and - p = b.getNode(_) and - s = b.getNode(_) and - not p = b.getLastNode() - ) -} - private class ControlFlowNodeAlias = ControlFlowNode; final private class FinalBasicBlock = BasicBlock; diff --git a/python/ql/lib/semmle/python/Metrics.qll b/python/ql/lib/semmle/python/Metrics.qll index f36454cccd51..5185d70dc1de 100644 --- a/python/ql/lib/semmle/python/Metrics.qll +++ b/python/ql/lib/semmle/python/Metrics.qll @@ -32,9 +32,9 @@ class FunctionMetrics extends Function { */ int getCyclomaticComplexity() { exists(int e, int n | - n = count(BasicBlock b | b = this.getABasicBlock() and b.likelyReachable()) and + n = count(BasicBlockWithPointsTo b | b = this.getABasicBlock() and b.likelyReachable()) and e = - count(BasicBlock b1, BasicBlock b2 | + count(BasicBlockWithPointsTo b1, BasicBlockWithPointsTo b2 | b1 = this.getABasicBlock() and b1.likelyReachable() and b2 = this.getABasicBlock() and diff --git a/python/ql/lib/semmle/python/SSA.qll b/python/ql/lib/semmle/python/SSA.qll index a139f22dfc6f..fc98e5975fbd 100644 --- a/python/ql/lib/semmle/python/SSA.qll +++ b/python/ql/lib/semmle/python/SSA.qll @@ -92,7 +92,7 @@ class SsaVariable extends @py_ssa_var { } /** Gets the incoming edges for a Phi node, pruned of unlikely edges. */ - private BasicBlock getAPrunedPredecessorBlockForPhi() { + private BasicBlockWithPointsTo getAPrunedPredecessorBlockForPhi() { result = this.getAPredecessorBlockForPhi() and not result.unlikelySuccessor(this.getDefinition().getBasicBlock()) } From c52839b7d5184b865cf0fb5fdc669273630cefd5 Mon Sep 17 00:00:00 2001 From: Taus Date: Fri, 31 Oct 2025 14:22:29 +0000 Subject: [PATCH 16/19] Python: Fix reachability-related test failures --- python/ql/lib/semmle/python/dataflow/old/Implementation.qll | 6 ++++-- python/ql/src/Functions/ConsistentReturns.ql | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/python/ql/lib/semmle/python/dataflow/old/Implementation.qll b/python/ql/lib/semmle/python/dataflow/old/Implementation.qll index eb7e5fdc9a5c..18020c7d9ffa 100644 --- a/python/ql/lib/semmle/python/dataflow/old/Implementation.qll +++ b/python/ql/lib/semmle/python/dataflow/old/Implementation.qll @@ -256,7 +256,7 @@ class TaintTrackingImplementation extends string instanceof TaintTracking::Confi TaintKind kind, string edgeLabel ) { this.unprunedStep(src, node, context, path, kind, edgeLabel) and - node.getBasicBlock().likelyReachable() and + node.getBasicBlock().(BasicBlockWithPointsTo).likelyReachable() and not super.isBarrier(node) and ( not path = TNoAttribute() @@ -684,7 +684,9 @@ private class EssaTaintTracking extends string instanceof TaintTracking::Configu TaintTrackingNode src, PhiFunction defn, TaintTrackingContext context, AttributePath path, TaintKind kind ) { - exists(DataFlow::Node srcnode, BasicBlock pred, EssaVariable predvar, DataFlow::Node phi | + exists( + DataFlow::Node srcnode, BasicBlockWithPointsTo pred, EssaVariable predvar, DataFlow::Node phi + | src = TTaintTrackingNode_(srcnode, context, path, kind, this) and defn = phi.asVariable().getDefinition() and predvar = defn.getInput(pred) and diff --git a/python/ql/src/Functions/ConsistentReturns.ql b/python/ql/src/Functions/ConsistentReturns.ql index 1bc7b5724b36..9beeafc63723 100644 --- a/python/ql/src/Functions/ConsistentReturns.ql +++ b/python/ql/src/Functions/ConsistentReturns.ql @@ -12,6 +12,7 @@ */ import python +private import LegacyPointsTo predicate explicitly_returns_non_none(Function func) { exists(Return return | @@ -21,7 +22,7 @@ predicate explicitly_returns_non_none(Function func) { } predicate has_implicit_return(Function func) { - exists(ControlFlowNode fallthru | + exists(ControlFlowNodeWithPointsTo fallthru | fallthru = func.getFallthroughNode() and not fallthru.unlikelyReachable() ) or From a4720d2cd0af60e62b1a6a9f5a50a77c1c534ee1 Mon Sep 17 00:00:00 2001 From: Taus Date: Fri, 31 Oct 2025 14:56:13 +0000 Subject: [PATCH 17/19] Python: Get rid of points-to from `Definitions.qll` Turns out the `ImportTime` module (despite living in `semmle.python.types` does not actually depend on points-to, so some of the `LegacyPointsTo` imports could be replaced or removed. --- python/ql/lib/LegacyPointsTo.qll | 1 - python/ql/lib/analysis/DefinitionTracking.qll | 1 + python/ql/lib/semmle/python/essa/Definitions.qll | 2 +- python/ql/src/Imports/Cyclic.qll | 1 + python/ql/src/Imports/UnintentionalImport.ql | 1 + python/ql/src/Variables/UndefinedGlobal.ql | 1 + python/ql/src/Variables/UndefinedPlaceHolder.ql | 1 + python/ql/test/library-tests/PointsTo/general/GlobalPointsTo.ql | 1 + 8 files changed, 7 insertions(+), 2 deletions(-) diff --git a/python/ql/lib/LegacyPointsTo.qll b/python/ql/lib/LegacyPointsTo.qll index 21afebbea5ec..29de09cc6c3f 100644 --- a/python/ql/lib/LegacyPointsTo.qll +++ b/python/ql/lib/LegacyPointsTo.qll @@ -33,7 +33,6 @@ import semmle.python.types.FunctionObject import semmle.python.types.ModuleObject import semmle.python.types.Exceptions import semmle.python.types.Properties -import semmle.python.types.ImportTime import semmle.python.types.Descriptors import semmle.python.SelfAttribute diff --git a/python/ql/lib/analysis/DefinitionTracking.qll b/python/ql/lib/analysis/DefinitionTracking.qll index c019e92c0ca3..0d58bd69b7b6 100644 --- a/python/ql/lib/analysis/DefinitionTracking.qll +++ b/python/ql/lib/analysis/DefinitionTracking.qll @@ -4,6 +4,7 @@ import python private import LegacyPointsTo +private import semmle.python.types.ImportTime import IDEContextual private newtype TDefinition = diff --git a/python/ql/lib/semmle/python/essa/Definitions.qll b/python/ql/lib/semmle/python/essa/Definitions.qll index 17b4e622ea13..aca6991b9f69 100644 --- a/python/ql/lib/semmle/python/essa/Definitions.qll +++ b/python/ql/lib/semmle/python/essa/Definitions.qll @@ -11,7 +11,7 @@ import python * Escaping globals -- Global variables that have definitions and at least one of those definitions is in another scope. */ -private import LegacyPointsTo +private import semmle.python.types.ImportTime private import semmle.python.essa.SsaDefinitions /** A source language variable, to be converted into a set of SSA variables. */ diff --git a/python/ql/src/Imports/Cyclic.qll b/python/ql/src/Imports/Cyclic.qll index 720ea8f00481..ad24a08eddd3 100644 --- a/python/ql/src/Imports/Cyclic.qll +++ b/python/ql/src/Imports/Cyclic.qll @@ -1,5 +1,6 @@ import python private import LegacyPointsTo +private import semmle.python.types.ImportTime predicate is_import_time(Stmt s) { not s.getScope+() instanceof Function } diff --git a/python/ql/src/Imports/UnintentionalImport.ql b/python/ql/src/Imports/UnintentionalImport.ql index 7b22865cd89e..db1775a0d41e 100644 --- a/python/ql/src/Imports/UnintentionalImport.ql +++ b/python/ql/src/Imports/UnintentionalImport.ql @@ -14,6 +14,7 @@ import python private import LegacyPointsTo +private import semmle.python.types.ImportTime predicate import_star(ImportStar imp, ModuleValue exporter) { exporter.importedAs(imp.getImportedModuleName()) diff --git a/python/ql/src/Variables/UndefinedGlobal.ql b/python/ql/src/Variables/UndefinedGlobal.ql index bfe816d5c589..2fdf708a2b9f 100644 --- a/python/ql/src/Variables/UndefinedGlobal.ql +++ b/python/ql/src/Variables/UndefinedGlobal.ql @@ -12,6 +12,7 @@ import python private import LegacyPointsTo +private import semmle.python.types.ImportTime import Variables.MonkeyPatched import Loop diff --git a/python/ql/src/Variables/UndefinedPlaceHolder.ql b/python/ql/src/Variables/UndefinedPlaceHolder.ql index 11bf3b6d0bec..4b21e3719770 100644 --- a/python/ql/src/Variables/UndefinedPlaceHolder.ql +++ b/python/ql/src/Variables/UndefinedPlaceHolder.ql @@ -14,6 +14,7 @@ import python import Variables.MonkeyPatched private import LegacyPointsTo +private import semmle.python.types.ImportTime /* Local variable part */ predicate initialized_as_local(PlaceHolder use) { diff --git a/python/ql/test/library-tests/PointsTo/general/GlobalPointsTo.ql b/python/ql/test/library-tests/PointsTo/general/GlobalPointsTo.ql index e90674bab2e3..a0b7e8979f37 100644 --- a/python/ql/test/library-tests/PointsTo/general/GlobalPointsTo.ql +++ b/python/ql/test/library-tests/PointsTo/general/GlobalPointsTo.ql @@ -1,5 +1,6 @@ import python private import LegacyPointsTo +private import semmle.python.types.ImportTime import interesting from int line, ControlFlowNodeWithPointsTo f, Object o, ImportTimeScope n From f7243ee1942740ea210c1a5bf9bfe0ce6e6baf57 Mon Sep 17 00:00:00 2001 From: Taus Date: Fri, 31 Oct 2025 15:52:53 +0000 Subject: [PATCH 18/19] Python: Remove points-to dependency from parts of SSA For whatever reason, the CFG node for exceptions and exception groups was placed with the points-to code. (Probably because a lot of the predicates depended on points-to.) However, as it turned out, two of the SSA modules only depended on non-points-to properties of these nodes, and so it was fairly straightforward to remove the imports of `LegacyPointsTo` for those modules. In the process, I moved the aforementioned CFG node types into `Flow.qll`, and changed the classes in the `Exceptions` module to the `...WithPointsTo` form that we introduced elsewhere. --- python/ql/lib/semmle/python/Flow.qll | 52 +++++++++++++ python/ql/lib/semmle/python/essa/Essa.qll | 1 - .../lib/semmle/python/essa/SsaDefinitions.qll | 1 - .../ql/lib/semmle/python/types/Exceptions.qll | 76 ++++--------------- .../Exceptions/IllegalExceptionHandlerType.ql | 2 +- .../ControlFlow/Exceptions/Handles.ql | 2 +- .../ControlFlow/Exceptions/Handles.ql | 2 +- .../test/library-tests/exceptions/Handles.ql | 2 +- .../library-tests/types/exceptions/Handles.ql | 2 +- 9 files changed, 70 insertions(+), 70 deletions(-) diff --git a/python/ql/lib/semmle/python/Flow.qll b/python/ql/lib/semmle/python/Flow.qll index 2994a9108887..898cd566ab96 100644 --- a/python/ql/lib/semmle/python/Flow.qll +++ b/python/ql/lib/semmle/python/Flow.qll @@ -883,6 +883,58 @@ class StarredNode extends ControlFlowNode { ControlFlowNode getValue() { toAst(result) = toAst(this).(Starred).getValue() } } +/** The ControlFlowNode for an 'except' statement. */ +class ExceptFlowNode extends ControlFlowNode { + ExceptFlowNode() { this.getNode() instanceof ExceptStmt } + + /** + * Gets the type handled by this exception handler. + * `ExceptionType` in `except ExceptionType as e:` + */ + ControlFlowNode getType() { + exists(ExceptStmt ex | + this.getBasicBlock().dominates(result.getBasicBlock()) and + ex = this.getNode() and + result = ex.getType().getAFlowNode() + ) + } + + /** + * Gets the name assigned to the handled exception, if any. + * `e` in `except ExceptionType as e:` + */ + ControlFlowNode getName() { + exists(ExceptStmt ex | + this.getBasicBlock().dominates(result.getBasicBlock()) and + ex = this.getNode() and + result = ex.getName().getAFlowNode() + ) + } +} + +/** The ControlFlowNode for an 'except*' statement. */ +class ExceptGroupFlowNode extends ControlFlowNode { + ExceptGroupFlowNode() { this.getNode() instanceof ExceptGroupStmt } + + /** + * Gets the type handled by this exception handler. + * `ExceptionType` in `except* ExceptionType as e:` + */ + ControlFlowNode getType() { + this.getBasicBlock().dominates(result.getBasicBlock()) and + result = this.getNode().(ExceptGroupStmt).getType().getAFlowNode() + } + + /** + * Gets the name assigned to the handled exception, if any. + * `e` in `except* ExceptionType as e:` + */ + ControlFlowNode getName() { + this.getBasicBlock().dominates(result.getBasicBlock()) and + result = this.getNode().(ExceptGroupStmt).getName().getAFlowNode() + } +} + private module Scopes { private predicate fast_local(NameNode n) { exists(FastLocalVariable v | diff --git a/python/ql/lib/semmle/python/essa/Essa.qll b/python/ql/lib/semmle/python/essa/Essa.qll index 1b83f8df6ac1..384bfd2f91fe 100644 --- a/python/ql/lib/semmle/python/essa/Essa.qll +++ b/python/ql/lib/semmle/python/essa/Essa.qll @@ -6,7 +6,6 @@ import python private import SsaCompute import semmle.python.essa.Definitions private import semmle.python.internal.CachedStages -private import LegacyPointsTo private import semmle.python.essa.SsaDefinitions /** An (enhanced) SSA variable derived from `SsaSourceVariable`. */ diff --git a/python/ql/lib/semmle/python/essa/SsaDefinitions.qll b/python/ql/lib/semmle/python/essa/SsaDefinitions.qll index b263287d05d9..6c87af102fa9 100644 --- a/python/ql/lib/semmle/python/essa/SsaDefinitions.qll +++ b/python/ql/lib/semmle/python/essa/SsaDefinitions.qll @@ -5,7 +5,6 @@ import python private import semmle.python.internal.CachedStages -private import LegacyPointsTo /** Hold if `expr` is a test (a branch) and `use` is within that test */ predicate test_contains(ControlFlowNode expr, ControlFlowNode use) { diff --git a/python/ql/lib/semmle/python/types/Exceptions.qll b/python/ql/lib/semmle/python/types/Exceptions.qll index 5e982aa01346..9863319f3602 100644 --- a/python/ql/lib/semmle/python/types/Exceptions.qll +++ b/python/ql/lib/semmle/python/types/Exceptions.qll @@ -80,7 +80,7 @@ class RaisingNode extends ControlFlowNode { or this.getNode() instanceof Print and result = theIOErrorType() or - exists(ExceptFlowNode except | + exists(ExceptFlowNodeWithPointsTo except | except = this.getAnExceptionalSuccessor() and except.handles_objectapi(result) and result = this.innateException_objectapi() @@ -107,7 +107,7 @@ class RaisingNode extends ControlFlowNode { or this.getNode() instanceof Print and result = ClassValue::ioError() or - exists(ExceptFlowNode except | + exists(ExceptFlowNodeWithPointsTo except | except = this.getAnExceptionalSuccessor() and except.handles(result) and result = this.innateException() @@ -200,8 +200,8 @@ class RaisingNode extends ControlFlowNode { succ = this.getAnExceptionalSuccessor() and ( /* An 'except' that handles raised and there is no more previous handler */ - succ.(ExceptFlowNode).handles_objectapi(raised) and - not exists(ExceptFlowNode other, StmtList s, int i, int j | + succ.(ExceptFlowNodeWithPointsTo).handles_objectapi(raised) and + not exists(ExceptFlowNodeWithPointsTo other, StmtList s, int i, int j | not other = succ and other.handles_objectapi(raised) and s.getItem(i) = succ.getNode() and @@ -211,7 +211,7 @@ class RaisingNode extends ControlFlowNode { ) or /* Any successor that is not an 'except', provided that 'raised' is not handled by a different successor. */ - not this.getAnExceptionalSuccessor().(ExceptFlowNode).handles_objectapi(raised) and + not this.getAnExceptionalSuccessor().(ExceptFlowNodeWithPointsTo).handles_objectapi(raised) and not succ instanceof ExceptFlowNode ) } @@ -223,8 +223,8 @@ class RaisingNode extends ControlFlowNode { succ = this.getAnExceptionalSuccessor() and ( /* An 'except' that handles raised and there is no more previous handler */ - succ.(ExceptFlowNode).handles(raised) and - not exists(ExceptFlowNode other, StmtList s, int i, int j | + succ.(ExceptFlowNodeWithPointsTo).handles(raised) and + not exists(ExceptFlowNodeWithPointsTo other, StmtList s, int i, int j | not other = succ and other.handles(raised) and s.getItem(i) = succ.getNode() and @@ -234,7 +234,7 @@ class RaisingNode extends ControlFlowNode { ) or /* Any successor that is not an 'except', provided that 'raised' is not handled by a different successor. */ - not this.getAnExceptionalSuccessor().(ExceptFlowNode).handles(raised) and + not this.getAnExceptionalSuccessor().(ExceptFlowNodeWithPointsTo).handles(raised) and not succ instanceof ExceptFlowNode ) } @@ -248,7 +248,7 @@ class RaisingNode extends ControlFlowNode { raised.isLegalExceptionType() and raised = this.getARaisedType_objectapi() and this.isExceptionalExit(s) and - not this.getAnExceptionalSuccessor().(ExceptFlowNode).handles_objectapi(raised) + not this.getAnExceptionalSuccessor().(ExceptFlowNodeWithPointsTo).handles_objectapi(raised) } /** @@ -260,7 +260,7 @@ class RaisingNode extends ControlFlowNode { raised.isLegalExceptionType() and raised = this.getARaisedType() and this.isExceptionalExit(s) and - not this.getAnExceptionalSuccessor().(ExceptFlowNode).handles(raised) + not this.getAnExceptionalSuccessor().(ExceptFlowNodeWithPointsTo).handles(raised) } } @@ -368,36 +368,9 @@ predicate scope_raises_unknown(Scope s) { ) } -/** The ControlFlowNode for an 'except' statement. */ -class ExceptFlowNode extends ControlFlowNode { - ExceptFlowNode() { this.getNode() instanceof ExceptStmt } - - /** - * Gets the type handled by this exception handler. - * `ExceptionType` in `except ExceptionType as e:` - */ - ControlFlowNodeWithPointsTo getType() { - exists(ExceptStmt ex | - this.getBasicBlock().dominates(result.getBasicBlock()) and - ex = this.getNode() and - result = ex.getType().getAFlowNode() - ) - } - - /** - * Gets the name assigned to the handled exception, if any. - * `e` in `except ExceptionType as e:` - */ - ControlFlowNode getName() { - exists(ExceptStmt ex | - this.getBasicBlock().dominates(result.getBasicBlock()) and - ex = this.getNode() and - result = ex.getName().getAFlowNode() - ) - } - +class ExceptFlowNodeWithPointsTo extends ControlFlowNodeWithPointsTo { private predicate handledObject_objectapi(Object obj, ClassObject cls, ControlFlowNode origin) { - this.getType().refersTo(obj, cls, origin) + this.(ExceptFlowNode).getType().(ControlFlowNodeWithPointsTo).refersTo(obj, cls, origin) or exists(Object tup | this.handledObject_objectapi(tup, theTupleType(), _) | element_from_tuple_objectapi(tup).refersTo(obj, cls, origin) @@ -407,7 +380,7 @@ class ExceptFlowNode extends ControlFlowNode { private predicate handledObject(Value val, ClassValue cls, ControlFlowNode origin) { val.getClass() = cls and ( - this.getType().pointsTo(val, origin) + this.(ExceptFlowNode).getType().(ControlFlowNodeWithPointsTo).pointsTo(val, origin) or exists(TupleValue tup | this.handledObject(tup, ClassValue::tuple(), _) | val = tup.getItem(_) and origin = val.getOrigin() @@ -452,29 +425,6 @@ class ExceptFlowNode extends ControlFlowNode { } } -/** The ControlFlowNode for an 'except*' statement. */ -class ExceptGroupFlowNode extends ControlFlowNode { - ExceptGroupFlowNode() { this.getNode() instanceof ExceptGroupStmt } - - /** - * Gets the type handled by this exception handler. - * `ExceptionType` in `except* ExceptionType as e:` - */ - ControlFlowNode getType() { - this.getBasicBlock().dominates(result.getBasicBlock()) and - result = this.getNode().(ExceptGroupStmt).getType().getAFlowNode() - } - - /** - * Gets the name assigned to the handled exception, if any. - * `e` in `except* ExceptionType as e:` - */ - ControlFlowNode getName() { - this.getBasicBlock().dominates(result.getBasicBlock()) and - result = this.getNode().(ExceptGroupStmt).getName().getAFlowNode() - } -} - private ControlFlowNodeWithPointsTo element_from_tuple_objectapi(Object tuple) { exists(Tuple t | t = tuple.getOrigin() and result = t.getAnElt().getAFlowNode()) } diff --git a/python/ql/src/Exceptions/IllegalExceptionHandlerType.ql b/python/ql/src/Exceptions/IllegalExceptionHandlerType.ql index b5446dccbfc9..dc1c3f2fa359 100644 --- a/python/ql/src/Exceptions/IllegalExceptionHandlerType.ql +++ b/python/ql/src/Exceptions/IllegalExceptionHandlerType.ql @@ -14,7 +14,7 @@ import python private import LegacyPointsTo -from ExceptFlowNode ex, Value t, ClassValue c, ControlFlowNode origin, string what +from ExceptFlowNodeWithPointsTo ex, Value t, ClassValue c, ControlFlowNode origin, string what where ex.handledException(t, c, origin) and ( diff --git a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql index 60989ff86452..a8bc92db3317 100644 --- a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql +++ b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql @@ -1,6 +1,6 @@ import python private import LegacyPointsTo -from ExceptFlowNode ex, Value val +from ExceptFlowNodeWithPointsTo ex, Value val where ex.handledException(val, _, _) select ex.getLocation().getStartLine(), ex.toString(), val.toString() diff --git a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql index 60989ff86452..a8bc92db3317 100644 --- a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql +++ b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql @@ -1,6 +1,6 @@ import python private import LegacyPointsTo -from ExceptFlowNode ex, Value val +from ExceptFlowNodeWithPointsTo ex, Value val where ex.handledException(val, _, _) select ex.getLocation().getStartLine(), ex.toString(), val.toString() diff --git a/python/ql/test/library-tests/exceptions/Handles.ql b/python/ql/test/library-tests/exceptions/Handles.ql index 60989ff86452..a8bc92db3317 100644 --- a/python/ql/test/library-tests/exceptions/Handles.ql +++ b/python/ql/test/library-tests/exceptions/Handles.ql @@ -1,6 +1,6 @@ import python private import LegacyPointsTo -from ExceptFlowNode ex, Value val +from ExceptFlowNodeWithPointsTo ex, Value val where ex.handledException(val, _, _) select ex.getLocation().getStartLine(), ex.toString(), val.toString() diff --git a/python/ql/test/library-tests/types/exceptions/Handles.ql b/python/ql/test/library-tests/types/exceptions/Handles.ql index e5a217249757..bec8767d6c5e 100644 --- a/python/ql/test/library-tests/types/exceptions/Handles.ql +++ b/python/ql/test/library-tests/types/exceptions/Handles.ql @@ -1,6 +1,6 @@ import python private import LegacyPointsTo -from ExceptFlowNode n, ClassObject cls +from ExceptFlowNodeWithPointsTo n, ClassObject cls where n.handles_objectapi(cls) select n.getLocation().getStartLine(), cls.toString() From 685b2db018ed6043c662c0301179d4ae21ca4b0f Mon Sep 17 00:00:00 2001 From: Taus Date: Fri, 31 Oct 2025 16:16:22 +0000 Subject: [PATCH 19/19] Python: Remove dependence on `Builtins` from attribute module The `Builtins` module is deeply entwined with points-to, so it would be nice to not have this dependence. Happily, the only thing we used `Builtin` for was to get the names of known builtins, and for this we already maintain such a set of names in `dataflow.new.internal.Builtins`. --- .../python/dataflow/new/internal/Attributes.qll | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/Attributes.qll b/python/ql/lib/semmle/python/dataflow/new/internal/Attributes.qll index 42c0c862e89b..e9bcc5e67855 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/Attributes.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/Attributes.qll @@ -1,9 +1,10 @@ /** This module provides an API for attribute reads and writes. */ +private import python import DataFlowUtil import DataFlowPublic private import DataFlowPrivate -private import semmle.python.types.Builtins +private import semmle.python.dataflow.new.internal.Builtins /** * A data flow node that reads or writes an attribute of an object. @@ -134,8 +135,12 @@ private class BuiltInCallNode extends CallNode { BuiltInCallNode() { // TODO disallow instances where the name of the built-in may refer to an in-scope variable of that name. - exists(NameNode id | this.getFunction() = id and id.getId() = name and id.isGlobal()) and - name = any(Builtin b).getName() + exists(NameNode id | + name = Builtins::getBuiltinName() and + this.getFunction() = id and + id.getId() = name and + id.isGlobal() + ) } /** Gets the name of the built-in function that is called at this `CallNode` */