From f4df3881f8f3d7151d947e44e2861de5f27fb90c Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Tue, 2 Sep 2025 11:05:47 +0200 Subject: [PATCH] C++: Handle `*&` sequences in `sizeof` VLA expressions --- .../raw/internal/TranslatedExpr.qll | 6 ++++++ .../test/library-tests/ir/ir/aliased_ir.expected | 8 ++++++++ .../ir/ir/aliased_ssa_consistency.expected | 1 - .../ir/aliased_ssa_consistency_unsound.expected | 1 - .../library-tests/ir/ir/raw_consistency.expected | 3 --- cpp/ql/test/library-tests/ir/ir/raw_ir.expected | 15 ++++++++------- .../ir/ir/unaliased_ssa_consistency.expected | 1 - .../ir/unaliased_ssa_consistency_unsound.expected | 1 - 8 files changed, 22 insertions(+), 14 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index 367d6f652e0..3db6a1dc7a8 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -4098,8 +4098,14 @@ private VlaDeclStmt getVlaDeclStmt(Expr expr, int pointerDerefCount) { expr.(VariableAccess).getTarget() = result.getVariable() and pointerDerefCount = 0 or + not expr.(PointerDereferenceExpr).getOperand() instanceof AddressOfExpr and result = getVlaDeclStmt(expr.(PointerDereferenceExpr).getOperand(), pointerDerefCount - 1) or + // Skip sequences of the form `*&...` + result = + getVlaDeclStmt(expr.(PointerDereferenceExpr).getOperand().(AddressOfExpr).getOperand(), + pointerDerefCount) + or result = getVlaDeclStmt(expr.(ArrayExpr).getArrayBase(), pointerDerefCount - 1) } diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected index 73da3614259..566cf07423b 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -20662,6 +20662,14 @@ ir.cpp: # 2820| r2820_6(unsigned long) = Load[len2] : &:r2820_5, m2819_8 # 2820| v2820_7(void) = NoOp : # 2821| r2821_1(glval) = VariableAddress[z] : +# 2821| r2821_2(unsigned long) = Constant[4] : +# 2821| r2821_3(unsigned long) = CopyValue : r2820_6 +# 2821| r2821_4(unsigned long) = Mul : r2821_2, r2821_3 +# 2821| m2821_5(unsigned long) = Store[z] : &:r2821_1, r2821_4 +# 2822| v2822_1(void) = NoOp : +# 2819| v2819_9(void) = ReturnVoid : +# 2819| v2819_10(void) = AliasedUse : m2819_3 +# 2819| v2819_11(void) = ExitFunction : ir23.cpp: # 1| bool consteval_1() diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected index 45b26f56bd7..b83d9ea47e3 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected @@ -6,7 +6,6 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor -| ir.cpp:2821:10:2821:10 | VariableAddress: definition of z | Instruction 'VariableAddress: definition of z' has no successors in function '$@'. | ir.cpp:2819:6:2819:21 | void vla_sizeof_test5(int, size_t) | void vla_sizeof_test5(int, size_t) | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected index 45b26f56bd7..b83d9ea47e3 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected @@ -6,7 +6,6 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor -| ir.cpp:2821:10:2821:10 | VariableAddress: definition of z | Instruction 'VariableAddress: definition of z' has no successors in function '$@'. | ir.cpp:2819:6:2819:21 | void vla_sizeof_test5(int, size_t) | void vla_sizeof_test5(int, size_t) | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction diff --git a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected index fb13b34cf55..e30106d3520 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected @@ -1,5 +1,4 @@ missingOperand -| ir.cpp:2821:14:2821:32 | Store: sizeof() | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | ir.cpp:2819:6:2819:21 | void vla_sizeof_test5(int, size_t) | void vla_sizeof_test5(int, size_t) | unexpectedOperand duplicateOperand missingPhiOperand @@ -7,7 +6,6 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor -| ir.cpp:2821:10:2821:10 | VariableAddress: definition of z | Instruction 'VariableAddress: definition of z' has no successors in function '$@'. | ir.cpp:2819:6:2819:21 | void vla_sizeof_test5(int, size_t) | void vla_sizeof_test5(int, size_t) | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction @@ -23,7 +21,6 @@ lostReachability backEdgeCountMismatch useNotDominatedByDefinition | ir.cpp:1535:8:1535:8 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:1535:8:1535:8 | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | -| ir.cpp:2821:10:2821:10 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | ir.cpp:2819:6:2819:21 | void vla_sizeof_test5(int, size_t) | void vla_sizeof_test5(int, size_t) | switchInstructionWithoutDefaultEdge notMarkedAsConflated wronglyMarkedAsConflated diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index aa65bb705b0..1d8f885cd15 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -18803,13 +18803,14 @@ ir.cpp: # 2820| r2820_6(unsigned long) = Load[len2] : &:r2820_5, ~m? # 2820| v2820_7(void) = NoOp : # 2821| r2821_1(glval) = VariableAddress[z] : - -# 2821| Block 1 -# 2821| mu2821_2(unsigned long) = Store[z] : &:r2821_1 -# 2822| v2822_1(void) = NoOp : -# 2819| v2819_8(void) = ReturnVoid : -# 2819| v2819_9(void) = AliasedUse : ~m? -# 2819| v2819_10(void) = ExitFunction : +# 2821| r2821_2(unsigned long) = Constant[4] : +# 2821| r2821_3(unsigned long) = CopyValue : r2820_6 +# 2821| r2821_4(unsigned long) = Mul : r2821_2, r2821_3 +# 2821| mu2821_5(unsigned long) = Store[z] : &:r2821_1, r2821_4 +# 2822| v2822_1(void) = NoOp : +# 2819| v2819_8(void) = ReturnVoid : +# 2819| v2819_9(void) = AliasedUse : ~m? +# 2819| v2819_10(void) = ExitFunction : ir23.cpp: # 1| bool consteval_1() diff --git a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency.expected b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency.expected index 45b26f56bd7..b83d9ea47e3 100644 --- a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency.expected @@ -6,7 +6,6 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor -| ir.cpp:2821:10:2821:10 | VariableAddress: definition of z | Instruction 'VariableAddress: definition of z' has no successors in function '$@'. | ir.cpp:2819:6:2819:21 | void vla_sizeof_test5(int, size_t) | void vla_sizeof_test5(int, size_t) | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction diff --git a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency_unsound.expected b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency_unsound.expected index 45b26f56bd7..b83d9ea47e3 100644 --- a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency_unsound.expected @@ -6,7 +6,6 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor -| ir.cpp:2821:10:2821:10 | VariableAddress: definition of z | Instruction 'VariableAddress: definition of z' has no successors in function '$@'. | ir.cpp:2819:6:2819:21 | void vla_sizeof_test5(int, size_t) | void vla_sizeof_test5(int, size_t) | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction