From 6c792e69b341de543d31598c63acbc8fa4cba429 Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Wed, 11 Mar 2026 13:53:24 -0700 Subject: [PATCH 1/3] Expose the indirection index --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll index fe954c640d1b..d1eccf8c1cce 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll @@ -767,10 +767,11 @@ module Public { */ class UninitializedNode extends Node { LocalVariable v; + int indirectionIndex; UninitializedNode() { exists(SsaImpl::Definition def, SsaImpl::SourceVariable sv | - def.getIndirectionIndex() = 0 and + def.getIndirectionIndex() = indirectionIndex and def.getValue().asInstruction() instanceof UninitializedInstruction and SsaImpl::defToNode(this, def, sv) and v = sv.getBaseVariable().(SsaImpl::BaseIRVariable).getIRVariable().getAst() @@ -779,6 +780,9 @@ module Public { /** Gets the uninitialized local variable corresponding to this node. */ LocalVariable getLocalVariable() { result = v } + + /** Gets the level of indirection to get to this node. */ + int getIndirectionIndex() { result = indirectionIndex } } /** From 8c03136c252e22cc062b63f132d89235b3354633 Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Fri, 13 Mar 2026 10:11:40 -0700 Subject: [PATCH 2/3] Revert "Expose the indirection index" This reverts commit 6c792e69b341de543d31598c63acbc8fa4cba429. --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll index d1eccf8c1cce..fe954c640d1b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll @@ -767,11 +767,10 @@ module Public { */ class UninitializedNode extends Node { LocalVariable v; - int indirectionIndex; UninitializedNode() { exists(SsaImpl::Definition def, SsaImpl::SourceVariable sv | - def.getIndirectionIndex() = indirectionIndex and + def.getIndirectionIndex() = 0 and def.getValue().asInstruction() instanceof UninitializedInstruction and SsaImpl::defToNode(this, def, sv) and v = sv.getBaseVariable().(SsaImpl::BaseIRVariable).getIRVariable().getAst() @@ -780,9 +779,6 @@ module Public { /** Gets the uninitialized local variable corresponding to this node. */ LocalVariable getLocalVariable() { result = v } - - /** Gets the level of indirection to get to this node. */ - int getIndirectionIndex() { result = indirectionIndex } } /** From d3066af2e2ca786bca7cc16c65613f07720c9ffc Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Fri, 13 Mar 2026 11:39:57 -0700 Subject: [PATCH 3/3] Create `IndirectUninitializedNode` and add a bridge from it to `LocalVariable` This way the changes do not alter the meaning of `UninitializedNode`. In the meantime, the code still provides a specialized `Node` type `IndirectUninitializedNode` to access the nodes behind levels of indirection. --- .../ir/dataflow/internal/DataFlowNodes.qll | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll index fe954c640d1b..6b201a7aa8b5 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll @@ -617,6 +617,25 @@ module Public { */ LocalVariable asUninitialized() { result = this.(UninitializedNode).getLocalVariable() } + /** + * Gets the uninitialized local variable corresponding to this node behind + * the given levels of indirection, if any. + */ + LocalVariable asIndirectUninitialized(int indirectionIndex) { + exists(IndirectUninitializedNode indirectUninitializedNode | + this = indirectUninitializedNode and + indirectUninitializedNode.getIndirectionIndex() = indirectionIndex + | + result = indirectUninitializedNode.getLocalVariable() + ) + } + + /** + * Gets the uninitialized local variable corresponding to this node behind + * any levels of indirection, if any. + */ + LocalVariable asIndirectUninitialized() { result = this.asIndirectUninitialized(_) } + /** * Gets the positional parameter corresponding to the node that represents * the value of the parameter after `index` number of loads, if any. For @@ -781,6 +800,34 @@ module Public { LocalVariable getLocalVariable() { result = v } } + /** + * The value of an uninitialized local variable behind one or more levels of + * indirection, viewed as a node in a data flow graph. + * + * NOTE: For the direct value of the uninitialized local variable, see + * `UninitializedNode`. + */ + class IndirectUninitializedNode extends Node { + LocalVariable v; + int indirectionIndex; + + IndirectUninitializedNode() { + exists(SsaImpl::Definition def, SsaImpl::SourceVariable sv | + def.getIndirectionIndex() = indirectionIndex and + indirectionIndex > 0 and // With `indirectionIndex` = 0, this class becomes the same as `UninitializedNode`. + def.getValue().asInstruction() instanceof UninitializedInstruction and + SsaImpl::defToNode(this, def, sv) and + v = sv.getBaseVariable().(SsaImpl::BaseIRVariable).getIRVariable().getAst() + ) + } + + /** Gets the uninitialized local variable corresponding to this node. */ + LocalVariable getLocalVariable() { result = v } + + /** Gets the level of indirection to get to this node. */ + int getIndirectionIndex() { result = indirectionIndex } + } + /** * The value of a parameter at function entry, viewed as a node in a data * flow graph. This includes both explicit parameters such as `x` in `f(x)`