mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
Python: Allow import resolution with recursive phi/refine steps
This commit is contained in:
@@ -64,6 +64,19 @@ private import semmle.python.dataflow.new.internal.DataFlowPrivate
|
|||||||
* `bar` subpackage.
|
* `bar` subpackage.
|
||||||
*/
|
*/
|
||||||
module ImportResolution {
|
module ImportResolution {
|
||||||
|
/**
|
||||||
|
* Holds if there is an ESSA step from `defFrom` to `defTo`, which should be allowed
|
||||||
|
* for import resolution.
|
||||||
|
*/
|
||||||
|
private predicate allowedEssaImportStep(EssaDefinition defFrom, EssaDefinition defTo) {
|
||||||
|
// to handle definitions guarded by if-then-else
|
||||||
|
defFrom = defTo.(PhiFunction).getAnInput()
|
||||||
|
or
|
||||||
|
// refined variable
|
||||||
|
// example: https://github.com/nvbn/thefuck/blob/ceeaeab94b5df5a4fe9d94d61e4f6b0bbea96378/thefuck/utils.py#L25-L45
|
||||||
|
defFrom = defTo.(EssaNodeRefinement).getInput().getDefinition()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if the module `m` defines a name `name` by assigning `defn` to it. This is an
|
* Holds if the module `m` defines a name `name` by assigning `defn` to it. This is an
|
||||||
* overapproximation, as `name` may not in fact be exported (e.g. by defining an `__all__` that does
|
* overapproximation, as `name` may not in fact be exported (e.g. by defining an `__all__` that does
|
||||||
@@ -74,15 +87,7 @@ module ImportResolution {
|
|||||||
exists(EssaVariable v, EssaDefinition essaDef |
|
exists(EssaVariable v, EssaDefinition essaDef |
|
||||||
v.getName() = name and
|
v.getName() = name and
|
||||||
v.getAUse() = ImportStar::getStarImported*(m).getANormalExit() and
|
v.getAUse() = ImportStar::getStarImported*(m).getANormalExit() and
|
||||||
(
|
allowedEssaImportStep*(essaDef, v.getDefinition())
|
||||||
essaDef = v.getDefinition()
|
|
||||||
or
|
|
||||||
// to handle definitions guarded by if-then-else
|
|
||||||
essaDef = v.getDefinition().(PhiFunction).getAnInput()
|
|
||||||
or
|
|
||||||
// refined variable
|
|
||||||
essaDef = v.getDefinition().(EssaNodeRefinement).getInput().getDefinition()
|
|
||||||
)
|
|
||||||
|
|
|
|
||||||
defn.getNode() = essaDef.(AssignmentDefinition).getValue()
|
defn.getNode() = essaDef.(AssignmentDefinition).getValue()
|
||||||
or
|
or
|
||||||
|
|||||||
@@ -95,10 +95,10 @@ check("if_then_else_defined", if_then_else_defined, "if_defined", globals()) #$
|
|||||||
|
|
||||||
# check that refined definitions are handled correctly
|
# check that refined definitions are handled correctly
|
||||||
import refined # $ imports=refined as=refined
|
import refined # $ imports=refined as=refined
|
||||||
check("refined.SOURCE", refined.SOURCE, refined.SOURCE, globals()) #$ MISSING: prints=SOURCE
|
check("refined.SOURCE", refined.SOURCE, refined.SOURCE, globals()) #$ prints=SOURCE
|
||||||
|
|
||||||
import if_then_else_refined # $ imports=if_then_else_refined as=if_then_else_refined
|
import if_then_else_refined # $ imports=if_then_else_refined as=if_then_else_refined
|
||||||
check("if_then_else_refined.src", if_then_else_refined.src, if_then_else_refined.src, globals()) #$ MISSING: prints=SOURCE
|
check("if_then_else_refined.src", if_then_else_refined.src, if_then_else_refined.src, globals()) #$ prints=SOURCE
|
||||||
|
|
||||||
exit(__file__)
|
exit(__file__)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user