Add and use WriteNode.writesElementPreUpdate

This commit is contained in:
Owen Mansel-Chan
2025-09-29 17:20:11 +01:00
parent 6fcd35885e
commit 59e3c14a5e
2 changed files with 17 additions and 10 deletions

View File

@@ -188,9 +188,7 @@ module ControlFlow {
* initialized.
*/
predicate writesElement(DataFlow::Node base, DataFlow::Node index, DataFlow::Node rhs) {
exists(DataFlow::Node b |
this.writesElementInsn(b.asInstruction(), index.asInstruction(), rhs.asInstruction())
|
exists(DataFlow::Node b | this.writesElementPreUpdate(b, index, rhs) |
this.isInitialization() and base = b
or
not this.isInitialization() and
@@ -198,6 +196,21 @@ module ControlFlow {
)
}
/**
* Holds if this node sets the value of element `index` on `base` (or its implicit dereference)
* to `rhs`.
*
* For example, for the assignment `xs[i] = v`, `base` is the post-update node of the data-flow
* node corresponding to `xs` or (if `xs` is a pointer) the implicit dereference `*xs`, `index`
* is the data-flow node corresponding to `i`, and `rhs` is the data-flow node corresponding to
* `base`. If this `WriteNode` corresponds to the initialization of an array/slice/map then
* there is no need for a post-update node and `base` is the array/slice/map literal being
* initialized.
*/
predicate writesElementPreUpdate(DataFlow::Node base, DataFlow::Node index, DataFlow::Node rhs) {
this.writesElementInsn(base.asInstruction(), index.asInstruction(), rhs.asInstruction())
}
private predicate writesElementInsn(
IR::Instruction base, IR::Instruction index, IR::Instruction rhs
) {

View File

@@ -52,13 +52,7 @@ module NetHttp {
MapWrite() {
this.getType().hasQualifiedName("net/http", "Header") and
exists(Write write, DataFlow::Node base |
write.writesElement(base, index, rhs) and
// The following line works because `Http::HeaderWrite::Range` extends
// `DataFlow::ExprNode`, which is incompatible with
// `DataFlow::PostUpdateNode`.
this = [base, base.(DataFlow::PostUpdateNode).getPreUpdateNode()]
)
any(Write write).writesElementPreUpdate(this, index, rhs)
}
override DataFlow::Node getName() { result = index }