From d0e766da3e12015912efa3d90cb37a63c1e5df80 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 28 Aug 2025 12:06:21 +0200 Subject: [PATCH 1/3] C++: Add a testcase with invalid IR. --- .../library-tests/ir/ir/PrintAST.expected | 31 ++++++++++++++++++ .../library-tests/ir/ir/aliased_ir.expected | 32 +++++++++++++++++++ cpp/ql/test/library-tests/ir/ir/ir.cpp | 5 +++ .../ir/ir/raw_consistency.expected | 1 + .../test/library-tests/ir/ir/raw_ir.expected | 31 ++++++++++++++++++ 5 files changed, 100 insertions(+) diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index 6e62071e7d97..c3085da03ab5 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -24550,6 +24550,37 @@ ir.cpp: # 2771| Type = [LValueReferenceType] ThreeWay & # 2771| ValueCategory = prvalue # 2772| getStmt(2): [ReturnStmt] return ... +# 2774| [TopLevelFunction] void test_allocation_with_initializer() +# 2774| : +# 2774| getEntryPoint(): [BlockStmt] { ... } +# 2775| getStmt(0): [DeclStmt] declaration +# 2775| getDeclarationEntry(0): [VariableDeclarationEntry] definition of p1 +# 2775| Type = [IntPointerType] int * +# 2775| getVariable().getInitializer(): [Initializer] initializer for p1 +# 2775| getExpr(): [NewExpr] new +# 2775| Type = [IntPointerType] int * +# 2775| ValueCategory = prvalue +# 2775| getInitializer(): [Literal] 42 +# 2775| Type = [IntType] int +# 2775| Value = [Literal] 42 +# 2775| ValueCategory = prvalue +# 2776| getStmt(1): [DeclStmt] declaration +# 2776| getDeclarationEntry(0): [VariableDeclarationEntry] definition of p2 +# 2776| Type = [PointerType] long * +# 2776| getVariable().getInitializer(): [Initializer] initializer for p2 +# 2776| getExpr(): [NewExpr] new +# 2776| Type = [PointerType] long * +# 2776| ValueCategory = prvalue +# 2776| getInitializer(): [Literal] 42 +# 2776| Type = [IntType] int +# 2776| Value = [Literal] 42 +# 2776| ValueCategory = prvalue +# 2776| getInitializer().getFullyConverted(): [CStyleCast] (long)... +# 2776| Conversion = [IntegralConversion] integral conversion +# 2776| Type = [LongType] long +# 2776| Value = [CStyleCast] 42 +# 2776| ValueCategory = prvalue +# 2777| getStmt(2): [ReturnStmt] return ... ir23.cpp: # 1| [TopLevelFunction] bool consteval_1() # 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 6bf6801a48bd..30741be68918 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -20395,6 +20395,38 @@ ir.cpp: # 2769| v2769_14(void) = AliasedUse : ~m2771_8 # 2769| v2769_15(void) = ExitFunction : +# 2774| void test_allocation_with_initializer() +# 2774| Block 0 +# 2774| v2774_1(void) = EnterFunction : +# 2774| m2774_2(unknown) = AliasedDefinition : +# 2774| m2774_3(unknown) = InitializeNonLocal : +# 2774| m2774_4(unknown) = Chi : total:m2774_2, partial:m2774_3 +# 2775| r2775_1(glval) = VariableAddress[p1] : +# 2775| r2775_2(glval) = FunctionAddress[operator new] : +# 2775| r2775_3(unsigned long) = Constant[4] : +# 2775| r2775_4(void *) = Call[operator new] : func:r2775_2, 0:r2775_3 +# 2775| m2775_5(unknown) = ^CallSideEffect : ~m2774_4 +# 2775| m2775_6(unknown) = Chi : total:m2774_4, partial:m2775_5 +# 2775| m2775_7(unknown) = ^InitializeDynamicAllocation : &:r2775_4 +# 2775| r2775_8(int *) = Convert : r2775_4 +# 2775| r2775_9(int) = Constant[42] : +# 2775| m2775_10(int) = Store[?] : &:r2775_8, r2775_9 +# 2775| m2775_11(unknown) = Chi : total:m2775_7, partial:m2775_10 +# 2775| m2775_12(int *) = Store[p1] : &:r2775_1, r2775_8 +# 2776| r2776_1(glval) = VariableAddress[p2] : +# 2776| r2776_2(glval) = FunctionAddress[operator new] : +# 2776| r2776_3(unsigned long) = Constant[8] : +# 2776| r2776_4(void *) = Call[operator new] : func:r2776_2, 0:r2776_3 +# 2776| m2776_5(unknown) = ^CallSideEffect : ~m2775_6 +# 2776| m2776_6(unknown) = Chi : total:m2775_6, partial:m2776_5 +# 2776| m2776_7(unknown) = ^InitializeDynamicAllocation : &:r2776_4 +# 2776| r2776_8(long *) = Convert : r2776_4 +# 2776| m2776_9(long *) = Store[p2] : &:r2776_1, r2776_8 +# 2777| v2777_1(void) = NoOp : +# 2774| v2774_5(void) = ReturnVoid : +# 2774| v2774_6(void) = AliasedUse : ~m2776_6 +# 2774| v2774_7(void) = ExitFunction : + ir23.cpp: # 1| bool consteval_1() # 1| Block 0 diff --git a/cpp/ql/test/library-tests/ir/ir/ir.cpp b/cpp/ql/test/library-tests/ir/ir/ir.cpp index 74c41c7e916b..66af788db12d 100644 --- a/cpp/ql/test/library-tests/ir/ir/ir.cpp +++ b/cpp/ql/test/library-tests/ir/ir/ir.cpp @@ -2771,4 +2771,9 @@ void test_three_way(int a, int b, ThreeWay c, ThreeWay d) { auto y = c <=> d; } +void test_allocation_with_initializer() { + int* p1 = new int(42); + long* p2 = new long(42); +} + // semmle-extractor-options: -std=c++20 --clang 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 e30106d35204..39bfd38faef5 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected @@ -6,6 +6,7 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor +| ir.cpp:2776:25:2776:26 | Constant: (long)... | Instruction 'Constant: (long)...' has no successors in function '$@'. | ir.cpp:2774:6:2774:37 | void test_allocation_with_initializer() | void test_allocation_with_initializer() | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction 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 bf4cef8c3f49..b3774bcbd00f 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -18547,6 +18547,37 @@ ir.cpp: # 2769| v2769_13(void) = AliasedUse : ~m? # 2769| v2769_14(void) = ExitFunction : +# 2774| void test_allocation_with_initializer() +# 2774| Block 0 +# 2774| v2774_1(void) = EnterFunction : +# 2774| mu2774_2(unknown) = AliasedDefinition : +# 2774| mu2774_3(unknown) = InitializeNonLocal : +# 2775| r2775_1(glval) = VariableAddress[p1] : +# 2775| r2775_2(glval) = FunctionAddress[operator new] : +# 2775| r2775_3(unsigned long) = Constant[4] : +# 2775| r2775_4(void *) = Call[operator new] : func:r2775_2, 0:r2775_3 +# 2775| mu2775_5(unknown) = ^CallSideEffect : ~m? +# 2775| mu2775_6(unknown) = ^InitializeDynamicAllocation : &:r2775_4 +# 2775| r2775_7(int *) = Convert : r2775_4 +# 2775| r2775_8(int) = Constant[42] : +# 2775| mu2775_9(int) = Store[?] : &:r2775_7, r2775_8 +# 2775| mu2775_10(int *) = Store[p1] : &:r2775_1, r2775_7 +# 2776| r2776_1(glval) = VariableAddress[p2] : +# 2776| r2776_2(glval) = FunctionAddress[operator new] : +# 2776| r2776_3(unsigned long) = Constant[8] : +# 2776| r2776_4(void *) = Call[operator new] : func:r2776_2, 0:r2776_3 +# 2776| mu2776_5(unknown) = ^CallSideEffect : ~m? +# 2776| mu2776_6(unknown) = ^InitializeDynamicAllocation : &:r2776_4 +# 2776| r2776_7(long *) = Convert : r2776_4 +# 2776| mu2776_8(long *) = Store[p2] : &:r2776_1, r2776_7 +# 2777| v2777_1(void) = NoOp : +# 2774| v2774_4(void) = ReturnVoid : +# 2774| v2774_5(void) = AliasedUse : ~m? +# 2774| v2774_6(void) = ExitFunction : + +# 2776| Block 1 +# 2776| r2776_9(long) = Constant[42] : + ir23.cpp: # 1| bool consteval_1() # 1| Block 0 From 2033552bb2dca0d8bff48efe5519cef1820d4ec0 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 28 Aug 2025 12:13:02 +0200 Subject: [PATCH 2/3] C++: Handle conversions in new initializers. --- .../code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 f7786fcf290a..f749f8b7502c 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 @@ -3884,7 +3884,7 @@ class TranslatedNewExpr extends TranslatedNewOrNewArrayExpr { final override Type getTargetType() { result = expr.getAllocatedType().getUnspecifiedType() } final override TranslatedInitialization getInitialization() { - result = getTranslatedInitialization(expr.getInitializer()) + result = getTranslatedInitialization(expr.getInitializer().getFullyConverted()) } } From 4116292888c0c61f41863ac059476b4291f9e69d Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 28 Aug 2025 12:13:19 +0200 Subject: [PATCH 3/3] C++: Accept test changes. --- cpp/ql/test/library-tests/ir/ir/aliased_ir.expected | 5 ++++- cpp/ql/test/library-tests/ir/ir/raw_consistency.expected | 1 - cpp/ql/test/library-tests/ir/ir/raw_ir.expected | 7 +++---- 3 files changed, 7 insertions(+), 6 deletions(-) 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 30741be68918..d8babdb54e20 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -20421,7 +20421,10 @@ ir.cpp: # 2776| m2776_6(unknown) = Chi : total:m2775_6, partial:m2776_5 # 2776| m2776_7(unknown) = ^InitializeDynamicAllocation : &:r2776_4 # 2776| r2776_8(long *) = Convert : r2776_4 -# 2776| m2776_9(long *) = Store[p2] : &:r2776_1, r2776_8 +# 2776| r2776_9(long) = Constant[42] : +# 2776| m2776_10(long) = Store[?] : &:r2776_8, r2776_9 +# 2776| m2776_11(unknown) = Chi : total:m2776_7, partial:m2776_10 +# 2776| m2776_12(long *) = Store[p2] : &:r2776_1, r2776_8 # 2777| v2777_1(void) = NoOp : # 2774| v2774_5(void) = ReturnVoid : # 2774| v2774_6(void) = AliasedUse : ~m2776_6 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 39bfd38faef5..e30106d35204 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected @@ -6,7 +6,6 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor -| ir.cpp:2776:25:2776:26 | Constant: (long)... | Instruction 'Constant: (long)...' has no successors in function '$@'. | ir.cpp:2774:6:2774:37 | void test_allocation_with_initializer() | void test_allocation_with_initializer() | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction 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 b3774bcbd00f..a567c651ca24 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -18569,15 +18569,14 @@ ir.cpp: # 2776| mu2776_5(unknown) = ^CallSideEffect : ~m? # 2776| mu2776_6(unknown) = ^InitializeDynamicAllocation : &:r2776_4 # 2776| r2776_7(long *) = Convert : r2776_4 -# 2776| mu2776_8(long *) = Store[p2] : &:r2776_1, r2776_7 +# 2776| r2776_8(long) = Constant[42] : +# 2776| mu2776_9(long) = Store[?] : &:r2776_7, r2776_8 +# 2776| mu2776_10(long *) = Store[p2] : &:r2776_1, r2776_7 # 2777| v2777_1(void) = NoOp : # 2774| v2774_4(void) = ReturnVoid : # 2774| v2774_5(void) = AliasedUse : ~m? # 2774| v2774_6(void) = ExitFunction : -# 2776| Block 1 -# 2776| r2776_9(long) = Constant[42] : - ir23.cpp: # 1| bool consteval_1() # 1| Block 0