mirror of
https://github.com/github/codeql.git
synced 2026-04-25 16:55:19 +02:00
Merge pull request #21611 from MathiasVP/nsdmi-dataflow-3
C++: Add dataflow through NSDMI
This commit is contained in:
4
cpp/ql/lib/change-notes/2026-03-30-nsdmi-dataflow.md
Normal file
4
cpp/ql/lib/change-notes/2026-03-30-nsdmi-dataflow.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added dataflow through members initialized via non-static data member initialization (NSDMI).
|
||||
@@ -850,11 +850,6 @@ module Public {
|
||||
{
|
||||
ThisParameterInstructionNode() { instr.getIRVariable() instanceof IRThisVariable }
|
||||
|
||||
override predicate isSourceParameterOf(Function f, ParameterPosition pos) {
|
||||
pos.(DirectPosition).getArgumentIndex() = -1 and
|
||||
instr.getEnclosingFunction() = f
|
||||
}
|
||||
|
||||
override string toStringImpl() { result = "this" }
|
||||
}
|
||||
|
||||
@@ -1129,7 +1124,7 @@ class IndirectArgumentOutNode extends PostUpdateNodeImpl {
|
||||
/**
|
||||
* Gets the `Function` that the call targets, if this is statically known.
|
||||
*/
|
||||
Function getStaticCallTarget() { result = this.getCallInstruction().getStaticCallTarget() }
|
||||
Declaration getStaticCallTarget() { result = this.getCallInstruction().getStaticCallTarget() }
|
||||
|
||||
override string toStringImpl() {
|
||||
exists(string prefix | if indirectionIndex > 0 then prefix = "" else prefix = "pointer to " |
|
||||
@@ -1633,7 +1628,7 @@ abstract private class AbstractParameterNode extends Node {
|
||||
* implicit `this` parameter is considered to have position `-1`, and
|
||||
* pointer-indirection parameters are at further negative positions.
|
||||
*/
|
||||
predicate isSourceParameterOf(Function f, ParameterPosition pos) { none() }
|
||||
predicate isSourceParameterOf(Declaration f, ParameterPosition pos) { none() }
|
||||
|
||||
/**
|
||||
* Holds if this node is the parameter of `sc` at the specified position. The
|
||||
@@ -1659,6 +1654,11 @@ abstract private class AbstractParameterNode extends Node {
|
||||
|
||||
/** Gets the `Parameter` associated with this node, if it exists. */
|
||||
Parameter getParameter() { none() } // overridden by subclasses
|
||||
|
||||
/**
|
||||
* Holds if this node represents an implicit `this` parameter, if it exists.
|
||||
*/
|
||||
predicate isThis() { none() } // overridden by subclasses
|
||||
}
|
||||
|
||||
abstract private class AbstractIndirectParameterNode extends AbstractParameterNode {
|
||||
@@ -1687,7 +1687,9 @@ private class IndirectInstructionParameterNode extends AbstractIndirectParameter
|
||||
InitializeParameterInstruction init;
|
||||
|
||||
IndirectInstructionParameterNode() {
|
||||
IndirectInstruction.super.hasInstructionAndIndirectionIndex(init, _)
|
||||
IndirectInstruction.super.hasInstructionAndIndirectionIndex(init, _) and
|
||||
// We don't model catch parameters as parameter nodes
|
||||
not exists(init.getParameter().getCatchBlock())
|
||||
}
|
||||
|
||||
int getArgumentIndex() { init.hasIndex(result) }
|
||||
@@ -1701,16 +1703,17 @@ private class IndirectInstructionParameterNode extends AbstractIndirectParameter
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the parameter whose indirection is initialized. */
|
||||
override Parameter getParameter() { result = init.getParameter() }
|
||||
|
||||
override predicate isThis() { init.hasIndex(-1) }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result.asSourceCallable() = this.getFunction()
|
||||
}
|
||||
|
||||
override Declaration getFunction() { result = init.getEnclosingFunction() }
|
||||
|
||||
override predicate isSourceParameterOf(Function f, ParameterPosition pos) {
|
||||
override predicate isSourceParameterOf(Declaration f, ParameterPosition pos) {
|
||||
this.getFunction() = f and
|
||||
exists(int argumentIndex, int indirectionIndex |
|
||||
indirectPositionHasArgumentIndexAndIndex(pos, argumentIndex, indirectionIndex) and
|
||||
@@ -1738,6 +1741,18 @@ abstract class InstructionDirectParameterNode extends InstructionNode, AbstractD
|
||||
* Gets the `IRVariable` that this parameter references.
|
||||
*/
|
||||
final IRVariable getIRVariable() { result = instr.getIRVariable() }
|
||||
|
||||
override predicate isThis() { instr.hasIndex(-1) }
|
||||
|
||||
override Parameter getParameter() { result = instr.getParameter() }
|
||||
|
||||
override predicate isSourceParameterOf(Declaration f, ParameterPosition pos) {
|
||||
this.getFunction() = f and
|
||||
exists(int argumentIndex |
|
||||
pos.(DirectPosition).getArgumentIndex() = argumentIndex and
|
||||
instr.hasIndex(argumentIndex)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
abstract private class AbstractExplicitParameterNode extends AbstractDirectParameterNode { }
|
||||
@@ -1746,15 +1761,12 @@ abstract private class AbstractExplicitParameterNode extends AbstractDirectParam
|
||||
private class ExplicitParameterInstructionNode extends AbstractExplicitParameterNode,
|
||||
InstructionDirectParameterNode
|
||||
{
|
||||
ExplicitParameterInstructionNode() { exists(instr.getParameter()) }
|
||||
|
||||
override predicate isSourceParameterOf(Function f, ParameterPosition pos) {
|
||||
f.getParameter(pos.(DirectPosition).getArgumentIndex()) = instr.getParameter()
|
||||
ExplicitParameterInstructionNode() {
|
||||
// We don't model catch parameters as parameter nodes.
|
||||
exists(instr.getParameter().getFunction())
|
||||
}
|
||||
|
||||
override string toStringImpl() { result = instr.getParameter().toString() }
|
||||
|
||||
override Parameter getParameter() { result = instr.getParameter() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1782,9 +1794,9 @@ private class DirectBodyLessParameterNode extends AbstractExplicitParameterNode,
|
||||
{
|
||||
DirectBodyLessParameterNode() { indirectionIndex = 0 }
|
||||
|
||||
override predicate isSourceParameterOf(Function f, ParameterPosition pos) {
|
||||
override predicate isSourceParameterOf(Declaration f, ParameterPosition pos) {
|
||||
this.getFunction() = f and
|
||||
f.getParameter(pos.(DirectPosition).getArgumentIndex()) = p
|
||||
f.(Function).getParameter(pos.(DirectPosition).getArgumentIndex()) = p
|
||||
}
|
||||
|
||||
override Parameter getParameter() { result = p }
|
||||
@@ -1795,10 +1807,10 @@ private class IndirectBodyLessParameterNode extends AbstractIndirectParameterNod
|
||||
{
|
||||
IndirectBodyLessParameterNode() { not this instanceof DirectBodyLessParameterNode }
|
||||
|
||||
override predicate isSourceParameterOf(Function f, ParameterPosition pos) {
|
||||
override predicate isSourceParameterOf(Declaration f, ParameterPosition pos) {
|
||||
exists(int argumentPosition |
|
||||
this.getFunction() = f and
|
||||
f.getParameter(argumentPosition) = p and
|
||||
f.(Function).getParameter(argumentPosition) = p and
|
||||
indirectPositionHasArgumentIndexAndIndex(pos, argumentPosition, indirectionIndex)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1170,7 +1170,7 @@ class DataFlowCall extends TDataFlowCall {
|
||||
/**
|
||||
* Gets the `Function` that the call targets, if this is statically known.
|
||||
*/
|
||||
Function getStaticCallSourceTarget() { none() }
|
||||
Declaration getStaticCallSourceTarget() { none() }
|
||||
|
||||
/**
|
||||
* Gets the target of this call. We use the following strategy for deciding
|
||||
@@ -1182,7 +1182,7 @@ class DataFlowCall extends TDataFlowCall {
|
||||
* whether is it manual or generated.
|
||||
*/
|
||||
final DataFlowCallable getStaticCallTarget() {
|
||||
exists(Function target | target = this.getStaticCallSourceTarget() |
|
||||
exists(Declaration target | target = this.getStaticCallSourceTarget() |
|
||||
// Don't use the source callable if there is a manual model for the
|
||||
// target
|
||||
not exists(SummarizedCallable sc |
|
||||
@@ -1242,7 +1242,7 @@ private class NormalCall extends DataFlowCall, TNormalCall {
|
||||
|
||||
override CallTargetOperand getCallTargetOperand() { result = call.getCallTargetOperand() }
|
||||
|
||||
override Function getStaticCallSourceTarget() { result = call.getStaticCallTarget() }
|
||||
override Declaration getStaticCallSourceTarget() { result = call.getStaticCallTarget() }
|
||||
|
||||
override ArgumentOperand getArgumentOperand(int index) { result = call.getArgumentOperand(index) }
|
||||
|
||||
|
||||
@@ -11,13 +11,18 @@ private import TypeFlow
|
||||
private import semmle.code.cpp.ir.ValueNumbering
|
||||
|
||||
/**
|
||||
* Gets the C++ type of `this` in the member function `f`.
|
||||
* Gets the C++ type of `this` in an `IRFunction` generated from `f`.
|
||||
* The result is a glvalue if `isGLValue` is true, and
|
||||
* a prvalue if `isGLValue` is false.
|
||||
*/
|
||||
bindingset[isGLValue]
|
||||
private CppType getThisType(Cpp::MemberFunction f, boolean isGLValue) {
|
||||
result.hasType(f.getTypeOfThis(), isGLValue)
|
||||
private CppType getThisType(Cpp::Declaration f, boolean isGLValue) {
|
||||
result.hasType(f.(Cpp::MemberFunction).getTypeOfThis(), isGLValue)
|
||||
or
|
||||
exists(Cpp::PointerType pt |
|
||||
pt.getBaseType() = f.(Cpp::Field).getDeclaringType() and
|
||||
result.hasType(pt, isGLValue)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user