Python: Remove points-to from Expr

This commit is contained in:
Taus
2025-10-30 11:52:39 +00:00
parent b434ce460e
commit b93ce98612
35 changed files with 164 additions and 119 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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'"

View File

@@ -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() }
}

View File

@@ -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` */

View File

@@ -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
)
)

View File

@@ -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
)
)
}

View File

@@ -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

View File

@@ -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

View File

@@ -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())
}

View File

@@ -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

View File

@@ -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())
)
}

View File

@@ -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)
|

View File

@@ -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

View File

@@ -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 */

View File

@@ -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
)

View File

@@ -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

View File

@@ -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()

View File

@@ -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)
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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()
|

View File

@@ -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()

View File

@@ -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()
)
}

View File

@@ -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."

View File

@@ -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)
}

View File

@@ -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())
)
}

View File

@@ -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(), _))

View File

@@ -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
(

View File

@@ -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()

View File

@@ -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()