Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
120 commits
Select commit Hold shift + click to select a range
c48d63f
Python: First draft of ADT based objects and attendant points-to.
markshannon Mar 19, 2019
051683f
Python: Break-up internal object modules.
markshannon Mar 19, 2019
5a46df2
Python: Add ADTs for ints and strings. Add some global data-flow.
markshannon Mar 19, 2019
bf692f4
Python: Add better class support, including inheritance.
markshannon Mar 20, 2019
39b9723
Python: Add support for bound-methods.
markshannon Mar 20, 2019
ec151e9
Python points-to: Convert two pairs of predicates to methods on boole…
markshannon Mar 20, 2019
ce9d0f1
Python points-to: Add support for some more ESSA definitions.
markshannon Mar 21, 2019
84c9866
Python points-to: Add generic instances and handle returns for builti…
markshannon Mar 21, 2019
e3ed8c6
Python points-to: Simplify handling of booleans and comparisons.
markshannon Mar 21, 2019
aa30745
Python points-to: Further types and flow.
markshannon Mar 21, 2019
dd83149
Python points-to: Port old API classes to use new points-to.
markshannon Mar 22, 2019
12853cc
Python points-to: Add support for tuples.
markshannon Mar 25, 2019
85a9016
Python points-to: make 'self' instances distinct from other instances.
markshannon Mar 25, 2019
48297e2
Python points-to: Improve handling of 'type' object.
markshannon Mar 25, 2019
f5c3242
Python points-to: Handle list, dict and float literals as instances.
markshannon Mar 25, 2019
dbf228d
Python points-to: Better handling of *args, **kwargs and procedures.
markshannon Mar 25, 2019
0b0a633
Python points-to: Support descriptor protocols, particularly functions.
markshannon Mar 25, 2019
e9f58ba
Python: refactor ConstantObjects.
markshannon Mar 27, 2019
931100c
Python points-to: Add float objects for better backwards compatibility.
markshannon Mar 27, 2019
d3762ac
Rename 'points_to' to 'pointsTo'.
markshannon Mar 27, 2019
f7edbcc
Python points-to: Clean up interface, and deprecate old interface.
markshannon Mar 27, 2019
610a35c
Python points-to: Improve backwards compatibility for comparisons.
markshannon Mar 28, 2019
8af6cb6
Python points-to: Use objects, not booleans when doing evaluation of …
markshannon Mar 28, 2019
23ca403
Python points-to: Understand callable and hasattr.
markshannon Mar 28, 2019
54c27e1
Python points-to: Various minor performance tweaks.
markshannon Mar 28, 2019
ef0a6b6
Python points-to: Rationalize handling of expressions and conditions.…
markshannon Apr 2, 2019
162bf51
Python points-to: Assorted improvements to performance and better com…
markshannon Apr 4, 2019
31a95ce
Python points-to: Use strongly typed version of CfgOrigin.
markshannon Apr 4, 2019
3c30480
Python: Extend API a bit.
markshannon Apr 5, 2019
782311f
Python: Update taint-tracking to use new points-to API.
markshannon Apr 5, 2019
fc2c46f
Python: Fix error in update Module to use new points-to API.
markshannon Apr 5, 2019
662aedc
Python points-to: Fix up module attributes and classmethods.
markshannon Apr 8, 2019
f543adc
Python points-to: Fix up matching arguments to parameters.
markshannon Apr 8, 2019
b47c2dd
Python remove old MRO module and rename MRO2 to MRO.
markshannon Apr 8, 2019
5644072
Python points-to: make sure builtin tuples are visible.
markshannon Apr 8, 2019
0b2421e
Python points-to. Tidy up a bit.
markshannon Apr 8, 2019
55eac7d
Python points-to: Fix up handling of recursive 'from ... import *'.
markshannon Apr 9, 2019
b8fb3e3
Python points-to: Distinguish between class attribute access and look…
markshannon Apr 9, 2019
9af7071
Python points-to: track return values from builtin methods.
markshannon Apr 9, 2019
03159bb
Python points-to: Track 'unknown' value through simple iteration.
markshannon Apr 9, 2019
e21a863
Python points-to: Update sanity check.
markshannon Apr 9, 2019
a442695
Python points-to: Improve handling of len(), sequences and comparisons.
markshannon Apr 10, 2019
e82b2c4
Python: Update test to use new API.
markshannon Apr 10, 2019
4a03fd0
Update test to reflect new true positive.
markshannon Apr 10, 2019
53f8591
Python points-to: Fix attribute lookup for packages.
markshannon Apr 11, 2019
3b42f3c
Python points-to/taint-tracking: Fix up flow into __init__ methods.
markshannon Apr 11, 2019
ec08041
Python points-to: Assorted tweaks to get nore tests passing.
markshannon Apr 11, 2019
62e0518
Python points-to: Add property objects.
markshannon Apr 12, 2019
46b9ef7
Python points-to: Fix up neverReturns() and return value of __import_…
markshannon Apr 12, 2019
90bbfd3
Python: Add library tests for django.
markshannon Apr 12, 2019
9d40a6c
Python points-to: restore getArgumentForCall() API method.
markshannon Apr 15, 2019
06ab671
Python points-to. Fix descriptor behviour of Python functions.
markshannon Apr 15, 2019
2e6c3c9
Python points-to: Support classes created dynamically as instances of…
markshannon Apr 15, 2019
cd34e23
Python points-to: Bring attribute points-to to effective parity with …
markshannon Apr 15, 2019
dffbf69
Python points-to: improve performance.
markshannon Apr 16, 2019
989d587
Python points-to: Fix support for backwards compatible extensions.
markshannon Apr 17, 2019
2d4f64f
Python legacy objects: fix function/method call.
markshannon Apr 17, 2019
ddc4ada
Python points-to: Handle subclassing of ABCs.
markshannon Apr 17, 2019
4145b19
Python points-to: update some test results.
markshannon Apr 17, 2019
2aa967a
Remove redundant tests.
markshannon Apr 17, 2019
2ea204f
Python points-to: Fix up failedInference predicate.
markshannon Apr 17, 2019
96eaf81
Python: Fix up state-tracking library.
markshannon Apr 17, 2019
8a2fb54
Python points-to. Track bitwise or-ing of small integer flags.
markshannon Apr 17, 2019
f51a2d9
Python points-to: Fix up test-evaluate for ABCs and tests involving t…
markshannon Apr 17, 2019
5ad731a
Python points-to. Fix handling of six.add_metaclass.
markshannon Apr 24, 2019
674a3da
Python points-to: Importing from 'unknown' gives 'unknown'.
markshannon Apr 24, 2019
3bb61e7
Python points-to: Improve handling of subscripts and sequence inequal…
markshannon Apr 24, 2019
48c0cbe
Python: improve handling of __all__
markshannon Apr 24, 2019
abf0347
Python points-to: Split strings into bytes and unicode.
markshannon Apr 24, 2019
5551143
Python points-to. Don't let unknown values escape refersTo().
markshannon Apr 29, 2019
6a5ec51
Update IsComparisons.qll to account for not tracking attributes in de…
markshannon Apr 29, 2019
65a30ab
Adjust a couple of query tests to work with latest points-to.
markshannon Apr 29, 2019
3ca4524
Python points-to: Improve handling of __call__() a bit.
markshannon Apr 29, 2019
dfc0a80
Python points-to: Handle old-style classes correctly.
markshannon Apr 29, 2019
15a7ac3
Python: update failed inference query to use latest points-to.
markshannon Apr 29, 2019
d44ce4f
Python points-to: Performance improvement.
markshannon Apr 29, 2019
92d0aef
Rename super_() to superType() for better consistency.
markshannon May 9, 2019
93f0b8f
Python points-to: Fix up support for six.add_metaclass()
markshannon May 9, 2019
3986159
Python points-to: Fix up handiling of metaclasses, new-style and type…
markshannon May 10, 2019
2db0bd9
Python: Remove obsolete tests.
markshannon May 10, 2019
992ee2f
Python points-to: Fix up some test results.
markshannon May 10, 2019
76c43b4
Python points-to: Improve handling of attributes.
markshannon May 10, 2019
8b28105
Python points-to: update some more test results.
markshannon May 10, 2019
a1bf071
Python points-to: Fix getattr() points-to.
markshannon May 10, 2019
80f6883
Python points-to: Update test results.
markshannon May 10, 2019
315fe0a
Python points-to: Update an expected file.
markshannon May 10, 2019
7244b9f
Python points-to: Update some more expected test results.
markshannon May 13, 2019
beebd0e
Python points-to: Be more specific when describing inheritance analys…
markshannon May 13, 2019
d74c765
Python points-to: Don't track non-descriptor class attributes on inst…
markshannon May 13, 2019
2905737
Python points-to: Fix analysis of zero-arg super().
markshannon May 13, 2019
0491fe1
Python points-to: Update 'analysis' query test results.
markshannon May 13, 2019
26044f2
Python points-to: Fix up tuple inequality analysis.
markshannon May 13, 2019
1f00c3b
Python points-to: Fix up metaclass determination for Python 2.
markshannon May 13, 2019
33043d6
Python: update exptected test results.
markshannon May 13, 2019
5f9a807
Python points-to: Fix handling of builtin-method objects.
markshannon May 13, 2019
972ac0f
Python: Update test result.
markshannon May 13, 2019
a03e101
Python points-to: Improve performance.
markshannon May 13, 2019
1c20336
Python points-to. Fix attribute lookup for type.
markshannon May 13, 2019
a8dc290
Python: Update test results.
markshannon May 13, 2019
a5ff527
Python: Remove test due to instability across minor versions.
markshannon May 14, 2019
0afcb11
Python points-to: Make sure reachability can skip over if-statements.
markshannon May 14, 2019
8f74f91
Python points-to: Speed up call-points-to.
markshannon May 14, 2019
b10a7cd
Python points-to: Make behviour of instances more consistent.
markshannon May 14, 2019
bf78c62
Python points-to: Add objects representing missing modules and their …
markshannon Apr 26, 2019
2b72a50
Python points-to: Fix up re extension.
markshannon May 15, 2019
d6d72dc
Python: Account for --respect-init when determining module name.
markshannon May 16, 2019
2f940d0
Python points-to: Fully document object classes.
markshannon May 16, 2019
8558cb3
Python points-to: Update Overview.qll to reflect new object model.
markshannon May 16, 2019
685826e
Python points-to: Prevent bad magic.
markshannon May 17, 2019
f057d5c
Python: Speed up MRO calculation a bit.
markshannon May 14, 2019
1018f27
Python points-to: Add more comments about TObject and ObjectInternal.
markshannon May 22, 2019
e161488
Python points-to. Improve API bey renaming a couple of methods and cl…
markshannon May 22, 2019
66e6461
Python points-to: Improve qldoc and internal API a bit.
markshannon May 28, 2019
3adaf07
Python points-to: Make purpose of '$' variable explicit.
markshannon May 28, 2019
77c508f
Python points-to: More comment clarifications and typo fixes.
markshannon May 28, 2019
7181a02
Python points-to: Update expected results to account for fixed tuple …
markshannon May 28, 2019
1ed3e5d
Python points-to: Fix ordering of string constants.
markshannon May 29, 2019
71ae61c
Python points-to: Remove duplicate import.
markshannon May 29, 2019
6689994
Python points-to: Minor refactoring for clarity.
markshannon May 30, 2019
8e2d6c4
Python points-to: Simplify logic w.r.t. comparisons.
markshannon May 30, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion python/ql/src/Exceptions/UnguardedNextInGenerator.ql
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ FunctionObject iter() {
result = Object::builtin("iter")
}

FunctionObject next() {
BuiltinFunctionObject next() {
result = Object::builtin("next")
}

Expand Down
10 changes: 8 additions & 2 deletions python/ql/src/Expressions/IsComparisons.qll
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,14 @@ predicate invalid_portable_is_comparison(Compare comp, Cmpop op, ClassObject cls
/* OK to use 'is' when comparing items from a known set of objects */
not exists(Expr left, Expr right, Object obj |
comp.compares(left, op, right) and
left.refersTo(obj) and right.refersTo(obj) and
exists(ImmutableLiteral il | il.getLiteralObject() = obj)
exists(ImmutableLiteral il | il.getLiteralObject() = obj) |
left.refersTo(obj) and right.refersTo(obj)
or
/* Simple constant in module, probably some sort of sentinel */
exists(AstNode origin |
not left.refersTo(_) and right.refersTo(obj, origin) and
origin.getScope().getEnclosingModule() = comp.getScope().getEnclosingModule()
)
)
and
/* OK to use 'is' when comparing with a member of an enum */
Expand Down
8 changes: 4 additions & 4 deletions python/ql/src/analysis/CallGraphEfficiency.ql
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import semmle.python.pointsto.PointsToContext

from int total_facts, int total_size, int depth, float efficiency
where
total_facts = strictcount(ControlFlowNode call, FunctionObject func |
total_facts = strictcount(ControlFlowNode call, CallableValue func |
exists(PointsToContext ctx |
call = PointsTo::get_a_call(func, ctx) and
call = func.getACall(ctx) and
depth = ctx.getDepth()
)
)
and
total_size = strictcount(ControlFlowNode call, FunctionObject func, PointsToContext ctx |
call = PointsTo::get_a_call(func, ctx) and
total_size = strictcount(ControlFlowNode call, CallableValue func, PointsToContext ctx |
call = func.getACall(ctx) and
depth = ctx.getDepth()
)
and
Expand Down
10 changes: 5 additions & 5 deletions python/ql/src/analysis/CallGraphMarginalEfficiency.ql
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ import semmle.python.pointsto.PointsToContext

from int total_facts, int total_size, int depth, float efficiency
where
total_facts = strictcount(ControlFlowNode call, FunctionObject func |
total_facts = strictcount(ControlFlowNode call, CallableValue func |
exists(PointsToContext ctx |
call = PointsTo::get_a_call(func, ctx) and
call = func.getACall(ctx) and
depth = ctx.getDepth()
and not
exists(PointsToContext shallower |
call = PointsTo::get_a_call(func, shallower) and
call = func.getACall(shallower) and
shallower.getDepth() < depth
)
)
)
and
total_size = strictcount(ControlFlowNode call, FunctionObject func, PointsToContext ctx |
call = PointsTo::get_a_call(func, ctx) and
total_size = strictcount(ControlFlowNode call, CallableValue func, PointsToContext ctx |
call = func.getACall(ctx) and
depth = ctx.getDepth()
)
and
Expand Down
2 changes: 1 addition & 1 deletion python/ql/src/analysis/ContextMarginalEfficiency.ql
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ total_size = strictcount(ControlFlowNode f, Object value, ClassObject cls, Point
)
and
efficiency = 100.0 * total_facts / total_size
select depth, total_facts, total_size, efficiency
select depth, total_facts, total_size, efficiency
4 changes: 2 additions & 2 deletions python/ql/src/analysis/FailedInference.ql
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import python
import semmle.python.pointsto.PointsTo

from ClassObject cls, string reason
from ClassValue cls, string reason

where
PointsTo::Types::failed_inference(cls, reason)
Types::failedInference(cls, reason)

select cls, reason

5 changes: 3 additions & 2 deletions python/ql/src/analysis/KeyPointsToFailure.ql
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
*/

import python
import semmle.python.pointsto.PointsTo

predicate points_to_failure(Expr e) {
exists(ControlFlowNode f |
exists(ControlFlowNode f |
f = e.getAFlowNode() |
not f.refersTo(_)
not PointsTo::pointsTo(f, _, _, _)
)
}

Expand Down
2 changes: 1 addition & 1 deletion python/ql/src/analysis/Pruned.ql
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ from int size

where
size = count(ControlFlowNode f |
not PointsTo::Test::reachableBlock(f.getBasicBlock(), _)
not PointsToInternal::reachableBlock(f.getBasicBlock(), _)
)


Expand Down
1 change: 1 addition & 0 deletions python/ql/src/python.qll
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@ import semmle.dataflow.SSA
import semmle.python.pointsto.Base
import semmle.python.pointsto.Context
import semmle.python.pointsto.CallGraph
import semmle.python.objects.ObjectAPI

import site
8 changes: 8 additions & 0 deletions python/ql/src/semmle/dataflow/SSA.qll
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,14 @@ class EssaVariable extends TEssaDefinition {
result = this.getDefinition().getScope()
}

/** Holds if this the meta-variable for a scope.
* This is used to attach attributes for undeclared variables implicitly
* defined by `from ... import *` and the like.
*/
predicate isMetaVariable() {
this.getName() = "$"
}

}

/* Helper for location_string
Expand Down
41 changes: 23 additions & 18 deletions python/ql/src/semmle/python/Exprs.qll
Original file line number Diff line number Diff line change
Expand Up @@ -78,37 +78,42 @@ class Expr extends Expr_, AstNode {
* NOTE: For complex dataflow, involving multiple stages of points-to analysis, it may be more precise to use
* `ControlFlowNode.refersTo(...)` instead.
*/
predicate refersTo(Object value, ClassObject cls, AstNode origin) {
not py_special_objects(cls, "_semmle_unknown_type")
and
not value = unknownValue()
and
PointsTo::points_to(this.getAFlowNode(), _, value, cls, origin.getAFlowNode())
predicate refersTo(Object obj, ClassObject cls, AstNode origin) {
this.refersTo(_, obj, cls, origin)
}

/** Gets what this expression might "refer-to" in the given `context`.
*/
predicate refersTo(Context context, Object value, ClassObject cls, AstNode origin) {
not py_special_objects(cls, "_semmle_unknown_type")
and
PointsTo::points_to(this.getAFlowNode(), context, value, cls, origin.getAFlowNode())
predicate refersTo(Context context, Object obj, ClassObject cls, AstNode origin) {
exists(Value value, ControlFlowNode cfgorigin |
PointsTo::pointsTo(this.getAFlowNode(), context, value, cfgorigin) and
origin.getAFlowNode() = cfgorigin and
cls = value.getClass().getSource() |
if exists(value.getSource()) then
obj = value.getSource()
else
obj = cfgorigin
)
}

/** Whether 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.
*/
predicate refersTo(Object value, AstNode origin) {
PointsTo::points_to(this.getAFlowNode(), _, value, _, origin.getAFlowNode())
and
not value = unknownValue()
predicate refersTo(Object obj, AstNode origin) {
exists(Value value, ControlFlowNode cfgorigin |
PointsTo::pointsTo(this.getAFlowNode(), _, value, cfgorigin) and
origin.getAFlowNode() = cfgorigin and
if exists(value.getSource()) then
obj = value.getSource()
else
obj = cfgorigin
)
}

/** Equivalent to `this.refersTo(value, _)` */
predicate refersTo(Object value) {
PointsTo::points_to(this.getAFlowNode(), _, value, _, _)
and
not value = unknownValue()
predicate refersTo(Object obj) {
this.refersTo(obj, _)
}

}
Expand Down
98 changes: 77 additions & 21 deletions python/ql/src/semmle/python/Flow.qll
Original file line number Diff line number Diff line change
Expand Up @@ -212,47 +212,55 @@ class ControlFlowNode extends @py_flow_node {
py_scope_flow(this, _, -1)
}

/** Use ControlFlowNode.refersTo() instead. */
deprecated Object pointsTo() {
this.refersTo(result)
/** The value that this ControlFlowNode points-to. */
predicate pointsTo(Value value) {
this.pointsTo(_, value, _)
}

/** Gets a value that this ControlFlowNode may points-to. */
Value inferredValue() {
this.pointsTo(_, result, _)
}

/** The value and origin that this ControlFlowNode points-to. */
predicate pointsTo(Value value, ControlFlowNode origin) {
this.pointsTo(_, value, origin)
}

/** 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.
*/
predicate refersTo(Object value, ClassObject cls, ControlFlowNode origin) {
not py_special_objects(cls, "_semmle_unknown_type")
and
not value = unknownValue()
and
PointsTo::points_to(this, _, value, cls, origin)
predicate refersTo(Object obj, ClassObject cls, ControlFlowNode origin) {
this.refersTo(_, obj, cls, origin)
}

/** Gets what this expression might "refer-to" in the given `context`.
*/
predicate refersTo(Context context, Object value, ClassObject cls, ControlFlowNode origin) {
not py_special_objects(cls, "_semmle_unknown_type")
and
PointsTo::points_to(this, context, value, cls, origin)
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.
*/
predicate refersTo(Object value, ControlFlowNode origin) {
PointsTo::points_to(this, _, value, _, origin)
and
not value = unknownValue()
predicate refersTo(Object obj, ControlFlowNode origin) {
not obj = unknownValue() and
PointsTo::points_to(this, _, obj, _, origin)
}

/** Equivalent to `this.refersTo(value, _)` */
predicate refersTo(Object value) {
PointsTo::points_to(this, _, value, _, _)
and
not value = unknownValue()
predicate refersTo(Object obj) {
this.refersTo(obj, _)
}

/** Gets the basic block containing this flow node */
Expand Down Expand Up @@ -460,6 +468,16 @@ class CallNode extends ControlFlowNode {

override Call getNode() { result = super.getNode() }

predicate isDecoratorCall() {
exists(FunctionExpr func |
this.getNode() = func.getADecoratorCall()
)
or
exists(ClassExpr cls |
this.getNode() = cls.getADecoratorCall()
)
}

}

/** A control flow corresponding to an attribute expression, such as `value.attr` */
Expand Down Expand Up @@ -643,6 +661,16 @@ class BinaryExprNode extends ControlFlowNode {
result = this.getNode().getOp()
}

/** Whether left and right are a pair of operands for this binary expression */
predicate operands(ControlFlowNode left, Operator op, ControlFlowNode right) {
exists(BinaryExpr b, Expr eleft, Expr eright |
this.getNode() = b and left.getNode() = eleft and right.getNode() = eright |
eleft = b.getLeft() and eright = b.getRight() and op = b.getOp()
) and
left.getBasicBlock().dominates(this.getBasicBlock()) and
right.getBasicBlock().dominates(this.getBasicBlock())
}

}

/** A control flow node corresponding to a boolean shortcut (and/or) operation */
Expand Down Expand Up @@ -986,6 +1014,18 @@ class BasicBlock extends @py_flow_node {
result = this.getLastNode().getAFalseSuccessor().getBasicBlock()
}

/** Gets an unconditional successor to this basic block */
BasicBlock getAnUnconditionalSuccessor() {
result = this.getASuccessor() and
not result = this.getATrueSuccessor() and
not result = this.getAFalseSuccessor()
}

/** Gets an exceptional successor to this basic block */
BasicBlock getAnExceptionalSuccessor() {
result = this.getLastNode().getAnExceptionalSuccessor().getBasicBlock()
}

/** Gets the scope of this block */
pragma [nomagic] Scope getScope() {
exists(ControlFlowNode n |
Expand Down Expand Up @@ -1037,6 +1077,22 @@ class BasicBlock extends @py_flow_node {
not result.(ConditionBlock).controls(this, _)
}

/** Holds if flow from this BasicBlock always reaches `succ`
*/
predicate alwaysReaches(BasicBlock succ) {
succ = this
or
strictcount(this.getASuccessor()) = 1
and succ = this.getASuccessor()
or
forex(BasicBlock immsucc |
immsucc = this.getASuccessor()
|
immsucc.alwaysReaches(succ)
)

}

}

private predicate start_bb_likely_reachable(BasicBlock b) {
Expand Down
2 changes: 1 addition & 1 deletion python/ql/src/semmle/python/Import.qll
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class Alias extends Alias_ {
private predicate valid_module_name(string name) {
exists(Module m | m.getName() = name)
or
exists(Builtin cmod | cmod.getClass() = theModuleType().asBuiltin() and cmod.getName() = name)
exists(Builtin cmod | cmod.getClass() = Builtin::special("ModuleType") and cmod.getName() = name)
}

/** An artificial expression representing an import */
Expand Down
Loading