mirror of
https://github.com/github/codeql.git
synced 2026-06-03 04:40:14 +02:00
Preparatory refactor for the shared-CFG dataflow migration. Deprecates the AstNode.getAFlowNode() cached predicate on the public Python QL API and rewrites all ~140 internal callers across lib/, src/, test/, and tools/ from `expr.getAFlowNode() = cfgNode` to `cfgNode.getNode() = expr`, using ControlFlowNode.getNode() which already exists in Flow.qll. The predicate itself is preserved (with a deprecation note pointing at the new pattern) so external users do not experience churn — they can migrate at their own pace and the AST/CFG hierarchies still get the intended untangling once the deprecation eventually elapses. Semantic noop verified by: - All 361 lib/ + src/ queries compile clean. - All 122 ControlFlow + PointsTo library-tests pass. - All 64 dataflow library-tests pass. - All 113 Variables/Exceptions/Expressions/Statements/Functions/Imports/ Security/CWE-798/ModificationOfParameterWithDefault query-tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
106 lines
2.9 KiB
Plaintext
106 lines
2.9 KiB
Plaintext
/**
|
|
* Symbols for cross-project jump-to-definition resolution.
|
|
*/
|
|
|
|
import python
|
|
private import LegacyPointsTo
|
|
|
|
private newtype TSymbol =
|
|
TModule(Module m) or
|
|
TMember(Symbol outer, string part) {
|
|
exists(Object o | outer.resolvesTo() = o |
|
|
o.(ModuleObject).hasAttribute(part)
|
|
or
|
|
o.(ClassObject).hasAttribute(part)
|
|
)
|
|
}
|
|
|
|
/**
|
|
* A "symbol" referencing an object in another module
|
|
* Symbols are represented by the module name and the dotted name by which the
|
|
* object would be referred to in that module.
|
|
* For example for the code:
|
|
* ```
|
|
* class C:
|
|
* def m(self): pass
|
|
* ```
|
|
* If the code were in a module `mod`,
|
|
* then symbol for the method `m` would be "mod/C.m"
|
|
*/
|
|
class Symbol extends TSymbol {
|
|
string toString() {
|
|
exists(Module m | this = TModule(m) and result = m.getName())
|
|
or
|
|
exists(TModule outer, string part |
|
|
this = TMember(outer, part) and
|
|
outer = TModule(_) and
|
|
result = outer.(Symbol).toString() + "/" + part
|
|
)
|
|
or
|
|
exists(TMember outer, string part |
|
|
this = TMember(outer, part) and
|
|
outer = TMember(_, _) and
|
|
result = outer.(Symbol).toString() + "." + part
|
|
)
|
|
}
|
|
|
|
/** Finds the `AstNode` that this `Symbol` refers to. */
|
|
AstNode find() {
|
|
this = TModule(result)
|
|
or
|
|
exists(Symbol s, string name, ControlFlowNode resultCfg |
|
|
this = TMember(s, name) and resultCfg.getNode() = result
|
|
|
|
|
exists(ClassObject cls |
|
|
s.resolvesTo() = cls and
|
|
cls.attributeRefersTo(name, _, resultCfg)
|
|
)
|
|
or
|
|
exists(ModuleObject m |
|
|
s.resolvesTo() = m and
|
|
m.attributeRefersTo(name, _, resultCfg)
|
|
)
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Find the class or module `Object` that this `Symbol` refers to, if
|
|
* this `Symbol` refers to a class or module.
|
|
*/
|
|
Object resolvesTo() {
|
|
this = TModule(result.(ModuleObject).getModule())
|
|
or
|
|
exists(Symbol s, string name, Object o |
|
|
this = TMember(s, name) and
|
|
o = s.resolvesTo() and
|
|
result = attribute_in_scope(o, name)
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Gets the `Module` for the module part of this `Symbol`.
|
|
* For example, this would return the `os` module for the `Symbol` "os/environ".
|
|
*/
|
|
Module getModule() {
|
|
this = TModule(result)
|
|
or
|
|
exists(Symbol outer | this = TMember(outer, _) and result = outer.getModule())
|
|
}
|
|
|
|
/** Gets the `Symbol` that is the named member of this `Symbol`. */
|
|
Symbol getMember(string name) { result = TMember(this, name) }
|
|
}
|
|
|
|
/* Helper for `Symbol`.resolvesTo() */
|
|
private Object attribute_in_scope(Object obj, string name) {
|
|
exists(ClassObject cls | cls = obj |
|
|
cls.lookupAttribute(name) = result and result.(ControlFlowNode).getScope() = cls.getPyClass()
|
|
)
|
|
or
|
|
exists(ModuleObject mod | mod = obj |
|
|
mod.attr(name) = result and
|
|
result.(ControlFlowNode).getScope() = mod.getModule() and
|
|
not result.(ControlFlowNode).isEntryNode()
|
|
)
|
|
}
|