From f68d3477d4be389ae9b9ec5b0c11921996419a76 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Mon, 1 Sep 2025 19:24:34 +0200 Subject: [PATCH] C++: Output necessary conversions in the `sizeof` VLA IR --- .../raw/internal/InstructionTag.qll | 3 + .../raw/internal/TranslatedExpr.qll | 41 +++++++++-- .../library-tests/ir/ir/aliased_ir.expected | 70 ++++++++++++------- .../test/library-tests/ir/ir/raw_ir.expected | 68 +++++++++++------- 4 files changed, 124 insertions(+), 58 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll index 90af7d54fbb..be3f680aa16 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll @@ -99,6 +99,9 @@ newtype TInstructionTag = CoAwaitBranchTag() or BoolToIntConversionTag() or SizeofVlaBaseSizeTag() or + SizeofVlaConversionTag(int index) { + exists(VlaDeclStmt v | exists(v.getTransitiveVlaDimensionStmt(index))) + } or SizeofVlaDimensionTag(int index) { exists(VlaDeclStmt v | exists(v.getTransitiveVlaDimensionStmt(index))) } 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 c3aecd8d940..b7ffffea333 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 @@ -4131,6 +4131,23 @@ class TranslatedSizeofExpr extends TranslatedNonConstantExpr { tag = SizeofVlaBaseSizeTag() and resultType = this.getResultType() or + exists(int n, Type dimType | + pointerDerefCount <= n and + n < vlaDimensions and + dimType = vlaDeclStmt.getTransitiveVlaDimensionStmt(n).getDimensionExpr().getUnderlyingType() + | + ( + expr.getUnderlyingType() = dimType and + opcode instanceof Opcode::CopyValue and + tag = SizeofVlaConversionTag(n) + or + not expr.getUnderlyingType() = dimType and + opcode instanceof Opcode::Convert and + tag = SizeofVlaConversionTag(n) + ) + ) and + resultType = this.getResultType() + or opcode instanceof Opcode::Mul and exists(int n | pointerDerefCount <= n and n < vlaDimensions | tag = SizeofVlaDimensionTag(n)) and resultType = this.getResultType() @@ -4138,12 +4155,18 @@ class TranslatedSizeofExpr extends TranslatedNonConstantExpr { final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { tag = SizeofVlaBaseSizeTag() and - result = this.getInstruction(SizeofVlaDimensionTag(pointerDerefCount)) and + result = this.getInstruction(SizeofVlaConversionTag(pointerDerefCount)) and + kind instanceof GotoEdge + or + exists(int n | pointerDerefCount <= n and n < vlaDimensions | + tag = SizeofVlaConversionTag(n) and + result = this.getInstruction(SizeofVlaDimensionTag(n)) + ) and kind instanceof GotoEdge or exists(int n | pointerDerefCount <= n and n < vlaDimensions - 1 | tag = SizeofVlaDimensionTag(n) and - result = this.getInstruction(SizeofVlaDimensionTag(n + 1)) + result = this.getInstruction(SizeofVlaConversionTag(n + 1)) ) and kind instanceof GotoEdge or @@ -4176,6 +4199,16 @@ class TranslatedSizeofExpr extends TranslatedNonConstantExpr { } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { + exists(int n | pointerDerefCount <= n and n < vlaDimensions | + tag = SizeofVlaConversionTag(n) and + ( + operandTag instanceof UnaryOperandTag and + result = + getTranslatedExpr(vlaDeclStmt.getTransitiveVlaDimensionStmt(n).getDimensionExpr()) + .getResult() + ) + ) + or exists(int n | pointerDerefCount <= n and n < vlaDimensions | tag = SizeofVlaDimensionTag(n) and ( @@ -4189,9 +4222,7 @@ class TranslatedSizeofExpr extends TranslatedNonConstantExpr { ) or operandTag instanceof RightOperandTag and - result = - getTranslatedExpr(vlaDeclStmt.getTransitiveVlaDimensionStmt(n).getDimensionExpr()) - .getResult() + result = this.getInstruction(SizeofVlaConversionTag(n)) ) ) } 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 afa2b781480..df46de0f489 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -20449,8 +20449,9 @@ ir.cpp: # 2780| v2780_5(void) = NoOp : # 2781| r2781_1(glval) = VariableAddress[x] : # 2781| r2781_2(unsigned long) = Constant[1] : -# 2781| r2781_3(unsigned long) = Mul : r2781_2, r2780_4 -# 2781| m2781_4(unsigned long) = Store[x] : &:r2781_1, r2781_3 +# 2781| r2781_3(unsigned long) = Convert : r2780_4 +# 2781| r2781_4(unsigned long) = Mul : r2781_2, r2781_3 +# 2781| m2781_5(unsigned long) = Store[x] : &:r2781_1, r2781_4 # 2782| r2782_1(glval) = VariableAddress[tmp2] : # 2782| m2782_2(int[][]) = Uninitialized[tmp2] : &:r2782_1 # 2782| r2782_3(glval) = VariableAddress[len1] : @@ -20460,13 +20461,16 @@ ir.cpp: # 2782| v2782_7(void) = NoOp : # 2783| r2783_1(glval) = VariableAddress[y] : # 2783| r2783_2(unsigned long) = Constant[4] : -# 2783| r2783_3(unsigned long) = Mul : r2783_2, r2782_4 -# 2783| r2783_4(unsigned long) = Mul : r2783_3, r2782_6 -# 2783| m2783_5(unsigned long) = Store[y] : &:r2783_1, r2783_4 +# 2783| r2783_3(unsigned long) = Convert : r2782_4 +# 2783| r2783_4(unsigned long) = Mul : r2783_2, r2783_3 +# 2783| r2783_5(unsigned long) = CopyValue : r2782_6 +# 2783| r2783_6(unsigned long) = Mul : r2783_4, r2783_5 +# 2783| m2783_7(unsigned long) = Store[y] : &:r2783_1, r2783_6 # 2784| r2784_1(glval) = VariableAddress[z] : # 2784| r2784_2(unsigned long) = Constant[4] : -# 2784| r2784_3(unsigned long) = Mul : r2784_2, r2782_6 -# 2784| m2784_4(unsigned long) = Store[z] : &:r2784_1, r2784_3 +# 2784| r2784_3(unsigned long) = CopyValue : r2782_6 +# 2784| r2784_4(unsigned long) = Mul : r2784_2, r2784_3 +# 2784| m2784_5(unsigned long) = Store[z] : &:r2784_1, r2784_4 # 2785| r2785_1(glval) = VariableAddress[tmp3] : # 2785| m2785_2(int[][][]) = Uninitialized[tmp3] : &:r2785_1 # 2785| r2785_3(glval) = VariableAddress[len1] : @@ -20478,19 +20482,25 @@ ir.cpp: # 2785| v2785_9(void) = NoOp : # 2786| r2786_1(glval) = VariableAddress[w] : # 2786| r2786_2(unsigned long) = Constant[4] : -# 2786| r2786_3(unsigned long) = Mul : r2786_2, r2785_4 -# 2786| r2786_4(unsigned long) = Mul : r2786_3, r2785_6 -# 2786| r2786_5(unsigned long) = Mul : r2786_4, r2785_8 -# 2786| m2786_6(unsigned long) = Store[w] : &:r2786_1, r2786_5 +# 2786| r2786_3(unsigned long) = Convert : r2785_4 +# 2786| r2786_4(unsigned long) = Mul : r2786_2, r2786_3 +# 2786| r2786_5(unsigned long) = CopyValue : r2785_6 +# 2786| r2786_6(unsigned long) = Mul : r2786_4, r2786_5 +# 2786| r2786_7(unsigned long) = Convert : r2785_8 +# 2786| r2786_8(unsigned long) = Mul : r2786_6, r2786_7 +# 2786| m2786_9(unsigned long) = Store[w] : &:r2786_1, r2786_8 # 2787| r2787_1(glval) = VariableAddress[v] : # 2787| r2787_2(unsigned long) = Constant[4] : -# 2787| r2787_3(unsigned long) = Mul : r2787_2, r2785_6 -# 2787| r2787_4(unsigned long) = Mul : r2787_3, r2785_8 -# 2787| m2787_5(unsigned long) = Store[v] : &:r2787_1, r2787_4 +# 2787| r2787_3(unsigned long) = CopyValue : r2785_6 +# 2787| r2787_4(unsigned long) = Mul : r2787_2, r2787_3 +# 2787| r2787_5(unsigned long) = Convert : r2785_8 +# 2787| r2787_6(unsigned long) = Mul : r2787_4, r2787_5 +# 2787| m2787_7(unsigned long) = Store[v] : &:r2787_1, r2787_6 # 2788| r2788_1(glval) = VariableAddress[u] : # 2788| r2788_2(unsigned long) = Constant[4] : -# 2788| r2788_3(unsigned long) = Mul : r2788_2, r2785_8 -# 2788| m2788_4(unsigned long) = Store[u] : &:r2788_1, r2788_3 +# 2788| r2788_3(unsigned long) = Convert : r2785_8 +# 2788| r2788_4(unsigned long) = Mul : r2788_2, r2788_3 +# 2788| m2788_5(unsigned long) = Store[u] : &:r2788_1, r2788_4 # 2789| r2789_1(glval) = VariableAddress[t] : # 2789| r2789_2(unsigned long) = Constant[4] : # 2789| m2789_3(unsigned long) = Store[t] : &:r2789_1, r2789_2 @@ -20520,8 +20530,9 @@ ir.cpp: # 2793| v2793_7(void) = NoOp : # 2794| r2794_1(glval) = VariableAddress[z] : # 2794| r2794_2(unsigned long) = Constant[4] : -# 2794| r2794_3(unsigned long) = Mul : r2794_2, r2793_6 -# 2794| m2794_4(unsigned long) = Store[z] : &:r2794_1, r2794_3 +# 2794| r2794_3(unsigned long) = CopyValue : r2793_6 +# 2794| r2794_4(unsigned long) = Mul : r2794_2, r2794_3 +# 2794| m2794_5(unsigned long) = Store[z] : &:r2794_1, r2794_4 # 2795| r2795_1(glval) = VariableAddress[tmp2] : # 2795| m2795_2(int[][][]) = Uninitialized[tmp2] : &:r2795_1 # 2795| r2795_3(glval) = VariableAddress[len1] : @@ -20533,13 +20544,16 @@ ir.cpp: # 2795| v2795_9(void) = NoOp : # 2796| r2796_1(glval) = VariableAddress[v] : # 2796| r2796_2(unsigned long) = Constant[4] : -# 2796| r2796_3(unsigned long) = Mul : r2796_2, r2795_6 -# 2796| r2796_4(unsigned long) = Mul : r2796_3, r2795_8 -# 2796| m2796_5(unsigned long) = Store[v] : &:r2796_1, r2796_4 +# 2796| r2796_3(unsigned long) = CopyValue : r2795_6 +# 2796| r2796_4(unsigned long) = Mul : r2796_2, r2796_3 +# 2796| r2796_5(unsigned long) = Convert : r2795_8 +# 2796| r2796_6(unsigned long) = Mul : r2796_4, r2796_5 +# 2796| m2796_7(unsigned long) = Store[v] : &:r2796_1, r2796_6 # 2797| r2797_1(glval) = VariableAddress[u] : # 2797| r2797_2(unsigned long) = Constant[4] : -# 2797| r2797_3(unsigned long) = Mul : r2797_2, r2795_8 -# 2797| m2797_4(unsigned long) = Store[u] : &:r2797_1, r2797_3 +# 2797| r2797_3(unsigned long) = Convert : r2795_8 +# 2797| r2797_4(unsigned long) = Mul : r2797_2, r2797_3 +# 2797| m2797_5(unsigned long) = Store[u] : &:r2797_1, r2797_4 # 2798| r2798_1(glval) = VariableAddress[t] : # 2798| r2798_2(unsigned long) = Constant[4] : # 2798| m2798_3(unsigned long) = Store[t] : &:r2798_1, r2798_2 @@ -20578,7 +20592,7 @@ ir.cpp: #-----| True -> Block 2 # 2801| Block 1 -# 2801| m2801_13(unsigned long) = Phi : from 2:m2808_5, from 3:m2811_3 +# 2801| m2801_13(unsigned long) = Phi : from 2:m2808_7, from 3:m2811_3 # 2801| r2801_14(glval) = VariableAddress[#return] : # 2801| v2801_15(void) = ReturnValue : &:r2801_14, m2801_13 # 2801| v2801_16(void) = AliasedUse : m2801_3 @@ -20590,9 +20604,11 @@ ir.cpp: # 2807| v2807_3(void) = NoOp : # 2808| r2808_1(glval) = VariableAddress[#return] : # 2808| r2808_2(unsigned long) = Constant[8] : -# 2808| r2808_3(unsigned long) = Mul : r2808_2, r2802_2 -# 2808| r2808_4(unsigned long) = Mul : r2808_3, r2802_4 -# 2808| m2808_5(unsigned long) = Store[#return] : &:r2808_1, r2808_4 +# 2808| r2808_3(unsigned long) = Convert : r2802_2 +# 2808| r2808_4(unsigned long) = Mul : r2808_2, r2808_3 +# 2808| r2808_5(unsigned long) = CopyValue : r2802_4 +# 2808| r2808_6(unsigned long) = Mul : r2808_4, r2808_5 +# 2808| m2808_7(unsigned long) = Store[#return] : &:r2808_1, r2808_6 #-----| Goto -> Block 1 # 2811| Block 3 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 a14e59b3213..5a65885edee 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -18595,8 +18595,9 @@ ir.cpp: # 2780| v2780_5(void) = NoOp : # 2781| r2781_1(glval) = VariableAddress[x] : # 2781| r2781_2(unsigned long) = Constant[1] : -# 2781| r2781_3(unsigned long) = Mul : r2781_2, r2780_4 -# 2781| mu2781_4(unsigned long) = Store[x] : &:r2781_1, r2781_3 +# 2781| r2781_3(unsigned long) = Convert : r2780_4 +# 2781| r2781_4(unsigned long) = Mul : r2781_2, r2781_3 +# 2781| mu2781_5(unsigned long) = Store[x] : &:r2781_1, r2781_4 # 2782| r2782_1(glval) = VariableAddress[tmp2] : # 2782| mu2782_2(int[][]) = Uninitialized[tmp2] : &:r2782_1 # 2782| r2782_3(glval) = VariableAddress[len1] : @@ -18606,13 +18607,16 @@ ir.cpp: # 2782| v2782_7(void) = NoOp : # 2783| r2783_1(glval) = VariableAddress[y] : # 2783| r2783_2(unsigned long) = Constant[4] : -# 2783| r2783_3(unsigned long) = Mul : r2783_2, r2782_4 -# 2783| r2783_4(unsigned long) = Mul : r2783_3, r2782_6 -# 2783| mu2783_5(unsigned long) = Store[y] : &:r2783_1, r2783_4 +# 2783| r2783_3(unsigned long) = Convert : r2782_4 +# 2783| r2783_4(unsigned long) = Mul : r2783_2, r2783_3 +# 2783| r2783_5(unsigned long) = CopyValue : r2782_6 +# 2783| r2783_6(unsigned long) = Mul : r2783_4, r2783_5 +# 2783| mu2783_7(unsigned long) = Store[y] : &:r2783_1, r2783_6 # 2784| r2784_1(glval) = VariableAddress[z] : # 2784| r2784_2(unsigned long) = Constant[4] : -# 2784| r2784_3(unsigned long) = Mul : r2784_2, r2782_6 -# 2784| mu2784_4(unsigned long) = Store[z] : &:r2784_1, r2784_3 +# 2784| r2784_3(unsigned long) = CopyValue : r2782_6 +# 2784| r2784_4(unsigned long) = Mul : r2784_2, r2784_3 +# 2784| mu2784_5(unsigned long) = Store[z] : &:r2784_1, r2784_4 # 2785| r2785_1(glval) = VariableAddress[tmp3] : # 2785| mu2785_2(int[][][]) = Uninitialized[tmp3] : &:r2785_1 # 2785| r2785_3(glval) = VariableAddress[len1] : @@ -18624,19 +18628,25 @@ ir.cpp: # 2785| v2785_9(void) = NoOp : # 2786| r2786_1(glval) = VariableAddress[w] : # 2786| r2786_2(unsigned long) = Constant[4] : -# 2786| r2786_3(unsigned long) = Mul : r2786_2, r2785_4 -# 2786| r2786_4(unsigned long) = Mul : r2786_3, r2785_6 -# 2786| r2786_5(unsigned long) = Mul : r2786_4, r2785_8 -# 2786| mu2786_6(unsigned long) = Store[w] : &:r2786_1, r2786_5 +# 2786| r2786_3(unsigned long) = Convert : r2785_4 +# 2786| r2786_4(unsigned long) = Mul : r2786_2, r2786_3 +# 2786| r2786_5(unsigned long) = CopyValue : r2785_6 +# 2786| r2786_6(unsigned long) = Mul : r2786_4, r2786_5 +# 2786| r2786_7(unsigned long) = Convert : r2785_8 +# 2786| r2786_8(unsigned long) = Mul : r2786_6, r2786_7 +# 2786| mu2786_9(unsigned long) = Store[w] : &:r2786_1, r2786_8 # 2787| r2787_1(glval) = VariableAddress[v] : # 2787| r2787_2(unsigned long) = Constant[4] : -# 2787| r2787_3(unsigned long) = Mul : r2787_2, r2785_6 -# 2787| r2787_4(unsigned long) = Mul : r2787_3, r2785_8 -# 2787| mu2787_5(unsigned long) = Store[v] : &:r2787_1, r2787_4 +# 2787| r2787_3(unsigned long) = CopyValue : r2785_6 +# 2787| r2787_4(unsigned long) = Mul : r2787_2, r2787_3 +# 2787| r2787_5(unsigned long) = Convert : r2785_8 +# 2787| r2787_6(unsigned long) = Mul : r2787_4, r2787_5 +# 2787| mu2787_7(unsigned long) = Store[v] : &:r2787_1, r2787_6 # 2788| r2788_1(glval) = VariableAddress[u] : # 2788| r2788_2(unsigned long) = Constant[4] : -# 2788| r2788_3(unsigned long) = Mul : r2788_2, r2785_8 -# 2788| mu2788_4(unsigned long) = Store[u] : &:r2788_1, r2788_3 +# 2788| r2788_3(unsigned long) = Convert : r2785_8 +# 2788| r2788_4(unsigned long) = Mul : r2788_2, r2788_3 +# 2788| mu2788_5(unsigned long) = Store[u] : &:r2788_1, r2788_4 # 2789| r2789_1(glval) = VariableAddress[t] : # 2789| r2789_2(unsigned long) = Constant[4] : # 2789| mu2789_3(unsigned long) = Store[t] : &:r2789_1, r2789_2 @@ -18665,8 +18675,9 @@ ir.cpp: # 2793| v2793_7(void) = NoOp : # 2794| r2794_1(glval) = VariableAddress[z] : # 2794| r2794_2(unsigned long) = Constant[4] : -# 2794| r2794_3(unsigned long) = Mul : r2794_2, r2793_6 -# 2794| mu2794_4(unsigned long) = Store[z] : &:r2794_1, r2794_3 +# 2794| r2794_3(unsigned long) = CopyValue : r2793_6 +# 2794| r2794_4(unsigned long) = Mul : r2794_2, r2794_3 +# 2794| mu2794_5(unsigned long) = Store[z] : &:r2794_1, r2794_4 # 2795| r2795_1(glval) = VariableAddress[tmp2] : # 2795| mu2795_2(int[][][]) = Uninitialized[tmp2] : &:r2795_1 # 2795| r2795_3(glval) = VariableAddress[len1] : @@ -18678,13 +18689,16 @@ ir.cpp: # 2795| v2795_9(void) = NoOp : # 2796| r2796_1(glval) = VariableAddress[v] : # 2796| r2796_2(unsigned long) = Constant[4] : -# 2796| r2796_3(unsigned long) = Mul : r2796_2, r2795_6 -# 2796| r2796_4(unsigned long) = Mul : r2796_3, r2795_8 -# 2796| mu2796_5(unsigned long) = Store[v] : &:r2796_1, r2796_4 +# 2796| r2796_3(unsigned long) = CopyValue : r2795_6 +# 2796| r2796_4(unsigned long) = Mul : r2796_2, r2796_3 +# 2796| r2796_5(unsigned long) = Convert : r2795_8 +# 2796| r2796_6(unsigned long) = Mul : r2796_4, r2796_5 +# 2796| mu2796_7(unsigned long) = Store[v] : &:r2796_1, r2796_6 # 2797| r2797_1(glval) = VariableAddress[u] : # 2797| r2797_2(unsigned long) = Constant[4] : -# 2797| r2797_3(unsigned long) = Mul : r2797_2, r2795_8 -# 2797| mu2797_4(unsigned long) = Store[u] : &:r2797_1, r2797_3 +# 2797| r2797_3(unsigned long) = Convert : r2795_8 +# 2797| r2797_4(unsigned long) = Mul : r2797_2, r2797_3 +# 2797| mu2797_5(unsigned long) = Store[u] : &:r2797_1, r2797_4 # 2798| r2798_1(glval) = VariableAddress[t] : # 2798| r2798_2(unsigned long) = Constant[4] : # 2798| mu2798_3(unsigned long) = Store[t] : &:r2798_1, r2798_2 @@ -18733,9 +18747,11 @@ ir.cpp: # 2807| v2807_3(void) = NoOp : # 2808| r2808_1(glval) = VariableAddress[#return] : # 2808| r2808_2(unsigned long) = Constant[8] : -# 2808| r2808_3(unsigned long) = Mul : r2808_2, r2802_2 -# 2808| r2808_4(unsigned long) = Mul : r2808_3, r2802_4 -# 2808| mu2808_5(unsigned long) = Store[#return] : &:r2808_1, r2808_4 +# 2808| r2808_3(unsigned long) = Convert : r2802_2 +# 2808| r2808_4(unsigned long) = Mul : r2808_2, r2808_3 +# 2808| r2808_5(unsigned long) = CopyValue : r2802_4 +# 2808| r2808_6(unsigned long) = Mul : r2808_4, r2808_5 +# 2808| mu2808_7(unsigned long) = Store[#return] : &:r2808_1, r2808_6 #-----| Goto -> Block 1 # 2811| Block 3