mirror of
https://github.com/github/codeql.git
synced 2026-05-27 01:21:23 +02:00
The legacy CFG emitted two ControlFlowNodes for `x[i] += 42` (one load, one store, with `load.strictlyDominates(store)`). The new CFG collapses them to a single canonical node, mirroring Java's single-`VarAccess` model where `isVarRead`/`isVarWrite` are non-disjoint on the same expression. Reconcile two legacy two-node behaviours with the merged single-node world: 1. `Cfg::ControlFlowNode.isLoad()` no longer excludes augmented targets — both `isLoad` and `isStore` hold on the merged canonical node, matching Java. `NameNode.defines` drops the now-redundant `not isLoad` guard; `Py::Name.defines` already filters by `isDefinition` (Store/Param/AugAssign-target ctx). 2. `LocalFlow::definitionFlowStep` is restricted to NameNode targets, matching legacy ESSA's `assignment_definition` which required `defn.(NameNode).defines(v)`. Subscript and attribute writes (`x[i] = 42`, `obj.attr = 42`) no longer emit a local-flow step *into* the LHS expression — that flow is handled by the AttrWrite and content-flow machinery. This is essential for keeping augmented Subscript/Attribute targets classifiable as `LocalSourceNode` on the read side, which the API graph requires for emitting Use edges. `StoreLoadTest.ql` is updated to filter `isAugLoad` out of the regular `load` tag, mirroring the pre-existing `not isAugStore` filter on the `store` tag so augmented-assignment expectations remain `augload=n augstore=n` (not also `load=n store=n`). Closes the three remaining ApiGraphs library-test failures (`getSubscript.ql` semantically, plus cosmetic toString updates in `ModuleImportWithDots.ql` and `test_crosstalk.ql`). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
46 lines
1.4 KiB
Plaintext
46 lines
1.4 KiB
Plaintext
/**
|
|
* Inline-expectations test for the store/load/delete/parameter
|
|
* classification predicates on the new-CFG facade.
|
|
*
|
|
* Each tag fires when the corresponding predicate (`isLoad`,
|
|
* `isStore`, `isDelete`, `isParameter`, `isAugLoad`, `isAugStore`)
|
|
* holds on the canonical CFG node wrapping a `Py::Name` with the
|
|
* given identifier.
|
|
*
|
|
* For subscript / attribute stores the tag fires on the Subscript /
|
|
* Attribute node itself, with `value` set to the rightmost identifier
|
|
* (the attribute name for `Attribute`, the index expression's textual
|
|
* form for `Subscript`).
|
|
*/
|
|
|
|
import python
|
|
import semmle.python.controlflow.internal.Cfg as Cfg
|
|
import utils.test.InlineExpectationsTest
|
|
|
|
module StoreLoadTest implements TestSig {
|
|
string getARelevantTag() { result = ["load", "store", "delete", "param", "augload", "augstore"] }
|
|
|
|
predicate hasActualResult(Location location, string element, string tag, string value) {
|
|
exists(Cfg::NameNode n |
|
|
location = n.getLocation() and
|
|
element = n.toString() and
|
|
value = n.getId() and
|
|
(
|
|
n.isLoad() and not n.isAugLoad() and tag = "load"
|
|
or
|
|
n.isStore() and not n.isAugStore() and tag = "store"
|
|
or
|
|
n.isDelete() and tag = "delete"
|
|
or
|
|
n.isParameter() and tag = "param"
|
|
or
|
|
n.isAugLoad() and tag = "augload"
|
|
or
|
|
n.isAugStore() and tag = "augstore"
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
import MakeTest<StoreLoadTest>
|