diff --git a/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll b/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll index ee419dd70249..bcd214ec0000 100644 --- a/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll +++ b/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll @@ -1156,5 +1156,14 @@ private predicate add_eq( ) } +private class IntegerOrPointerConstantInstruction extends ConstantInstruction { + IntegerOrPointerConstantInstruction() { + this instanceof IntegerConstantInstruction or + this instanceof PointerConstantInstruction + } +} + /** The int value of integer constant expression. */ -private int int_value(Instruction i) { result = i.(IntegerConstantInstruction).getValue().toInt() } +private int int_value(Instruction i) { + result = i.(IntegerOrPointerConstantInstruction).getValue().toInt() +} diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index 189ffce2903e..c7e40da1e17c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -247,8 +247,7 @@ class Instruction extends Construction::TStageInstruction { * Gets the type of the result produced by this instruction. If the instruction does not produce * a result, its result type will be `IRVoidType`. */ - cached - final IRType getResultIRType() { result = this.getResultLanguageType().getIRType() } + final IRType getResultIRType() { result = Construction::getInstructionResultIRType(this) } /** * Gets the type of the result produced by this instruction. If the @@ -995,9 +994,8 @@ class ConstantInstruction extends ConstantValueInstruction { */ class IntegerConstantInstruction extends ConstantInstruction { IntegerConstantInstruction() { - exists(IRType resultType | - resultType = this.getResultIRType() and - (resultType instanceof IRIntegerType or resultType instanceof IRBooleanType) + exists(IRType resultType | resultType = this.getResultIRType() | + resultType instanceof IRIntegerType or resultType instanceof IRBooleanType ) } } @@ -1009,6 +1007,17 @@ class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { this.getResultIRType() instanceof IRFloatingPointType } } +/** + * An instruction whose result is a constant value of a pointer type. + */ +class PointerConstantInstruction extends ConstantInstruction { + PointerConstantInstruction() { + exists(IRType resultType | resultType = this.getResultIRType() | + resultType instanceof IRAddressType or resultType instanceof IRFunctionAddressType + ) + } +} + /** * An instruction whose result is the address of a string literal. */ diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll index 209c42726b7d..d2e68c733041 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll @@ -429,6 +429,11 @@ private module Cached { instr = unreachedInstruction(_) and result = Language::getVoidType() } + cached + IRType getInstructionResultIRType(Instruction instr) { + result = instr.getResultLanguageType().getIRType() + } + /** * Holds if `opcode` is the opcode that specifies the operation performed by `instr`. * diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll index 189ffce2903e..c7e40da1e17c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -247,8 +247,7 @@ class Instruction extends Construction::TStageInstruction { * Gets the type of the result produced by this instruction. If the instruction does not produce * a result, its result type will be `IRVoidType`. */ - cached - final IRType getResultIRType() { result = this.getResultLanguageType().getIRType() } + final IRType getResultIRType() { result = Construction::getInstructionResultIRType(this) } /** * Gets the type of the result produced by this instruction. If the @@ -995,9 +994,8 @@ class ConstantInstruction extends ConstantValueInstruction { */ class IntegerConstantInstruction extends ConstantInstruction { IntegerConstantInstruction() { - exists(IRType resultType | - resultType = this.getResultIRType() and - (resultType instanceof IRIntegerType or resultType instanceof IRBooleanType) + exists(IRType resultType | resultType = this.getResultIRType() | + resultType instanceof IRIntegerType or resultType instanceof IRBooleanType ) } } @@ -1009,6 +1007,17 @@ class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { this.getResultIRType() instanceof IRFloatingPointType } } +/** + * An instruction whose result is a constant value of a pointer type. + */ +class PointerConstantInstruction extends ConstantInstruction { + PointerConstantInstruction() { + exists(IRType resultType | resultType = this.getResultIRType() | + resultType instanceof IRAddressType or resultType instanceof IRFunctionAddressType + ) + } +} + /** * An instruction whose result is the address of a string literal. */ diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll index 96a01954d17f..7bea8178d141 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll @@ -377,6 +377,10 @@ CppType getInstructionResultType(TStageInstruction instr) { result = getVoidType() } +IRType getInstructionResultIRType(Instruction instr) { + result = instr.getResultLanguageType().getIRType() +} + predicate getInstructionOpcode(Opcode opcode, TStageInstruction instr) { getInstructionTranslatedElement(instr).hasInstruction(opcode, getInstructionTag(instr), _) or 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 3f4039ebb346..a43595b08e08 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 @@ -538,6 +538,11 @@ class TranslatedResultCopy extends TranslatedExpr, TTranslatedResultCopy { final override predicate producesExprResult() { any() } private TranslatedCoreExpr getOperand() { result.getExpr() = expr } + + override predicate handlesDestructorsExplicitly() { + // The destructor calls will already have been generated by the translation of `expr`. + any() + } } class TranslatedCommaExpr extends TranslatedNonConstantExpr { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index 189ffce2903e..c7e40da1e17c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -247,8 +247,7 @@ class Instruction extends Construction::TStageInstruction { * Gets the type of the result produced by this instruction. If the instruction does not produce * a result, its result type will be `IRVoidType`. */ - cached - final IRType getResultIRType() { result = this.getResultLanguageType().getIRType() } + final IRType getResultIRType() { result = Construction::getInstructionResultIRType(this) } /** * Gets the type of the result produced by this instruction. If the @@ -995,9 +994,8 @@ class ConstantInstruction extends ConstantValueInstruction { */ class IntegerConstantInstruction extends ConstantInstruction { IntegerConstantInstruction() { - exists(IRType resultType | - resultType = this.getResultIRType() and - (resultType instanceof IRIntegerType or resultType instanceof IRBooleanType) + exists(IRType resultType | resultType = this.getResultIRType() | + resultType instanceof IRIntegerType or resultType instanceof IRBooleanType ) } } @@ -1009,6 +1007,17 @@ class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { this.getResultIRType() instanceof IRFloatingPointType } } +/** + * An instruction whose result is a constant value of a pointer type. + */ +class PointerConstantInstruction extends ConstantInstruction { + PointerConstantInstruction() { + exists(IRType resultType | resultType = this.getResultIRType() | + resultType instanceof IRAddressType or resultType instanceof IRFunctionAddressType + ) + } +} + /** * An instruction whose result is the address of a string literal. */ diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index 209c42726b7d..d2e68c733041 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -429,6 +429,11 @@ private module Cached { instr = unreachedInstruction(_) and result = Language::getVoidType() } + cached + IRType getInstructionResultIRType(Instruction instr) { + result = instr.getResultLanguageType().getIRType() + } + /** * Holds if `opcode` is the opcode that specifies the operation performed by `instr`. * diff --git a/cpp/ql/test/library-tests/controlflow/guards-ir/tests.expected b/cpp/ql/test/library-tests/controlflow/guards-ir/tests.expected index cc29559d5d31..943d7028a5d2 100644 --- a/cpp/ql/test/library-tests/controlflow/guards-ir/tests.expected +++ b/cpp/ql/test/library-tests/controlflow/guards-ir/tests.expected @@ -56,6 +56,8 @@ astGuardsCompare | 17 | y < 1+1 when ... > ... is false | | 17 | y >= 1+1 when ... && ... is true | | 17 | y >= 1+1 when ... > ... is true | +| 18 | call to get != 0 when call to get is true | +| 18 | call to get == 0 when call to get is false | | 26 | 0 < x+0 when ... > ... is true | | 26 | 0 >= x+0 when ... > ... is false | | 26 | x < 0+1 when ... > ... is false | @@ -487,6 +489,7 @@ astGuardsEnsure_const | test.c:109:9:109:23 | ... \|\| ... | test.c:109:9:109:9 | x | != | 0 | 113 | 113 | | test.c:175:13:175:32 | ... == ... | test.c:175:13:175:15 | call to foo | != | 0 | 175 | 175 | | test.c:175:13:175:32 | ... == ... | test.c:175:13:175:15 | call to foo | == | 0 | 175 | 175 | +| test.cpp:18:8:18:10 | call to get | test.cpp:18:8:18:10 | call to get | != | 0 | 19 | 19 | | test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 30 | 30 | | test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 34 | 34 | | test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | -1 | 30 | 30 | @@ -545,6 +548,8 @@ irGuardsCompare | 17 | y < 2 when CompareGT: ... > ... is false | | 17 | y >= 1+1 when CompareGT: ... > ... is true | | 17 | y >= 2 when CompareGT: ... > ... is true | +| 18 | call to get != 0 when CompareNE: (bool)... is true | +| 18 | call to get == 0 when CompareNE: (bool)... is false | | 26 | 0 < x+0 when CompareGT: ... > ... is true | | 26 | 0 >= x+0 when CompareGT: ... > ... is false | | 26 | x < 0+1 when CompareGT: ... > ... is false | @@ -996,6 +1001,7 @@ irGuardsEnsure_const | test.c:109:19:109:23 | CompareLT: ... < ... | test.c:109:19:109:19 | Load: y | >= | 0 | 113 | 113 | | test.c:175:13:175:32 | CompareEQ: ... == ... | test.c:175:13:175:15 | Call: call to foo | != | 0 | 175 | 175 | | test.c:175:13:175:32 | CompareEQ: ... == ... | test.c:175:13:175:15 | Call: call to foo | == | 0 | 175 | 175 | +| test.cpp:18:8:18:12 | CompareNE: (bool)... | test.cpp:18:8:18:10 | Call: call to get | != | 0 | 19 | 19 | | test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | != | -1 | 34 | 34 | | test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | == | -1 | 30 | 30 | | test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | == | -1 | 32 | 32 | diff --git a/cpp/ql/test/library-tests/controlflow/guards/Guards.expected b/cpp/ql/test/library-tests/controlflow/guards/Guards.expected index 6eebc960ce3c..08a8a9281bb1 100644 --- a/cpp/ql/test/library-tests/controlflow/guards/Guards.expected +++ b/cpp/ql/test/library-tests/controlflow/guards/Guards.expected @@ -32,3 +32,7 @@ | test.cpp:61:10:61:10 | i | | test.cpp:74:10:74:10 | i | | test.cpp:84:10:84:10 | i | +| test.cpp:93:6:93:6 | c | +| test.cpp:99:6:99:6 | f | +| test.cpp:105:6:105:14 | ... != ... | +| test.cpp:111:6:111:14 | ... != ... | diff --git a/cpp/ql/test/library-tests/controlflow/guards/GuardsCompare.expected b/cpp/ql/test/library-tests/controlflow/guards/GuardsCompare.expected index b88856d90cf0..756140604e13 100644 --- a/cpp/ql/test/library-tests/controlflow/guards/GuardsCompare.expected +++ b/cpp/ql/test/library-tests/controlflow/guards/GuardsCompare.expected @@ -22,6 +22,8 @@ | 17 | y >= 1+1 when ... > ... is true | | 17 | y >= 2 when ... && ... is true | | 17 | y >= 2 when ... > ... is true | +| 18 | call to get != 0 when call to get is true | +| 18 | call to get == 0 when call to get is false | | 26 | 0 < x+0 when ... > ... is true | | 26 | 0 >= x+0 when ... > ... is false | | 26 | x < 0+1 when ... > ... is false | @@ -107,6 +109,8 @@ | 85 | y != 0+0 when ... && ... is true | | 85 | y == 0 when ... != ... is false | | 85 | y == 0+0 when ... != ... is false | +| 93 | c != 0 when c is true | +| 93 | c == 0 when c is false | | 94 | 0 != x+0 when ... != ... is true | | 94 | 0 == x+0 when ... != ... is false | | 94 | x != 0 when ... != ... is true | @@ -119,6 +123,10 @@ | 102 | j < 10+0 when ... < ... is true | | 102 | j >= 10 when ... < ... is false | | 102 | j >= 10+0 when ... < ... is false | +| 105 | 0.0 != f+0 when ... != ... is true | +| 105 | 0.0 == f+0 when ... != ... is false | +| 105 | f != 0.0+0 when ... != ... is true | +| 105 | f == 0.0+0 when ... != ... is false | | 109 | 0 != x+0 when ... == ... is false | | 109 | 0 != x+0 when ... \|\| ... is false | | 109 | 0 < y+1 when ... < ... is false | @@ -137,3 +145,7 @@ | 109 | y >= 0 when ... \|\| ... is false | | 109 | y >= 0+0 when ... < ... is false | | 109 | y >= 0+0 when ... \|\| ... is false | +| 111 | 0.0 != i+0 when ... != ... is true | +| 111 | 0.0 == i+0 when ... != ... is false | +| 111 | i != 0.0+0 when ... != ... is true | +| 111 | i == 0.0+0 when ... != ... is false | diff --git a/cpp/ql/test/library-tests/controlflow/guards/GuardsControl.expected b/cpp/ql/test/library-tests/controlflow/guards/GuardsControl.expected index fbfaff9acf6b..62d9b0a12294 100644 --- a/cpp/ql/test/library-tests/controlflow/guards/GuardsControl.expected +++ b/cpp/ql/test/library-tests/controlflow/guards/GuardsControl.expected @@ -90,3 +90,7 @@ | test.cpp:61:10:61:10 | i | Case[1] | 65 | 66 | | test.cpp:74:10:74:10 | i | Case[0..10] | 75 | 77 | | test.cpp:74:10:74:10 | i | Case[11..20] | 78 | 79 | +| test.cpp:93:6:93:6 | c | true | 93 | 94 | +| test.cpp:99:6:99:6 | f | true | 99 | 100 | +| test.cpp:105:6:105:14 | ... != ... | true | 105 | 106 | +| test.cpp:111:6:111:14 | ... != ... | true | 111 | 112 | diff --git a/cpp/ql/test/library-tests/controlflow/guards/GuardsEnsure.expected b/cpp/ql/test/library-tests/controlflow/guards/GuardsEnsure.expected index e5328aefa629..f9eaced1276a 100644 --- a/cpp/ql/test/library-tests/controlflow/guards/GuardsEnsure.expected +++ b/cpp/ql/test/library-tests/controlflow/guards/GuardsEnsure.expected @@ -1,3 +1,4 @@ +binary | test.c:7:9:7:13 | ... > ... | test.c:7:9:7:9 | x | < | test.c:7:13:7:13 | 0 | 1 | 10 | 11 | | test.c:7:9:7:13 | ... > ... | test.c:7:9:7:9 | x | >= | test.c:7:13:7:13 | 0 | 1 | 7 | 9 | | test.c:7:9:7:13 | ... > ... | test.c:7:13:7:13 | 0 | < | test.c:7:9:7:9 | x | 0 | 7 | 9 | @@ -154,3 +155,94 @@ | test.cpp:31:7:31:13 | ... == ... | test.cpp:31:12:31:13 | - ... | != | test.cpp:31:7:31:7 | x | 0 | 34 | 34 | | test.cpp:31:7:31:13 | ... == ... | test.cpp:31:12:31:13 | - ... | == | test.cpp:31:7:31:7 | x | 0 | 30 | 30 | | test.cpp:31:7:31:13 | ... == ... | test.cpp:31:12:31:13 | - ... | == | test.cpp:31:7:31:7 | x | 0 | 31 | 32 | +| test.cpp:105:6:105:14 | ... != ... | test.cpp:105:6:105:6 | f | != | test.cpp:105:11:105:14 | 0.0 | 0 | 105 | 106 | +| test.cpp:105:6:105:14 | ... != ... | test.cpp:105:11:105:14 | 0.0 | != | test.cpp:105:6:105:6 | f | 0 | 105 | 106 | +| test.cpp:111:6:111:14 | ... != ... | test.cpp:111:6:111:6 | i | != | test.cpp:111:11:111:14 | 0.0 | 0 | 111 | 112 | +| test.cpp:111:6:111:14 | ... != ... | test.cpp:111:11:111:14 | 0.0 | != | test.cpp:111:6:111:6 | i | 0 | 111 | 112 | +unary +| test.c:7:9:7:13 | ... > ... | test.c:7:9:7:9 | x | < | 1 | 10 | 11 | +| test.c:7:9:7:13 | ... > ... | test.c:7:9:7:9 | x | >= | 1 | 7 | 9 | +| test.c:17:8:17:12 | ... < ... | test.c:17:8:17:8 | x | < | 0 | 17 | 17 | +| test.c:17:8:17:12 | ... < ... | test.c:17:8:17:8 | x | < | 0 | 18 | 18 | +| test.c:17:8:17:21 | ... && ... | test.c:17:8:17:8 | x | < | 0 | 18 | 18 | +| test.c:17:8:17:21 | ... && ... | test.c:17:17:17:17 | y | >= | 2 | 18 | 18 | +| test.c:17:17:17:21 | ... > ... | test.c:17:17:17:17 | y | >= | 2 | 18 | 18 | +| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 2 | 2 | +| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 31 | 34 | +| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 34 | 34 | +| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 39 | 42 | +| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 42 | 42 | +| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 42 | 44 | +| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 45 | 45 | +| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 45 | 47 | +| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 51 | 53 | +| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 56 | 58 | +| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 58 | 58 | +| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 58 | 66 | +| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | 1 | 62 | 62 | +| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | >= | 1 | 26 | 28 | +| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | < | 10 | 34 | 34 | +| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 2 | 2 | +| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 39 | 42 | +| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 42 | 42 | +| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 42 | 44 | +| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 45 | 45 | +| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 45 | 47 | +| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 51 | 53 | +| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 56 | 58 | +| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 58 | 58 | +| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 58 | 66 | +| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | 10 | 62 | 62 | +| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | 10 | 42 | 42 | +| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | 10 | 42 | 44 | +| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | 10 | 45 | 45 | +| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | 10 | 45 | 47 | +| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | 10 | 51 | 53 | +| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | < | 1 | 42 | 42 | +| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | < | 1 | 51 | 53 | +| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | >= | 1 | 45 | 45 | +| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | >= | 1 | 45 | 47 | +| test.c:45:16:45:20 | ... > ... | test.c:45:16:45:16 | y | >= | 1 | 45 | 47 | +| test.c:58:9:58:14 | ... == ... | test.c:58:9:58:9 | x | != | 0 | 58 | 58 | +| test.c:58:9:58:14 | ... == ... | test.c:58:9:58:9 | x | != | 0 | 62 | 62 | +| test.c:58:9:58:23 | ... \|\| ... | test.c:58:9:58:9 | x | != | 0 | 62 | 62 | +| test.c:58:9:58:23 | ... \|\| ... | test.c:58:19:58:19 | y | >= | 0 | 62 | 62 | +| test.c:58:19:58:23 | ... < ... | test.c:58:19:58:19 | y | >= | 0 | 62 | 62 | +| test.c:75:9:75:14 | ... == ... | test.c:75:9:75:9 | x | != | 0 | 78 | 79 | +| test.c:75:9:75:14 | ... == ... | test.c:75:9:75:9 | x | == | 0 | 75 | 77 | +| test.c:85:8:85:13 | ... == ... | test.c:85:8:85:8 | x | == | 0 | 85 | 85 | +| test.c:85:8:85:13 | ... == ... | test.c:85:8:85:8 | x | == | 0 | 86 | 86 | +| test.c:85:8:85:23 | ... && ... | test.c:85:8:85:8 | x | == | 0 | 86 | 86 | +| test.c:85:8:85:23 | ... && ... | test.c:85:18:85:18 | y | != | 0 | 86 | 86 | +| test.c:85:18:85:23 | ... != ... | test.c:85:18:85:18 | y | != | 0 | 86 | 86 | +| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | != | 0 | 94 | 96 | +| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | 0 | 70 | 70 | +| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | 0 | 99 | 102 | +| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | 0 | 102 | 102 | +| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | 0 | 107 | 109 | +| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | 0 | 109 | 109 | +| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | 0 | 109 | 117 | +| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | 0 | 113 | 113 | +| test.c:102:16:102:21 | ... < ... | test.c:102:16:102:16 | j | < | 10 | 102 | 102 | +| test.c:102:16:102:21 | ... < ... | test.c:102:16:102:16 | j | >= | 10 | 70 | 70 | +| test.c:102:16:102:21 | ... < ... | test.c:102:16:102:16 | j | >= | 10 | 107 | 109 | +| test.c:102:16:102:21 | ... < ... | test.c:102:16:102:16 | j | >= | 10 | 109 | 109 | +| test.c:102:16:102:21 | ... < ... | test.c:102:16:102:16 | j | >= | 10 | 109 | 117 | +| test.c:102:16:102:21 | ... < ... | test.c:102:16:102:16 | j | >= | 10 | 113 | 113 | +| test.c:109:9:109:14 | ... == ... | test.c:109:9:109:9 | x | != | 0 | 109 | 109 | +| test.c:109:9:109:14 | ... == ... | test.c:109:9:109:9 | x | != | 0 | 113 | 113 | +| test.c:109:9:109:23 | ... \|\| ... | test.c:109:9:109:9 | x | != | 0 | 113 | 113 | +| test.c:109:9:109:23 | ... \|\| ... | test.c:109:19:109:19 | y | >= | 0 | 113 | 113 | +| test.c:109:19:109:23 | ... < ... | test.c:109:19:109:19 | y | >= | 0 | 113 | 113 | +| test.cpp:18:8:18:10 | call to get | test.cpp:18:8:18:10 | call to get | != | 0 | 19 | 19 | +| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 30 | 30 | +| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 34 | 34 | +| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | -1 | 30 | 30 | +| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | -1 | 31 | 32 | +| test.cpp:61:10:61:10 | i | test.cpp:61:10:61:10 | i | == | 0 | 62 | 64 | +| test.cpp:61:10:61:10 | i | test.cpp:61:10:61:10 | i | == | 1 | 65 | 66 | +| test.cpp:74:10:74:10 | i | test.cpp:74:10:74:10 | i | < | 11 | 75 | 77 | +| test.cpp:74:10:74:10 | i | test.cpp:74:10:74:10 | i | < | 21 | 78 | 79 | +| test.cpp:74:10:74:10 | i | test.cpp:74:10:74:10 | i | >= | 0 | 75 | 77 | +| test.cpp:74:10:74:10 | i | test.cpp:74:10:74:10 | i | >= | 11 | 78 | 79 | +| test.cpp:93:6:93:6 | c | test.cpp:93:6:93:6 | c | != | 0 | 93 | 94 | diff --git a/cpp/ql/test/library-tests/controlflow/guards/GuardsEnsure.ql b/cpp/ql/test/library-tests/controlflow/guards/GuardsEnsure.ql index 94aaade03ed5..59f8a399c6d4 100644 --- a/cpp/ql/test/library-tests/controlflow/guards/GuardsEnsure.ql +++ b/cpp/ql/test/library-tests/controlflow/guards/GuardsEnsure.ql @@ -7,8 +7,9 @@ import cpp import semmle.code.cpp.controlflow.Guards -from GuardCondition guard, Expr left, Expr right, int k, int start, int end, string op -where +query predicate binary( + GuardCondition guard, Expr left, string op, Expr right, int k, int start, int end +) { exists(BasicBlock block | guard.ensuresLt(left, right, k, block, true) and op = "<" or @@ -20,4 +21,18 @@ where | block.hasLocationInfo(_, start, _, end, _) ) -select guard, left, op, right, k, start, end +} + +query predicate unary(GuardCondition guard, Expr left, string op, int k, int start, int end) { + exists(BasicBlock block | + guard.ensuresLt(left, k, block, true) and op = "<" + or + guard.ensuresLt(left, k, block, false) and op = ">=" + or + guard.ensuresEq(left, k, block, true) and op = "==" + or + guard.ensuresEq(left, k, block, false) and op = "!=" + | + block.hasLocationInfo(_, start, _, end, _) + ) +} diff --git a/cpp/ql/test/library-tests/controlflow/guards/test.cpp b/cpp/ql/test/library-tests/controlflow/guards/test.cpp index 3a60f5f026e7..84d02ca4efa5 100644 --- a/cpp/ql/test/library-tests/controlflow/guards/test.cpp +++ b/cpp/ql/test/library-tests/controlflow/guards/test.cpp @@ -85,4 +85,30 @@ void test_switches_default(int i) { default: use1(i); } -} \ No newline at end of file +} + +void use(...); + +void pointer_comparison(char* c) { + if(c) { + use(c); + } +} + +void implicit_float_comparison(float f) { + if(f) { + use(f); + } +} + +void explicit_float_comparison(float f) { + if(f != 0.0f) { + use(f); + } +} + +void int_float_comparison(int i) { + if(i != 0.0f) { + use(i); + } +} diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index e0d2da046b2e..28c1398d90bc 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -19565,12 +19565,6 @@ ir.cpp: # 2216| Type = [PlainCharType] char # 2216| Value = [CharLiteral] 97 # 2216| ValueCategory = prvalue -# 2215| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor -# 2215| Type = [VoidType] void -# 2215| ValueCategory = prvalue -# 2215| getQualifier(): [VariableAccess] y -# 2215| Type = [Class] ClassWithDestructor -# 2215| ValueCategory = lvalue # 2215| getImplicitDestructorCall(0): [DestructorCall] call to ~vector # 2215| Type = [VoidType] void # 2215| ValueCategory = prvalue @@ -19580,6 +19574,12 @@ ir.cpp: # 2215| getUpdate().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference) # 2215| Type = [ClassTemplateInstantiation,Struct] iterator # 2215| ValueCategory = lvalue +# 2215| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor +# 2215| Type = [VoidType] void +# 2215| ValueCategory = prvalue +# 2215| getQualifier(): [VariableAccess] y +# 2215| Type = [Class] ClassWithDestructor +# 2215| ValueCategory = lvalue # 2218| getStmt(6): [RangeBasedForStmt] for(...:...) ... # 2218| getInitialization(): [DeclStmt] declaration # 2218| getDeclarationEntry(0): [VariableDeclarationEntry] definition of ys @@ -19746,12 +19746,6 @@ ir.cpp: # 2233| getQualifier(): [VariableAccess] x # 2233| Type = [Class] ClassWithDestructor # 2233| ValueCategory = lvalue -# 2218| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor -# 2218| Type = [VoidType] void -# 2218| ValueCategory = prvalue -# 2218| getQualifier(): [VariableAccess] y -# 2218| Type = [Class] ClassWithDestructor -# 2218| ValueCategory = lvalue # 2218| getImplicitDestructorCall(0): [DestructorCall] call to ~vector # 2218| Type = [VoidType] void # 2218| ValueCategory = prvalue @@ -19761,6 +19755,12 @@ ir.cpp: # 2218| getUpdate().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference) # 2218| Type = [ClassTemplateInstantiation,Struct] iterator # 2218| ValueCategory = lvalue +# 2218| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor +# 2218| Type = [VoidType] void +# 2218| ValueCategory = prvalue +# 2218| getQualifier(): [VariableAccess] y +# 2218| Type = [Class] ClassWithDestructor +# 2218| ValueCategory = lvalue # 2224| getStmt(7): [RangeBasedForStmt] for(...:...) ... # 2224| getInitialization(): [DeclStmt] declaration # 2224| getDeclarationEntry(0): [VariableDeclarationEntry] definition of ys @@ -20038,12 +20038,6 @@ ir.cpp: # 2232| getQualifier(): [VariableAccess] z1 # 2232| Type = [Class] ClassWithDestructor # 2232| ValueCategory = lvalue -# 2229| getImplicitDestructorCall(2): [DestructorCall] call to ~ClassWithDestructor -# 2229| Type = [VoidType] void -# 2229| ValueCategory = prvalue -# 2229| getQualifier(): [VariableAccess] y -# 2229| Type = [Class] ClassWithDestructor -# 2229| ValueCategory = lvalue # 2229| getImplicitDestructorCall(0): [DestructorCall] call to ~vector # 2229| Type = [VoidType] void # 2229| ValueCategory = prvalue @@ -20053,6 +20047,12 @@ ir.cpp: # 2229| getUpdate().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference) # 2229| Type = [ClassTemplateInstantiation,Struct] iterator # 2229| ValueCategory = lvalue +# 2229| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor +# 2229| Type = [VoidType] void +# 2229| ValueCategory = prvalue +# 2229| getQualifier(): [VariableAccess] y +# 2229| Type = [Class] ClassWithDestructor +# 2229| ValueCategory = lvalue # 2233| getStmt(9): [ReturnStmt] return ... # 2233| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor # 2233| Type = [VoidType] void @@ -20662,15 +20662,15 @@ ir.cpp: # 2309| getQualifier(): [VariableAccess] s2 # 2309| Type = [Struct] String # 2309| ValueCategory = lvalue -# 2307| getImplicitDestructorCall(1): [DestructorCall] call to ~String +# 2307| getUpdate().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference) +# 2307| Type = [ClassTemplateInstantiation,Struct] iterator +# 2307| ValueCategory = lvalue +# 2307| getImplicitDestructorCall(0): [DestructorCall] call to ~String # 2307| Type = [VoidType] void # 2307| ValueCategory = prvalue # 2307| getQualifier(): [VariableAccess] s # 2307| Type = [Struct] String # 2307| ValueCategory = lvalue -# 2307| getUpdate().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference) -# 2307| Type = [ClassTemplateInstantiation,Struct] iterator -# 2307| ValueCategory = lvalue # 2311| getStmt(3): [ForStmt] for(...;...;...) ... # 2311| getInitialization(): [DeclStmt] declaration # 2311| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s 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 3d3a56e790e9..68e5d36d2062 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -15372,7 +15372,7 @@ ir.cpp: #-----| True -> Block 2 # 2198| Block 1 -# 2198| m2198_9(unknown) = Phi : from 13:~m2233_5, from 19:~m2233_13, from 23:~m2233_22 +# 2198| m2198_9(unknown) = Phi : from 14:~m2233_5, from 19:~m2233_13, from 23:~m2233_22 # 2198| v2198_10(void) = ReturnVoid : # 2198| v2198_11(void) = AliasedUse : ~m2198_9 # 2198| v2198_12(void) = ExitFunction : @@ -15524,8 +15524,8 @@ ir.cpp: #-----| Goto -> Block 8 # 2215| Block 8 -# 2215| m2215_40(iterator) = Phi : from 7:m2215_32, from 9:m2215_72 -# 2215| m2215_41(unknown) = Phi : from 7:~m2215_39, from 9:~m2215_63 +# 2215| m2215_40(iterator) = Phi : from 7:m2215_32, from 9:m2215_64 +# 2215| m2215_41(unknown) = Phi : from 7:~m2215_39, from 9:~m2215_69 # 2215| r2215_42(glval>) = VariableAddress[(__begin)] : #-----| r0_7(glval>) = Convert : r2215_42 # 2215| r2215_43(glval) = FunctionAddress[operator!=] : @@ -15567,21 +15567,21 @@ ir.cpp: # 2216| v2216_7(void) = ^IndirectReadSideEffect[-1] : &:r2216_1, m2215_58 # 2216| m2216_8(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2216_1 # 2216| m2216_9(ClassWithDestructor) = Chi : total:m2215_58, partial:m2216_8 -# 2215| r2215_59(glval) = VariableAddress[y] : -# 2215| r2215_60(glval) = FunctionAddress[~ClassWithDestructor] : -# 2215| v2215_61(void) = Call[~ClassWithDestructor] : func:r2215_60, this:r2215_59 -# 2215| m2215_62(unknown) = ^CallSideEffect : ~m2216_6 -# 2215| m2215_63(unknown) = Chi : total:m2216_6, partial:m2215_62 -# 2215| v2215_64(void) = ^IndirectReadSideEffect[-1] : &:r2215_59, m2216_9 -# 2215| m2215_65(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2215_59 -# 2215| m2215_66(ClassWithDestructor) = Chi : total:m2216_9, partial:m2215_65 -# 2215| r2215_67(glval>) = VariableAddress[(__begin)] : -# 2215| r2215_68(glval) = FunctionAddress[operator++] : -# 2215| r2215_69(iterator &) = Call[operator++] : func:r2215_68, this:r2215_67 -# 2215| v2215_70(void) = ^IndirectReadSideEffect[-1] : &:r2215_67, m2215_40 -# 2215| m2215_71(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2215_67 -# 2215| m2215_72(iterator) = Chi : total:m2215_40, partial:m2215_71 -# 2215| r2215_73(glval>) = CopyValue : r2215_69 +# 2215| r2215_59(glval>) = VariableAddress[(__begin)] : +# 2215| r2215_60(glval) = FunctionAddress[operator++] : +# 2215| r2215_61(iterator &) = Call[operator++] : func:r2215_60, this:r2215_59 +# 2215| v2215_62(void) = ^IndirectReadSideEffect[-1] : &:r2215_59, m2215_40 +# 2215| m2215_63(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2215_59 +# 2215| m2215_64(iterator) = Chi : total:m2215_40, partial:m2215_63 +# 2215| r2215_65(glval) = VariableAddress[y] : +# 2215| r2215_66(glval) = FunctionAddress[~ClassWithDestructor] : +# 2215| v2215_67(void) = Call[~ClassWithDestructor] : func:r2215_66, this:r2215_65 +# 2215| m2215_68(unknown) = ^CallSideEffect : ~m2216_6 +# 2215| m2215_69(unknown) = Chi : total:m2216_6, partial:m2215_68 +# 2215| v2215_70(void) = ^IndirectReadSideEffect[-1] : &:r2215_65, m2216_9 +# 2215| m2215_71(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2215_65 +# 2215| m2215_72(ClassWithDestructor) = Chi : total:m2216_9, partial:m2215_71 +# 2215| r2215_73(glval>) = CopyValue : r2215_61 #-----| Goto (back edge) -> Block 8 # 2218| Block 10 @@ -15633,8 +15633,8 @@ ir.cpp: #-----| Goto -> Block 11 # 2218| Block 11 -# 2218| m2218_40(iterator) = Phi : from 10:m2218_32, from 14:m2218_88 -# 2218| m2218_41(unknown) = Phi : from 10:~m2218_39, from 14:~m2218_79 +# 2218| m2218_40(iterator) = Phi : from 10:m2218_32, from 12:m2218_58 +# 2218| m2218_41(unknown) = Phi : from 10:~m2218_39, from 12:~m2218_63 # 2218| r2218_42(glval>) = VariableAddress[(__begin)] : #-----| r0_24(glval>) = Convert : r2218_42 # 2218| r2218_43(glval) = FunctionAddress[operator!=] : @@ -15656,26 +15656,44 @@ ir.cpp: #-----| v0_32(void) = ^IndirectReadSideEffect[-1] : &:r0_24, m2218_40 # 2218| v2218_52(void) = ConditionalBranch : r2218_51 #-----| False -> Block 15 -#-----| True -> Block 12 +#-----| True -> Block 13 # 2218| Block 12 -# 2218| r2218_53(glval) = VariableAddress[y] : -# 2218| r2218_54(glval>) = VariableAddress[(__begin)] : -#-----| r0_33(glval>) = Convert : r2218_54 -# 2218| r2218_55(glval) = FunctionAddress[operator*] : -# 2218| r2218_56(ClassWithDestructor &) = Call[operator*] : func:r2218_55, this:r0_33 +# 2218| r2218_53(glval>) = VariableAddress[(__begin)] : +# 2218| r2218_54(glval) = FunctionAddress[operator++] : +# 2218| r2218_55(iterator &) = Call[operator++] : func:r2218_54, this:r2218_53 +# 2218| v2218_56(void) = ^IndirectReadSideEffect[-1] : &:r2218_53, m2218_40 +# 2218| m2218_57(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2218_53 +# 2218| m2218_58(iterator) = Chi : total:m2218_40, partial:m2218_57 +# 2218| r2218_59(glval) = VariableAddress[y] : +# 2218| r2218_60(glval) = FunctionAddress[~ClassWithDestructor] : +# 2218| v2218_61(void) = Call[~ClassWithDestructor] : func:r2218_60, this:r2218_59 +# 2218| m2218_62(unknown) = ^CallSideEffect : ~m2220_5 +# 2218| m2218_63(unknown) = Chi : total:m2220_5, partial:m2218_62 +# 2218| v2218_64(void) = ^IndirectReadSideEffect[-1] : &:r2218_59, m2220_8 +# 2218| m2218_65(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2218_59 +# 2218| m2218_66(ClassWithDestructor) = Chi : total:m2220_8, partial:m2218_65 +# 2218| r2218_67(glval>) = CopyValue : r2218_55 +#-----| Goto (back edge) -> Block 11 + +# 2218| Block 13 +# 2218| r2218_68(glval) = VariableAddress[y] : +# 2218| r2218_69(glval>) = VariableAddress[(__begin)] : +#-----| r0_33(glval>) = Convert : r2218_69 +# 2218| r2218_70(glval) = FunctionAddress[operator*] : +# 2218| r2218_71(ClassWithDestructor &) = Call[operator*] : func:r2218_70, this:r0_33 #-----| v0_34(void) = ^IndirectReadSideEffect[-1] : &:r0_33, m2218_40 -# 2218| r2218_57(ClassWithDestructor) = Load[?] : &:r2218_56, ~m2218_50 -# 2218| m2218_58(ClassWithDestructor) = Store[y] : &:r2218_53, r2218_57 +# 2218| r2218_72(ClassWithDestructor) = Load[?] : &:r2218_71, ~m2218_50 +# 2218| m2218_73(ClassWithDestructor) = Store[y] : &:r2218_68, r2218_72 # 2219| r2219_1(glval) = VariableAddress[y] : # 2219| r2219_2(glval) = FunctionAddress[set_x] : # 2219| r2219_3(char) = Constant[97] : # 2219| v2219_4(void) = Call[set_x] : func:r2219_2, this:r2219_1, 0:r2219_3 # 2219| m2219_5(unknown) = ^CallSideEffect : ~m2218_50 # 2219| m2219_6(unknown) = Chi : total:m2218_50, partial:m2219_5 -# 2219| v2219_7(void) = ^IndirectReadSideEffect[-1] : &:r2219_1, m2218_58 +# 2219| v2219_7(void) = ^IndirectReadSideEffect[-1] : &:r2219_1, m2218_73 # 2219| m2219_8(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2219_1 -# 2219| m2219_9(ClassWithDestructor) = Chi : total:m2218_58, partial:m2219_8 +# 2219| m2219_9(ClassWithDestructor) = Chi : total:m2218_73, partial:m2219_8 # 2220| r2220_1(glval) = VariableAddress[y] : # 2220| r2220_2(glval) = FunctionAddress[get_x] : # 2220| r2220_3(char) = Call[get_x] : func:r2220_2, this:r2220_1 @@ -15688,55 +15706,37 @@ ir.cpp: # 2220| r2220_10(int) = Constant[98] : # 2220| r2220_11(bool) = CompareEQ : r2220_9, r2220_10 # 2220| v2220_12(void) = ConditionalBranch : r2220_11 -#-----| False -> Block 14 -#-----| True -> Block 13 +#-----| False -> Block 12 +#-----| True -> Block 14 -# 2221| Block 13 +# 2221| Block 14 # 2221| v2221_1(void) = NoOp : -# 2218| r2218_59(glval) = VariableAddress[y] : -# 2218| r2218_60(glval) = FunctionAddress[~ClassWithDestructor] : -# 2218| v2218_61(void) = Call[~ClassWithDestructor] : func:r2218_60, this:r2218_59 -# 2218| m2218_62(unknown) = ^CallSideEffect : ~m2220_5 -# 2218| m2218_63(unknown) = Chi : total:m2220_5, partial:m2218_62 -# 2218| v2218_64(void) = ^IndirectReadSideEffect[-1] : &:r2218_59, m2220_8 -# 2218| m2218_65(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2218_59 -# 2218| m2218_66(ClassWithDestructor) = Chi : total:m2220_8, partial:m2218_65 -# 2218| r2218_67(glval>) = VariableAddress[ys] : -# 2218| r2218_68(glval) = FunctionAddress[~vector] : -# 2218| v2218_69(void) = Call[~vector] : func:r2218_68, this:r2218_67 -# 2218| m2218_70(unknown) = ^CallSideEffect : ~m2218_63 -# 2218| m2218_71(unknown) = Chi : total:m2218_63, partial:m2218_70 -# 2218| v2218_72(void) = ^IndirectReadSideEffect[-1] : &:r2218_67, ~m2218_71 -# 2218| m2218_73(vector) = ^IndirectMayWriteSideEffect[-1] : &:r2218_67 -# 2218| m2218_74(unknown) = Chi : total:m2218_71, partial:m2218_73 +# 2218| r2218_74(glval) = VariableAddress[y] : +# 2218| r2218_75(glval) = FunctionAddress[~ClassWithDestructor] : +# 2218| v2218_76(void) = Call[~ClassWithDestructor] : func:r2218_75, this:r2218_74 +# 2218| m2218_77(unknown) = ^CallSideEffect : ~m2220_5 +# 2218| m2218_78(unknown) = Chi : total:m2220_5, partial:m2218_77 +# 2218| v2218_79(void) = ^IndirectReadSideEffect[-1] : &:r2218_74, m2220_8 +# 2218| m2218_80(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2218_74 +# 2218| m2218_81(ClassWithDestructor) = Chi : total:m2220_8, partial:m2218_80 +# 2218| r2218_82(glval>) = VariableAddress[ys] : +# 2218| r2218_83(glval) = FunctionAddress[~vector] : +# 2218| v2218_84(void) = Call[~vector] : func:r2218_83, this:r2218_82 +# 2218| m2218_85(unknown) = ^CallSideEffect : ~m2218_78 +# 2218| m2218_86(unknown) = Chi : total:m2218_78, partial:m2218_85 +# 2218| v2218_87(void) = ^IndirectReadSideEffect[-1] : &:r2218_82, ~m2218_86 +# 2218| m2218_88(vector) = ^IndirectMayWriteSideEffect[-1] : &:r2218_82 +# 2218| m2218_89(unknown) = Chi : total:m2218_86, partial:m2218_88 # 2233| r2233_1(glval) = VariableAddress[x] : # 2233| r2233_2(glval) = FunctionAddress[~ClassWithDestructor] : # 2233| v2233_3(void) = Call[~ClassWithDestructor] : func:r2233_2, this:r2233_1 -# 2233| m2233_4(unknown) = ^CallSideEffect : ~m2218_74 -# 2233| m2233_5(unknown) = Chi : total:m2218_74, partial:m2233_4 +# 2233| m2233_4(unknown) = ^CallSideEffect : ~m2218_89 +# 2233| m2233_5(unknown) = Chi : total:m2218_89, partial:m2233_4 # 2233| v2233_6(void) = ^IndirectReadSideEffect[-1] : &:r2233_1, m2214_8 # 2233| m2233_7(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2233_1 # 2233| m2233_8(ClassWithDestructor) = Chi : total:m2214_8, partial:m2233_7 #-----| Goto -> Block 1 -# 2218| Block 14 -# 2218| r2218_75(glval) = VariableAddress[y] : -# 2218| r2218_76(glval) = FunctionAddress[~ClassWithDestructor] : -# 2218| v2218_77(void) = Call[~ClassWithDestructor] : func:r2218_76, this:r2218_75 -# 2218| m2218_78(unknown) = ^CallSideEffect : ~m2220_5 -# 2218| m2218_79(unknown) = Chi : total:m2220_5, partial:m2218_78 -# 2218| v2218_80(void) = ^IndirectReadSideEffect[-1] : &:r2218_75, m2220_8 -# 2218| m2218_81(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2218_75 -# 2218| m2218_82(ClassWithDestructor) = Chi : total:m2220_8, partial:m2218_81 -# 2218| r2218_83(glval>) = VariableAddress[(__begin)] : -# 2218| r2218_84(glval) = FunctionAddress[operator++] : -# 2218| r2218_85(iterator &) = Call[operator++] : func:r2218_84, this:r2218_83 -# 2218| v2218_86(void) = ^IndirectReadSideEffect[-1] : &:r2218_83, m2218_40 -# 2218| m2218_87(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2218_83 -# 2218| m2218_88(iterator) = Chi : total:m2218_40, partial:m2218_87 -# 2218| r2218_89(glval>) = CopyValue : r2218_85 -#-----| Goto (back edge) -> Block 11 - # 2224| Block 15 # 2224| r2224_1(glval>) = VariableAddress[ys] : # 2224| m2224_2(vector) = Uninitialized[ys] : &:r2224_1 @@ -15895,8 +15895,8 @@ ir.cpp: #-----| Goto -> Block 21 # 2229| Block 21 -# 2229| m2229_40(iterator) = Phi : from 20:m2229_32, from 22:m2229_72 -# 2229| m2229_41(unknown) = Phi : from 20:~m2229_39, from 22:~m2229_63 +# 2229| m2229_40(iterator) = Phi : from 20:m2229_32, from 22:m2229_64 +# 2229| m2229_41(unknown) = Phi : from 20:~m2229_39, from 22:~m2229_69 # 2229| r2229_42(glval>) = VariableAddress[(__begin)] : #-----| r0_58(glval>) = Convert : r2229_42 # 2229| r2229_43(glval) = FunctionAddress[operator!=] : @@ -15961,21 +15961,21 @@ ir.cpp: # 2232| v2232_14(void) = ^IndirectReadSideEffect[-1] : &:r2232_9, m2230_8 # 2232| m2232_15(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2232_9 # 2232| m2232_16(ClassWithDestructor) = Chi : total:m2230_8, partial:m2232_15 -# 2229| r2229_59(glval) = VariableAddress[y] : -# 2229| r2229_60(glval) = FunctionAddress[~ClassWithDestructor] : -# 2229| v2229_61(void) = Call[~ClassWithDestructor] : func:r2229_60, this:r2229_59 -# 2229| m2229_62(unknown) = ^CallSideEffect : ~m2232_13 -# 2229| m2229_63(unknown) = Chi : total:m2232_13, partial:m2229_62 -# 2229| v2229_64(void) = ^IndirectReadSideEffect[-1] : &:r2229_59, m2229_58 -# 2229| m2229_65(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2229_59 -# 2229| m2229_66(ClassWithDestructor) = Chi : total:m2229_58, partial:m2229_65 -# 2229| r2229_67(glval>) = VariableAddress[(__begin)] : -# 2229| r2229_68(glval) = FunctionAddress[operator++] : -# 2229| r2229_69(iterator &) = Call[operator++] : func:r2229_68, this:r2229_67 -# 2229| v2229_70(void) = ^IndirectReadSideEffect[-1] : &:r2229_67, m2229_40 -# 2229| m2229_71(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2229_67 -# 2229| m2229_72(iterator) = Chi : total:m2229_40, partial:m2229_71 -# 2229| r2229_73(glval>) = CopyValue : r2229_69 +# 2229| r2229_59(glval>) = VariableAddress[(__begin)] : +# 2229| r2229_60(glval) = FunctionAddress[operator++] : +# 2229| r2229_61(iterator &) = Call[operator++] : func:r2229_60, this:r2229_59 +# 2229| v2229_62(void) = ^IndirectReadSideEffect[-1] : &:r2229_59, m2229_40 +# 2229| m2229_63(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2229_59 +# 2229| m2229_64(iterator) = Chi : total:m2229_40, partial:m2229_63 +# 2229| r2229_65(glval) = VariableAddress[y] : +# 2229| r2229_66(glval) = FunctionAddress[~ClassWithDestructor] : +# 2229| v2229_67(void) = Call[~ClassWithDestructor] : func:r2229_66, this:r2229_65 +# 2229| m2229_68(unknown) = ^CallSideEffect : ~m2232_13 +# 2229| m2229_69(unknown) = Chi : total:m2232_13, partial:m2229_68 +# 2229| v2229_70(void) = ^IndirectReadSideEffect[-1] : &:r2229_65, m2229_58 +# 2229| m2229_71(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2229_65 +# 2229| m2229_72(ClassWithDestructor) = Chi : total:m2229_58, partial:m2229_71 +# 2229| r2229_73(glval>) = CopyValue : r2229_61 #-----| Goto (back edge) -> Block 21 # 2233| Block 23 @@ -16684,8 +16684,8 @@ ir.cpp: #-----| Goto -> Block 4 # 2307| Block 4 -# 2307| m2307_47(iterator) = Phi : from 3:m2307_39, from 5:m2307_89 -# 2307| m2307_48(unknown) = Phi : from 3:~m2307_46, from 5:~m2307_83 +# 2307| m2307_47(iterator) = Phi : from 3:m2307_39, from 5:m2307_81 +# 2307| m2307_48(unknown) = Phi : from 3:~m2307_46, from 5:~m2307_89 # 2307| r2307_49(glval>) = VariableAddress[(__begin)] : #-----| r0_7(glval>) = Convert : r2307_49 # 2307| r2307_50(glval) = FunctionAddress[operator!=] : @@ -16745,21 +16745,21 @@ ir.cpp: # 2309| v2309_6(void) = ^IndirectReadSideEffect[-1] : &:r2309_1, ~m2309_5 # 2309| m2309_7(String) = ^IndirectMayWriteSideEffect[-1] : &:r2309_1 # 2309| m2309_8(unknown) = Chi : total:m2309_5, partial:m2309_7 -# 2307| r2307_76(glval) = VariableAddress[s] : -# 2307| r2307_77(glval) = FunctionAddress[~String] : -# 2307| v2307_78(void) = Call[~String] : func:r2307_77, this:r2307_76 -# 2307| m2307_79(unknown) = ^CallSideEffect : ~m2309_8 -# 2307| m2307_80(unknown) = Chi : total:m2309_8, partial:m2307_79 -# 2307| v2307_81(void) = ^IndirectReadSideEffect[-1] : &:r2307_76, ~m2307_80 -# 2307| m2307_82(String) = ^IndirectMayWriteSideEffect[-1] : &:r2307_76 -# 2307| m2307_83(unknown) = Chi : total:m2307_80, partial:m2307_82 -# 2307| r2307_84(glval>) = VariableAddress[(__begin)] : -# 2307| r2307_85(glval) = FunctionAddress[operator++] : -# 2307| r2307_86(iterator &) = Call[operator++] : func:r2307_85, this:r2307_84 -# 2307| v2307_87(void) = ^IndirectReadSideEffect[-1] : &:r2307_84, m2307_47 -# 2307| m2307_88(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2307_84 -# 2307| m2307_89(iterator) = Chi : total:m2307_47, partial:m2307_88 -# 2307| r2307_90(glval>) = CopyValue : r2307_86 +# 2307| r2307_76(glval>) = VariableAddress[(__begin)] : +# 2307| r2307_77(glval) = FunctionAddress[operator++] : +# 2307| r2307_78(iterator &) = Call[operator++] : func:r2307_77, this:r2307_76 +# 2307| v2307_79(void) = ^IndirectReadSideEffect[-1] : &:r2307_76, m2307_47 +# 2307| m2307_80(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2307_76 +# 2307| m2307_81(iterator) = Chi : total:m2307_47, partial:m2307_80 +# 2307| r2307_82(glval) = VariableAddress[s] : +# 2307| r2307_83(glval) = FunctionAddress[~String] : +# 2307| v2307_84(void) = Call[~String] : func:r2307_83, this:r2307_82 +# 2307| m2307_85(unknown) = ^CallSideEffect : ~m2309_8 +# 2307| m2307_86(unknown) = Chi : total:m2309_8, partial:m2307_85 +# 2307| v2307_87(void) = ^IndirectReadSideEffect[-1] : &:r2307_82, ~m2307_86 +# 2307| m2307_88(String) = ^IndirectMayWriteSideEffect[-1] : &:r2307_82 +# 2307| m2307_89(unknown) = Chi : total:m2307_86, partial:m2307_88 +# 2307| r2307_90(glval>) = CopyValue : r2307_78 #-----| Goto (back edge) -> Block 4 # 2311| Block 6 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 6ff42a28cb35..aadcd33f5104 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -14325,18 +14325,18 @@ ir.cpp: # 2216| mu2216_5(unknown) = ^CallSideEffect : ~m? # 2216| v2216_6(void) = ^IndirectReadSideEffect[-1] : &:r2216_1, ~m? # 2216| mu2216_7(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2216_1 -# 2215| r2215_49(glval) = VariableAddress[y] : -# 2215| r2215_50(glval) = FunctionAddress[~ClassWithDestructor] : -# 2215| v2215_51(void) = Call[~ClassWithDestructor] : func:r2215_50, this:r2215_49 -# 2215| mu2215_52(unknown) = ^CallSideEffect : ~m? -# 2215| v2215_53(void) = ^IndirectReadSideEffect[-1] : &:r2215_49, ~m? -# 2215| mu2215_54(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2215_49 -# 2215| r2215_55(glval>) = VariableAddress[(__begin)] : -# 2215| r2215_56(glval) = FunctionAddress[operator++] : -# 2215| r2215_57(iterator &) = Call[operator++] : func:r2215_56, this:r2215_55 -# 2215| v2215_58(void) = ^IndirectReadSideEffect[-1] : &:r2215_55, ~m? -# 2215| mu2215_59(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2215_55 -# 2215| r2215_60(glval>) = CopyValue : r2215_57 +# 2215| r2215_49(glval>) = VariableAddress[(__begin)] : +# 2215| r2215_50(glval) = FunctionAddress[operator++] : +# 2215| r2215_51(iterator &) = Call[operator++] : func:r2215_50, this:r2215_49 +# 2215| v2215_52(void) = ^IndirectReadSideEffect[-1] : &:r2215_49, ~m? +# 2215| mu2215_53(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2215_49 +# 2215| r2215_54(glval) = VariableAddress[y] : +# 2215| r2215_55(glval) = FunctionAddress[~ClassWithDestructor] : +# 2215| v2215_56(void) = Call[~ClassWithDestructor] : func:r2215_55, this:r2215_54 +# 2215| mu2215_57(unknown) = ^CallSideEffect : ~m? +# 2215| v2215_58(void) = ^IndirectReadSideEffect[-1] : &:r2215_54, ~m? +# 2215| mu2215_59(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2215_54 +# 2215| r2215_60(glval>) = CopyValue : r2215_51 #-----| Goto (back edge) -> Block 11 # 2215| Block 13 @@ -14409,17 +14409,32 @@ ir.cpp: #-----| v0_30(void) = ^IndirectReadSideEffect[-1] : &:r0_23, ~m? # 2218| v2218_42(void) = ConditionalBranch : r2218_41 #-----| False -> Block 20 -#-----| True -> Block 16 +#-----| True -> Block 17 # 2218| Block 16 -# 2218| r2218_43(glval) = VariableAddress[y] : -# 2218| r2218_44(glval>) = VariableAddress[(__begin)] : -#-----| r0_31(glval>) = Convert : r2218_44 -# 2218| r2218_45(glval) = FunctionAddress[operator*] : -# 2218| r2218_46(ClassWithDestructor &) = Call[operator*] : func:r2218_45, this:r0_31 +# 2218| r2218_43(glval>) = VariableAddress[(__begin)] : +# 2218| r2218_44(glval) = FunctionAddress[operator++] : +# 2218| r2218_45(iterator &) = Call[operator++] : func:r2218_44, this:r2218_43 +# 2218| v2218_46(void) = ^IndirectReadSideEffect[-1] : &:r2218_43, ~m? +# 2218| mu2218_47(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2218_43 +# 2218| r2218_48(glval) = VariableAddress[y] : +# 2218| r2218_49(glval) = FunctionAddress[~ClassWithDestructor] : +# 2218| v2218_50(void) = Call[~ClassWithDestructor] : func:r2218_49, this:r2218_48 +# 2218| mu2218_51(unknown) = ^CallSideEffect : ~m? +# 2218| v2218_52(void) = ^IndirectReadSideEffect[-1] : &:r2218_48, ~m? +# 2218| mu2218_53(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2218_48 +# 2218| r2218_54(glval>) = CopyValue : r2218_45 +#-----| Goto (back edge) -> Block 15 + +# 2218| Block 17 +# 2218| r2218_55(glval) = VariableAddress[y] : +# 2218| r2218_56(glval>) = VariableAddress[(__begin)] : +#-----| r0_31(glval>) = Convert : r2218_56 +# 2218| r2218_57(glval) = FunctionAddress[operator*] : +# 2218| r2218_58(ClassWithDestructor &) = Call[operator*] : func:r2218_57, this:r0_31 #-----| v0_32(void) = ^IndirectReadSideEffect[-1] : &:r0_31, ~m? -# 2218| r2218_47(ClassWithDestructor) = Load[?] : &:r2218_46, ~m? -# 2218| mu2218_48(ClassWithDestructor) = Store[y] : &:r2218_43, r2218_47 +# 2218| r2218_59(ClassWithDestructor) = Load[?] : &:r2218_58, ~m? +# 2218| mu2218_60(ClassWithDestructor) = Store[y] : &:r2218_55, r2218_59 # 2219| r2219_1(glval) = VariableAddress[y] : # 2219| r2219_2(glval) = FunctionAddress[set_x] : # 2219| r2219_3(char) = Constant[97] : @@ -14437,23 +14452,23 @@ ir.cpp: # 2220| r2220_8(int) = Constant[98] : # 2220| r2220_9(bool) = CompareEQ : r2220_7, r2220_8 # 2220| v2220_10(void) = ConditionalBranch : r2220_9 -#-----| False -> Block 18 -#-----| True -> Block 17 +#-----| False -> Block 16 +#-----| True -> Block 18 -# 2221| Block 17 +# 2221| Block 18 # 2221| v2221_1(void) = NoOp : -# 2218| r2218_49(glval) = VariableAddress[y] : -# 2218| r2218_50(glval) = FunctionAddress[~ClassWithDestructor] : -# 2218| v2218_51(void) = Call[~ClassWithDestructor] : func:r2218_50, this:r2218_49 -# 2218| mu2218_52(unknown) = ^CallSideEffect : ~m? -# 2218| v2218_53(void) = ^IndirectReadSideEffect[-1] : &:r2218_49, ~m? -# 2218| mu2218_54(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2218_49 -# 2218| r2218_55(glval>) = VariableAddress[ys] : -# 2218| r2218_56(glval) = FunctionAddress[~vector] : -# 2218| v2218_57(void) = Call[~vector] : func:r2218_56, this:r2218_55 -# 2218| mu2218_58(unknown) = ^CallSideEffect : ~m? -# 2218| v2218_59(void) = ^IndirectReadSideEffect[-1] : &:r2218_55, ~m? -# 2218| mu2218_60(vector) = ^IndirectMayWriteSideEffect[-1] : &:r2218_55 +# 2218| r2218_61(glval) = VariableAddress[y] : +# 2218| r2218_62(glval) = FunctionAddress[~ClassWithDestructor] : +# 2218| v2218_63(void) = Call[~ClassWithDestructor] : func:r2218_62, this:r2218_61 +# 2218| mu2218_64(unknown) = ^CallSideEffect : ~m? +# 2218| v2218_65(void) = ^IndirectReadSideEffect[-1] : &:r2218_61, ~m? +# 2218| mu2218_66(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2218_61 +# 2218| r2218_67(glval>) = VariableAddress[ys] : +# 2218| r2218_68(glval) = FunctionAddress[~vector] : +# 2218| v2218_69(void) = Call[~vector] : func:r2218_68, this:r2218_67 +# 2218| mu2218_70(unknown) = ^CallSideEffect : ~m? +# 2218| v2218_71(void) = ^IndirectReadSideEffect[-1] : &:r2218_67, ~m? +# 2218| mu2218_72(vector) = ^IndirectMayWriteSideEffect[-1] : &:r2218_67 # 2233| r2233_1(glval) = VariableAddress[x] : # 2233| r2233_2(glval) = FunctionAddress[~ClassWithDestructor] : # 2233| v2233_3(void) = Call[~ClassWithDestructor] : func:r2233_2, this:r2233_1 @@ -14462,21 +14477,6 @@ ir.cpp: # 2233| mu2233_6(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2233_1 #-----| Goto -> Block 1 -# 2218| Block 18 -# 2218| r2218_61(glval) = VariableAddress[y] : -# 2218| r2218_62(glval) = FunctionAddress[~ClassWithDestructor] : -# 2218| v2218_63(void) = Call[~ClassWithDestructor] : func:r2218_62, this:r2218_61 -# 2218| mu2218_64(unknown) = ^CallSideEffect : ~m? -# 2218| v2218_65(void) = ^IndirectReadSideEffect[-1] : &:r2218_61, ~m? -# 2218| mu2218_66(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2218_61 -# 2218| r2218_67(glval>) = VariableAddress[(__begin)] : -# 2218| r2218_68(glval) = FunctionAddress[operator++] : -# 2218| r2218_69(iterator &) = Call[operator++] : func:r2218_68, this:r2218_67 -# 2218| v2218_70(void) = ^IndirectReadSideEffect[-1] : &:r2218_67, ~m? -# 2218| mu2218_71(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2218_67 -# 2218| r2218_72(glval>) = CopyValue : r2218_69 -#-----| Goto (back edge) -> Block 15 - # 2218| Block 19 # 2218| r2218_73(glval>) = VariableAddress[ys] : # 2218| r2218_74(glval) = FunctionAddress[~vector] : @@ -14686,18 +14686,18 @@ ir.cpp: # 2232| mu2232_10(unknown) = ^CallSideEffect : ~m? # 2232| v2232_11(void) = ^IndirectReadSideEffect[-1] : &:r2232_7, ~m? # 2232| mu2232_12(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2232_7 -# 2229| r2229_49(glval) = VariableAddress[y] : -# 2229| r2229_50(glval) = FunctionAddress[~ClassWithDestructor] : -# 2229| v2229_51(void) = Call[~ClassWithDestructor] : func:r2229_50, this:r2229_49 -# 2229| mu2229_52(unknown) = ^CallSideEffect : ~m? -# 2229| v2229_53(void) = ^IndirectReadSideEffect[-1] : &:r2229_49, ~m? -# 2229| mu2229_54(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2229_49 -# 2229| r2229_55(glval>) = VariableAddress[(__begin)] : -# 2229| r2229_56(glval) = FunctionAddress[operator++] : -# 2229| r2229_57(iterator &) = Call[operator++] : func:r2229_56, this:r2229_55 -# 2229| v2229_58(void) = ^IndirectReadSideEffect[-1] : &:r2229_55, ~m? -# 2229| mu2229_59(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2229_55 -# 2229| r2229_60(glval>) = CopyValue : r2229_57 +# 2229| r2229_49(glval>) = VariableAddress[(__begin)] : +# 2229| r2229_50(glval) = FunctionAddress[operator++] : +# 2229| r2229_51(iterator &) = Call[operator++] : func:r2229_50, this:r2229_49 +# 2229| v2229_52(void) = ^IndirectReadSideEffect[-1] : &:r2229_49, ~m? +# 2229| mu2229_53(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2229_49 +# 2229| r2229_54(glval) = VariableAddress[y] : +# 2229| r2229_55(glval) = FunctionAddress[~ClassWithDestructor] : +# 2229| v2229_56(void) = Call[~ClassWithDestructor] : func:r2229_55, this:r2229_54 +# 2229| mu2229_57(unknown) = ^CallSideEffect : ~m? +# 2229| v2229_58(void) = ^IndirectReadSideEffect[-1] : &:r2229_54, ~m? +# 2229| mu2229_59(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2229_54 +# 2229| r2229_60(glval>) = CopyValue : r2229_51 #-----| Goto (back edge) -> Block 27 # 2229| Block 29 @@ -15339,18 +15339,18 @@ ir.cpp: # 2309| mu2309_4(unknown) = ^CallSideEffect : ~m? # 2309| v2309_5(void) = ^IndirectReadSideEffect[-1] : &:r2309_1, ~m? # 2309| mu2309_6(String) = ^IndirectMayWriteSideEffect[-1] : &:r2309_1 -# 2307| r2307_60(glval) = VariableAddress[s] : -# 2307| r2307_61(glval) = FunctionAddress[~String] : -# 2307| v2307_62(void) = Call[~String] : func:r2307_61, this:r2307_60 -# 2307| mu2307_63(unknown) = ^CallSideEffect : ~m? -# 2307| v2307_64(void) = ^IndirectReadSideEffect[-1] : &:r2307_60, ~m? -# 2307| mu2307_65(String) = ^IndirectMayWriteSideEffect[-1] : &:r2307_60 -# 2307| r2307_66(glval>) = VariableAddress[(__begin)] : -# 2307| r2307_67(glval) = FunctionAddress[operator++] : -# 2307| r2307_68(iterator &) = Call[operator++] : func:r2307_67, this:r2307_66 -# 2307| v2307_69(void) = ^IndirectReadSideEffect[-1] : &:r2307_66, ~m? -# 2307| mu2307_70(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2307_66 -# 2307| r2307_71(glval>) = CopyValue : r2307_68 +# 2307| r2307_60(glval>) = VariableAddress[(__begin)] : +# 2307| r2307_61(glval) = FunctionAddress[operator++] : +# 2307| r2307_62(iterator &) = Call[operator++] : func:r2307_61, this:r2307_60 +# 2307| v2307_63(void) = ^IndirectReadSideEffect[-1] : &:r2307_60, ~m? +# 2307| mu2307_64(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2307_60 +# 2307| r2307_65(glval) = VariableAddress[s] : +# 2307| r2307_66(glval) = FunctionAddress[~String] : +# 2307| v2307_67(void) = Call[~String] : func:r2307_66, this:r2307_65 +# 2307| mu2307_68(unknown) = ^CallSideEffect : ~m? +# 2307| v2307_69(void) = ^IndirectReadSideEffect[-1] : &:r2307_65, ~m? +# 2307| mu2307_70(String) = ^IndirectMayWriteSideEffect[-1] : &:r2307_65 +# 2307| r2307_71(glval>) = CopyValue : r2307_62 #-----| Goto (back edge) -> Block 4 # 2311| Block 6 diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/Assets.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/Assets.cs index a59991b4b837..4082146f5920 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/Assets.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/Assets.cs @@ -16,6 +16,11 @@ internal class Assets { private readonly ILogger logger; + /// + /// Contains the dependencies found in the parsed assets files. + /// + public DependencyContainer Dependencies { get; } = new(); + internal Assets(ILogger logger) { this.logger = logger; @@ -72,7 +77,7 @@ private record class ReferenceInfo(string? Type, Dictionary? Com /// "json.net" /// } /// - private void AddPackageDependencies(JObject json, DependencyContainer dependencies) + private void AddPackageDependencies(JObject json) { // If there is more than one framework we need to pick just one. // To ensure stability we pick one based on the lexicographic order of @@ -107,13 +112,13 @@ private void AddPackageDependencies(JObject json, DependencyContainer dependenci // If this is a framework reference then include everything. if (FrameworkPackageNames.AllFrameworks.Any(framework => name.StartsWith(framework))) { - dependencies.AddFramework(name); + Dependencies.AddFramework(name); } return; } info.Compile - .ForEach(r => dependencies.Add(name, r.Key)); + .ForEach(r => Dependencies.Add(name, r.Key)); }); return; @@ -149,7 +154,7 @@ private void AddPackageDependencies(JObject json, DependencyContainer dependenci /// "microsoft.netcore.app.ref" /// } /// - private void AddFrameworkDependencies(JObject json, DependencyContainer dependencies) + private void AddFrameworkDependencies(JObject json) { var frameworks = json @@ -178,7 +183,7 @@ private void AddFrameworkDependencies(JObject json, DependencyContainer dependen references .Properties() - .ForEach(f => dependencies.AddFramework($"{f.Name}.Ref".ToLowerInvariant())); + .ForEach(f => Dependencies.AddFramework($"{f.Name}.Ref".ToLowerInvariant())); } /// @@ -186,13 +191,13 @@ private void AddFrameworkDependencies(JObject json, DependencyContainer dependen /// (together with used package information) required for compilation. /// /// True if parsing succeeds, otherwise false. - public bool TryParse(string json, DependencyContainer dependencies) + public bool TryParse(string json) { try { var obj = JObject.Parse(json); - AddPackageDependencies(obj, dependencies); - AddFrameworkDependencies(obj, dependencies); + AddPackageDependencies(obj); + AddFrameworkDependencies(obj); return true; } catch (Exception e) @@ -217,19 +222,24 @@ private static bool TryReadAllText(string path, ILogger logger, [NotNullWhen(ret } } - public static DependencyContainer GetCompilationDependencies(ILogger logger, IEnumerable assets) + /// + /// Add the dependencies from the assets file to the dependencies. + /// + /// Path to an assets file. + public void AddDependencies(string asset) { - var parser = new Assets(logger); - var dependencies = new DependencyContainer(); - assets.ForEach(asset => + if (TryReadAllText(asset, logger, out var json)) { - if (TryReadAllText(asset, logger, out var json)) - { - parser.TryParse(json, dependencies); - } - }); - return dependencies; + TryParse(json); + } } + + /// + /// Add the dependencies from the assets files to the dependencies. + /// + /// Collection of paths to assets files. + public void AddDependenciesRange(IEnumerable assets) => + assets.ForEach(AddDependencies); } internal static class JsonExtensions diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependencyContainer.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependencyContainer.cs index d3858f17fe18..230731104124 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependencyContainer.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependencyContainer.cs @@ -12,7 +12,7 @@ internal class DependencyContainer /// /// Paths to dependencies required for compilation. /// - public List Paths { get; } = new(); + public HashSet Paths { get; } = new(); /// /// Packages that are used as a part of the required dependencies. @@ -45,7 +45,7 @@ public void Add(string package, string dependency) var p = package.Replace('/', Path.DirectorySeparatorChar); var d = dependency.Replace('/', Path.DirectorySeparatorChar); - // In most cases paths in asset files point to dll's or the empty _._ file. + // In most cases paths in assets files point to dll's or the empty _._ file. // That is, for _._ we don't need to add anything. if (Path.GetFileName(d) == "_._") { @@ -68,4 +68,18 @@ public void AddFramework(string framework) Packages.Add(GetPackageName(p)); } } -} \ No newline at end of file + + internal static class DependencyContainerExtensions + { + /// + /// Flatten a list of containers into a single container. + /// + public static DependencyContainer Flatten(this IEnumerable containers, DependencyContainer init) => + containers.Aggregate(init, (acc, container) => + { + acc.Paths.UnionWith(container.Paths); + acc.Packages.UnionWith(container.Packages); + return acc; + }); + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependencyManager.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependencyManager.cs index d5450affd930..f18d30f4f192 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependencyManager.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependencyManager.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Security.Cryptography; -using System.Text; using System.Threading.Tasks; using Semmle.Util; diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs index baf23a0d0cc7..07fb8d2c89d6 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; @@ -144,11 +145,11 @@ public HashSet Restore() logger.LogError($"Failed to restore Nuget packages with nuget.exe: {exc.Message}"); } - var restoredProjects = RestoreSolutions(out var assets1); + var restoredProjects = RestoreSolutions(out var container); var projects = fileProvider.Projects.Except(restoredProjects); - RestoreProjects(projects, out var assets2); + RestoreProjects(projects, out var containers); - var dependencies = Assets.GetCompilationDependencies(logger, assets1.Union(assets2)); + var dependencies = containers.Flatten(container); var paths = dependencies .Paths @@ -198,14 +199,14 @@ private List GetReachableFallbackNugetFeeds() /// As opposed to RestoreProjects this is not run in parallel using PLINQ /// as `dotnet restore` on a solution already uses multiple threads for restoring /// the projects (this can be disabled with the `--disable-parallel` flag). - /// Populates assets with the relative paths to the assets files generated by the restore. + /// Populates dependencies with the relevant dependencies from the assets files generated by the restore. /// Returns a list of projects that are up to date with respect to restore. /// - private IEnumerable RestoreSolutions(out IEnumerable assets) + private IEnumerable RestoreSolutions(out DependencyContainer dependencies) { var successCount = 0; var nugetSourceFailures = 0; - var assetFiles = new List(); + var assets = new Assets(logger); var projects = fileProvider.Solutions.SelectMany(solution => { logger.LogInfo($"Restoring solution {solution}..."); @@ -218,10 +219,10 @@ private IEnumerable RestoreSolutions(out IEnumerable assets) { nugetSourceFailures++; } - assetFiles.AddRange(res.AssetsFilePaths); + assets.AddDependenciesRange(res.AssetsFilePaths); return res.RestoredProjects; }).ToList(); - assets = assetFiles; + dependencies = assets.Dependencies; compilationInfoContainer.CompilationInfos.Add(("Successfully restored solution files", successCount.ToString())); compilationInfoContainer.CompilationInfos.Add(("Failed solution restore with package source error", nugetSourceFailures.ToString())); compilationInfoContainer.CompilationInfos.Add(("Restored projects through solution files", projects.Count.ToString())); @@ -231,33 +232,39 @@ private IEnumerable RestoreSolutions(out IEnumerable assets) /// /// Executes `dotnet restore` on all projects in projects. /// This is done in parallel for performance reasons. - /// Populates assets with the relative paths to the assets files generated by the restore. + /// Populates dependencies with the relative paths to the assets files generated by the restore. /// /// A list of paths to project files. - private void RestoreProjects(IEnumerable projects, out IEnumerable assets) + private void RestoreProjects(IEnumerable projects, out ConcurrentBag dependencies) { var successCount = 0; var nugetSourceFailures = 0; - var assetFiles = new List(); + ConcurrentBag collectedDependencies = []; var sync = new object(); - Parallel.ForEach(projects, new ParallelOptions { MaxDegreeOfParallelism = DependencyManager.Threads }, project => + var projectGroups = projects.GroupBy(Path.GetDirectoryName); + Parallel.ForEach(projectGroups, new ParallelOptions { MaxDegreeOfParallelism = DependencyManager.Threads }, projectGroup => { - logger.LogInfo($"Restoring project {project}..."); - var res = dotnet.Restore(new(project, PackageDirectory.DirInfo.FullName, ForceDotnetRefAssemblyFetching: true)); - lock (sync) + var assets = new Assets(logger); + foreach (var project in projectGroup) { - if (res.Success) + logger.LogInfo($"Restoring project {project}..."); + var res = dotnet.Restore(new(project, PackageDirectory.DirInfo.FullName, ForceDotnetRefAssemblyFetching: true)); + assets.AddDependenciesRange(res.AssetsFilePaths); + lock (sync) { - successCount++; - } - if (res.HasNugetPackageSourceError) - { - nugetSourceFailures++; + if (res.Success) + { + successCount++; + } + if (res.HasNugetPackageSourceError) + { + nugetSourceFailures++; + } } - assetFiles.AddRange(res.AssetsFilePaths); } + collectedDependencies.Add(assets.Dependencies); }); - assets = assetFiles; + dependencies = collectedDependencies; compilationInfoContainer.CompilationInfos.Add(("Successfully restored project files", successCount.ToString())); compilationInfoContainer.CompilationInfos.Add(("Failed project restore with package source error", nugetSourceFailures.ToString())); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Extractor.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Extractor.cs index 63d4ff0e83a8..e578dd4aa31c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Extractor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Extractor.cs @@ -40,7 +40,6 @@ private static void AnalyseStandalone( output.Name, syntaxTrees, references, new CSharpCompilationOptions(OutputKind.ConsoleApplication, allowUnsafe: true) ), (compilation, options) => analyser.Initialize(output.FullName, extractionInput.CompilationInfos, compilation, options), - _ => { }, () => { foreach (var type in analyser.MissingNamespaces) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Analyser.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Analyser.cs index cda4610a217f..2f21716284f0 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Analyser.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Analyser.cs @@ -245,6 +245,8 @@ private void DoAnalyseCompilation() } } + public void LogPerformance(Entities.PerformanceMetrics p) => compilationEntity.PopulatePerformance(p); + #nullable restore warnings /// diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Extractor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Extractor.cs index 22a55849a026..03369e7b6013 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Extractor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Extractor.cs @@ -309,7 +309,6 @@ public static ExitCode Analyse(Stopwatch stopwatch, Analyser analyser, CommonOpt Func, IEnumerable> getSyntaxTreeTasks, Func, IEnumerable, CSharpCompilation> getCompilation, Action initializeAnalyser, - Action logPerformance, Action postProcess) { using var references = new BlockingCollection(); @@ -368,7 +367,7 @@ public static ExitCode Analyse(Stopwatch stopwatch, Analyser analyser, CommonOpt PeakWorkingSet = currentProcess.PeakWorkingSet64 }; - logPerformance(performance); + analyser.LogPerformance(performance); analyser.Logger.Log(Severity.Info, " Extraction took {0}", sw.Elapsed); postProcess(); @@ -422,7 +421,6 @@ private static ExitCode AnalyseTracing( ); }, (compilation, options) => analyser.EndInitialize(compilerArguments, options, compilation), - performance => analyser.LogPerformance(performance), () => { }); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs index 22db6710f36f..3b73c35f55a4 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs @@ -175,9 +175,6 @@ private IEnumerable FilteredDiagnostics Where(e => e.Severity >= DiagnosticSeverity.Error && !errorsToIgnore.Contains(e.Id)); } } - - public void LogPerformance(Entities.PerformanceMetrics p) => compilationEntity.PopulatePerformance(p); - #nullable restore warnings } } diff --git a/csharp/extractor/Semmle.Extraction.Tests/Assets.cs b/csharp/extractor/Semmle.Extraction.Tests/Assets.cs index 3406788bd1c7..ea04597f96bd 100644 --- a/csharp/extractor/Semmle.Extraction.Tests/Assets.cs +++ b/csharp/extractor/Semmle.Extraction.Tests/Assets.cs @@ -14,29 +14,28 @@ public void TestAssets1() // Setup var assets = new Assets(new LoggerStub()); var json = assetsJson1; - var dependencies = new DependencyContainer(); // Execute - var success = assets.TryParse(json, dependencies); + var success = assets.TryParse(json); // Verify Assert.True(success); - Assert.Equal(6, dependencies.Paths.Count()); - Assert.Equal(5, dependencies.Packages.Count()); + Assert.Equal(6, assets.Dependencies.Paths.Count); + Assert.Equal(5, assets.Dependencies.Packages.Count); - var normalizedPaths = dependencies.Paths.Select(FixExpectedPathOnWindows); + var normalizedPaths = assets.Dependencies.Paths.Select(FixExpectedPathOnWindows); // Used references Assert.Contains("castle.core/4.4.1/lib/netstandard1.5/Castle.Core.dll", normalizedPaths); Assert.Contains("castle.core/4.4.1/lib/netstandard1.5/Castle.Core2.dll", normalizedPaths); Assert.Contains("json.net/1.0.33/lib/netstandard2.0/Json.Net.dll", normalizedPaths); Assert.Contains("microsoft.aspnetcore.cryptography.internal/6.0.8/lib/net6.0/Microsoft.AspNetCore.Cryptography.Internal.dll", normalizedPaths); // Used packages - Assert.Contains("castle.core", dependencies.Packages); - Assert.Contains("json.net", dependencies.Packages); - Assert.Contains("microsoft.aspnetcore.cryptography.internal", dependencies.Packages); + Assert.Contains("castle.core", assets.Dependencies.Packages); + Assert.Contains("json.net", assets.Dependencies.Packages); + Assert.Contains("microsoft.aspnetcore.cryptography.internal", assets.Dependencies.Packages); // Used frameworks - Assert.Contains("microsoft.netcore.app.ref", dependencies.Packages); - Assert.Contains("microsoft.aspnetcore.app.ref", dependencies.Packages); + Assert.Contains("microsoft.netcore.app.ref", assets.Dependencies.Packages); + Assert.Contains("microsoft.aspnetcore.app.ref", assets.Dependencies.Packages); } [Fact] @@ -45,14 +44,13 @@ public void TestAssetsFailure() // Setup var assets = new Assets(new LoggerStub()); var json = "garbage data"; - var dependencies = new DependencyContainer(); // Execute - var success = assets.TryParse(json, dependencies); + var success = assets.TryParse(json); // Verify Assert.False(success); - Assert.Empty(dependencies.Paths); + Assert.Empty(assets.Dependencies.Paths); } [Fact] @@ -61,28 +59,27 @@ public void TestAssetsNet70() // Setup var assets = new Assets(new LoggerStub()); var json = assetsNet70; - var dependencies = new DependencyContainer(); // Execute - var success = assets.TryParse(json, dependencies); + var success = assets.TryParse(json); // Verify Assert.True(success); - Assert.Equal(4, dependencies.Paths.Count); - Assert.Equal(4, dependencies.Packages.Count); + Assert.Equal(4, assets.Dependencies.Paths.Count); + Assert.Equal(4, assets.Dependencies.Packages.Count); - var normalizedPaths = dependencies.Paths.Select(FixExpectedPathOnWindows); + var normalizedPaths = assets.Dependencies.Paths.Select(FixExpectedPathOnWindows); // Used paths Assert.Contains("microsoft.netcore.app.ref", normalizedPaths); Assert.Contains("microsoft.aspnetcore.app.ref", normalizedPaths); Assert.Contains("newtonsoft.json/12.0.1/lib/netstandard2.0/Newtonsoft.Json.dll", normalizedPaths); Assert.Contains("newtonsoft.json.bson/1.0.2/lib/netstandard2.0/Newtonsoft.Json.Bson.dll", normalizedPaths); // Used packages - Assert.Contains("microsoft.netcore.app.ref", dependencies.Packages); - Assert.Contains("microsoft.aspnetcore.app.ref", dependencies.Packages); - Assert.Contains("newtonsoft.json", dependencies.Packages); - Assert.Contains("newtonsoft.json.bson", dependencies.Packages); + Assert.Contains("microsoft.netcore.app.ref", assets.Dependencies.Packages); + Assert.Contains("microsoft.aspnetcore.app.ref", assets.Dependencies.Packages); + Assert.Contains("newtonsoft.json", assets.Dependencies.Packages); + Assert.Contains("newtonsoft.json.bson", assets.Dependencies.Packages); } @@ -92,25 +89,24 @@ public void TestAssetsNet48() // Setup var assets = new Assets(new LoggerStub()); var json = assetsNet48; - var dependencies = new DependencyContainer(); // Execute - var success = assets.TryParse(json, dependencies); + var success = assets.TryParse(json); // Verify Assert.True(success); - Assert.Equal(3, dependencies.Paths.Count); - Assert.Equal(3, dependencies.Packages.Count); + Assert.Equal(3, assets.Dependencies.Paths.Count); + Assert.Equal(3, assets.Dependencies.Packages.Count); - var normalizedPaths = dependencies.Paths.Select(FixExpectedPathOnWindows); + var normalizedPaths = assets.Dependencies.Paths.Select(FixExpectedPathOnWindows); // Used references Assert.Contains("microsoft.netframework.referenceassemblies.net48/1.0.2", normalizedPaths); Assert.Contains("newtonsoft.json/12.0.1/lib/net45/Newtonsoft.Json.dll", normalizedPaths); Assert.Contains("newtonsoft.json.bson/1.0.2/lib/net45/Newtonsoft.Json.Bson.dll", normalizedPaths); // Used packages - Assert.Contains("microsoft.netframework.referenceassemblies.net48", dependencies.Packages); - Assert.Contains("newtonsoft.json", dependencies.Packages); - Assert.Contains("newtonsoft.json.bson", dependencies.Packages); + Assert.Contains("microsoft.netframework.referenceassemblies.net48", assets.Dependencies.Packages); + Assert.Contains("newtonsoft.json", assets.Dependencies.Packages); + Assert.Contains("newtonsoft.json.bson", assets.Dependencies.Packages); } [Fact] @@ -119,26 +115,25 @@ public void TestAssetsNetstandard21() // Setup var assets = new Assets(new LoggerStub()); var json = assetsNetstandard21; - var dependencies = new DependencyContainer(); // Execute - var success = assets.TryParse(json, dependencies); + var success = assets.TryParse(json); // Verify Assert.True(success); - Assert.Equal(3, dependencies.Paths.Count); - Assert.Equal(3, dependencies.Packages.Count); + Assert.Equal(3, assets.Dependencies.Paths.Count); + Assert.Equal(3, assets.Dependencies.Packages.Count); - var normalizedPaths = dependencies.Paths.Select(FixExpectedPathOnWindows); + var normalizedPaths = assets.Dependencies.Paths.Select(FixExpectedPathOnWindows); // Used references Assert.Contains("netstandard.library.ref", normalizedPaths); Assert.Contains("newtonsoft.json/12.0.1/lib/netstandard2.0/Newtonsoft.Json.dll", normalizedPaths); Assert.Contains("newtonsoft.json.bson/1.0.2/lib/netstandard2.0/Newtonsoft.Json.Bson.dll", normalizedPaths); // Used packages - Assert.Contains("netstandard.library.ref", dependencies.Packages); - Assert.Contains("newtonsoft.json", dependencies.Packages); - Assert.Contains("newtonsoft.json.bson", dependencies.Packages); + Assert.Contains("netstandard.library.ref", assets.Dependencies.Packages); + Assert.Contains("newtonsoft.json", assets.Dependencies.Packages); + Assert.Contains("newtonsoft.json.bson", assets.Dependencies.Packages); } [Fact] @@ -147,17 +142,16 @@ public void TestAssetsNetStandard16() // Setup var assets = new Assets(new LoggerStub()); var json = assetsNetstandard16; - var dependencies = new DependencyContainer(); // Execute - var success = assets.TryParse(json, dependencies); + var success = assets.TryParse(json); // Verify Assert.True(success); - Assert.Equal(5, dependencies.Paths.Count); - Assert.Equal(5, dependencies.Packages.Count); + Assert.Equal(5, assets.Dependencies.Paths.Count); + Assert.Equal(5, assets.Dependencies.Packages.Count); - var normalizedPaths = dependencies.Paths.Select(FixExpectedPathOnWindows); + var normalizedPaths = assets.Dependencies.Paths.Select(FixExpectedPathOnWindows); // Used references Assert.Contains("netstandard.library/1.6.1", normalizedPaths); @@ -166,11 +160,11 @@ public void TestAssetsNetStandard16() Assert.Contains("newtonsoft.json/12.0.1/lib/netstandard1.3/Newtonsoft.Json.dll", normalizedPaths); Assert.Contains("newtonsoft.json.bson/1.0.2/lib/netstandard1.3/Newtonsoft.Json.Bson.dll", normalizedPaths); // Used packages - Assert.Contains("netstandard.library", dependencies.Packages); - Assert.Contains("microsoft.csharp", dependencies.Packages); - Assert.Contains("microsoft.win32.primitives", dependencies.Packages); - Assert.Contains("newtonsoft.json", dependencies.Packages); - Assert.Contains("newtonsoft.json.bson", dependencies.Packages); + Assert.Contains("netstandard.library", assets.Dependencies.Packages); + Assert.Contains("microsoft.csharp", assets.Dependencies.Packages); + Assert.Contains("microsoft.win32.primitives", assets.Dependencies.Packages); + Assert.Contains("newtonsoft.json", assets.Dependencies.Packages); + Assert.Contains("newtonsoft.json.bson", assets.Dependencies.Packages); } [Fact] @@ -179,26 +173,25 @@ public void TestAssetsNetcoreapp20() // Setup var assets = new Assets(new LoggerStub()); var json = assetsNetcoreapp20; - var dependencies = new DependencyContainer(); // Execute - var success = assets.TryParse(json, dependencies); + var success = assets.TryParse(json); // Verify Assert.True(success); - Assert.Equal(144, dependencies.Paths.Count); - Assert.Equal(3, dependencies.Packages.Count); + Assert.Equal(144, assets.Dependencies.Paths.Count); + Assert.Equal(3, assets.Dependencies.Packages.Count); - var normalizedPaths = dependencies.Paths.Select(FixExpectedPathOnWindows); + var normalizedPaths = assets.Dependencies.Paths.Select(FixExpectedPathOnWindows); // Used references (only some of them) Assert.Contains("microsoft.netcore.app/2.0.0/ref/netcoreapp2.0/Microsoft.CSharp.dll", normalizedPaths); Assert.Contains("newtonsoft.json/12.0.1/lib/netstandard2.0/Newtonsoft.Json.dll", normalizedPaths); Assert.Contains("newtonsoft.json.bson/1.0.2/lib/netstandard2.0/Newtonsoft.Json.Bson.dll", normalizedPaths); // Used packages - Assert.Contains("microsoft.netcore.app", dependencies.Packages); - Assert.Contains("newtonsoft.json", dependencies.Packages); - Assert.Contains("newtonsoft.json.bson", dependencies.Packages); + Assert.Contains("microsoft.netcore.app", assets.Dependencies.Packages); + Assert.Contains("newtonsoft.json", assets.Dependencies.Packages); + Assert.Contains("newtonsoft.json.bson", assets.Dependencies.Packages); } [Fact] @@ -207,15 +200,14 @@ public void TestAssetsNetcoreapp31() // Setup var assets = new Assets(new LoggerStub()); var json = assetsNetcoreapp31; - var dependencies = new DependencyContainer(); // Execute - var success = assets.TryParse(json, dependencies); + var success = assets.TryParse(json); // Verify Assert.True(success); - var normalizedPaths = dependencies.Paths.Select(FixExpectedPathOnWindows); + var normalizedPaths = assets.Dependencies.Paths.Select(FixExpectedPathOnWindows); // Used paths Assert.Contains("microsoft.netcore.app.ref", normalizedPaths); @@ -223,10 +215,10 @@ public void TestAssetsNetcoreapp31() Assert.Contains("newtonsoft.json/12.0.1/lib/netstandard2.0/Newtonsoft.Json.dll", normalizedPaths); Assert.Contains("newtonsoft.json.bson/1.0.2/lib/netstandard2.0/Newtonsoft.Json.Bson.dll", normalizedPaths); // Used packages - Assert.Contains("microsoft.netcore.app.ref", dependencies.Packages); - Assert.Contains("microsoft.aspnetcore.app.ref", dependencies.Packages); - Assert.Contains("newtonsoft.json", dependencies.Packages); - Assert.Contains("newtonsoft.json.bson", dependencies.Packages); + Assert.Contains("microsoft.netcore.app.ref", assets.Dependencies.Packages); + Assert.Contains("microsoft.aspnetcore.app.ref", assets.Dependencies.Packages); + Assert.Contains("newtonsoft.json", assets.Dependencies.Packages); + Assert.Contains("newtonsoft.json.bson", assets.Dependencies.Packages); } /// diff --git a/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/Assemblies.expected b/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/Assemblies.expected new file mode 100644 index 000000000000..2d54c0155a43 --- /dev/null +++ b/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/Assemblies.expected @@ -0,0 +1,166 @@ +| [...]/avalara.avatax/23.11.0/lib/netstandard2.0/Avalara.AvaTax.RestClient.dll | +| [...]/microsoft.bcl.asyncinterfaces/8.0.0/lib/netstandard2.1/Microsoft.Bcl.AsyncInterfaces.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/Microsoft.CSharp.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/Microsoft.VisualBasic.Core.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/Microsoft.VisualBasic.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/Microsoft.Win32.Primitives.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/Microsoft.Win32.Registry.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.AppContext.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Buffers.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Collections.Concurrent.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Collections.Immutable.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Collections.NonGeneric.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Collections.Specialized.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Collections.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.ComponentModel.Annotations.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.ComponentModel.DataAnnotations.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.ComponentModel.EventBasedAsync.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.ComponentModel.Primitives.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.ComponentModel.TypeConverter.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.ComponentModel.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Configuration.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Console.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Core.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Data.Common.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Data.DataSetExtensions.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Data.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Diagnostics.Contracts.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Diagnostics.Debug.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Diagnostics.DiagnosticSource.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Diagnostics.FileVersionInfo.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Diagnostics.Process.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Diagnostics.StackTrace.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Diagnostics.TextWriterTraceListener.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Diagnostics.Tools.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Diagnostics.TraceSource.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Diagnostics.Tracing.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Drawing.Primitives.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Drawing.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Dynamic.Runtime.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Formats.Asn1.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Formats.Tar.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Globalization.Calendars.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Globalization.Extensions.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Globalization.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.IO.Compression.Brotli.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.IO.Compression.FileSystem.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.IO.Compression.ZipFile.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.IO.Compression.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.IO.FileSystem.AccessControl.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.IO.FileSystem.DriveInfo.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.IO.FileSystem.Primitives.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.IO.FileSystem.Watcher.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.IO.FileSystem.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.IO.IsolatedStorage.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.IO.MemoryMappedFiles.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.IO.Pipes.AccessControl.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.IO.Pipes.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.IO.UnmanagedMemoryStream.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.IO.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Linq.Expressions.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Linq.Parallel.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Linq.Queryable.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Linq.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Memory.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.Http.Json.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.Http.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.HttpListener.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.Mail.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.NameResolution.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.NetworkInformation.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.Ping.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.Primitives.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.Quic.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.Requests.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.Security.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.ServicePoint.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.Sockets.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.WebClient.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.WebHeaderCollection.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.WebProxy.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.WebSockets.Client.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.WebSockets.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Net.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Numerics.Vectors.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Numerics.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.ObjectModel.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Reflection.DispatchProxy.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Reflection.Emit.ILGeneration.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Reflection.Emit.Lightweight.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Reflection.Emit.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Reflection.Extensions.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Reflection.Metadata.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Reflection.Primitives.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Reflection.TypeExtensions.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Reflection.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Resources.Reader.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Resources.ResourceManager.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Resources.Writer.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Runtime.CompilerServices.Unsafe.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Runtime.CompilerServices.VisualC.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Runtime.Extensions.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Runtime.Handles.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Runtime.InteropServices.JavaScript.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Runtime.InteropServices.RuntimeInformation.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Runtime.InteropServices.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Runtime.Intrinsics.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Runtime.Loader.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Runtime.Numerics.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Runtime.Serialization.Formatters.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Runtime.Serialization.Json.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Runtime.Serialization.Primitives.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Runtime.Serialization.Xml.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Runtime.Serialization.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Runtime.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Security.AccessControl.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Security.Claims.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Security.Cryptography.Algorithms.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Security.Cryptography.Cng.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Security.Cryptography.Csp.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Security.Cryptography.Encoding.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Security.Cryptography.OpenSsl.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Security.Cryptography.Primitives.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Security.Cryptography.X509Certificates.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Security.Cryptography.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Security.Principal.Windows.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Security.Principal.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Security.SecureString.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Security.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.ServiceModel.Web.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.ServiceProcess.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Text.Encoding.CodePages.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Text.Encoding.Extensions.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Text.Encoding.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Text.Encodings.Web.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Text.Json.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Text.RegularExpressions.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Threading.Channels.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Threading.Overlapped.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Threading.Tasks.Dataflow.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Threading.Tasks.Extensions.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Threading.Tasks.Parallel.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Threading.Tasks.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Threading.Thread.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Threading.ThreadPool.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Threading.Timer.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Threading.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Transactions.Local.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Transactions.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.ValueTuple.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Web.HttpUtility.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Web.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Windows.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Xml.Linq.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Xml.ReaderWriter.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Xml.Serialization.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Xml.XDocument.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Xml.XPath.XDocument.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Xml.XPath.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Xml.XmlDocument.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Xml.XmlSerializer.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.Xml.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/System.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/WindowsBase.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/mscorlib.dll | +| [...]/microsoft.netcore.app.ref/8.0.1/ref/net8.0/netstandard.dll | +| [...]/newtonsoft.json/12.0.1/lib/netstandard2.0/Newtonsoft.Json.dll | diff --git a/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/Assemblies.ql b/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/Assemblies.ql new file mode 100644 index 000000000000..b78ceee2d8f8 --- /dev/null +++ b/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/Assemblies.ql @@ -0,0 +1,17 @@ +import csharp + +private string getPath(Assembly a) { + not a.getCompilation().getOutputAssembly() = a and + exists(string s | s = a.getFile().getAbsolutePath() | + result = + "[...]" + + s.substring(s.indexOf("test-db/working/") + "test-db/working/".length() + 16 + + "/packages".length(), s.length()) + or + result = s and + not exists(s.indexOf("test-db/working/")) + ) +} + +from Assembly a +select getPath(a) diff --git a/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/Program.cs b/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/Program.cs new file mode 100644 index 000000000000..39a9e95bb6e3 --- /dev/null +++ b/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/Program.cs @@ -0,0 +1,6 @@ +class Program +{ + static void Main(string[] args) + { + } +} \ No newline at end of file diff --git a/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/global.json b/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/global.json new file mode 100644 index 000000000000..d54915e8d4d0 --- /dev/null +++ b/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "version": "8.0.101" + } +} diff --git a/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/standalone1.csproj b/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/standalone1.csproj new file mode 100644 index 000000000000..67d37d1a7608 --- /dev/null +++ b/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/standalone1.csproj @@ -0,0 +1,16 @@ + + + + Exe + net8.0 + + + + + + + + + + + diff --git a/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/standalone2.csproj b/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/standalone2.csproj new file mode 100644 index 000000000000..05fb5c1aa487 --- /dev/null +++ b/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/standalone2.csproj @@ -0,0 +1,16 @@ + + + + Exe + net8.0 + + + + + + + + + + + diff --git a/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/test.py b/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/test.py new file mode 100644 index 000000000000..a17966e148a9 --- /dev/null +++ b/csharp/ql/integration-tests/posix-only/standalone_dependencies_multi_project/test.py @@ -0,0 +1,3 @@ +from create_database_utils import * + +run_codeql_database_create([], lang="csharp", extra_args=["--build-mode=none"]) diff --git a/csharp/ql/src/Telemetry/ExtractorInformation.ql b/csharp/ql/src/Telemetry/ExtractorInformation.ql index 64f90e481706..f466e2c8e8ec 100644 --- a/csharp/ql/src/Telemetry/ExtractorInformation.ql +++ b/csharp/ql/src/Telemetry/ExtractorInformation.ql @@ -201,6 +201,14 @@ predicate analyzerAssemblies(string key, float value) { value = 1.0 } +predicate timingValues(string key, float value) { + exists(Compilation c | + key = "Total elapsed seconds" and value = c.getElapsedSeconds() + or + key = "Extractor elapsed seconds" and value = c.getExtractorElapsedSeconds() + ) +} + from string key, float value where ( @@ -230,7 +238,8 @@ where ExprStatsReport::numberOfOk(key, value) or ExprStatsReport::numberOfNotOk(key, value) or ExprStatsReport::percentageOfOk(key, value) or - analyzerAssemblies(key, value) + analyzerAssemblies(key, value) or + timingValues(key, value) ) and /* Infinity */ value != 1.0 / 0.0 and diff --git a/javascript/ql/lib/semmle/javascript/endpoints/EndpointNaming.qll b/javascript/ql/lib/semmle/javascript/endpoints/EndpointNaming.qll index 9e514d4c9f41..8fcb83729c48 100644 --- a/javascript/ql/lib/semmle/javascript/endpoints/EndpointNaming.qll +++ b/javascript/ql/lib/semmle/javascript/endpoints/EndpointNaming.qll @@ -432,7 +432,7 @@ string renderName(string package, string name) { result = join("(" + package + " * These names are not necessarily part of a package's public API, and so we only used them * as a fallback when a publicly-accessible access path cannot be found. */ -private module InternalModuleNaming { +module InternalModuleNaming { /** Gets the path to `folder` relative to its enclosing non-private `package.json` file. */ private string getPackageRelativePathFromFolder(Folder folder) { exists(PackageJson json | @@ -446,7 +446,10 @@ private module InternalModuleNaming { getPackageRelativePathFromFolder(folder.getParentContainer()) + "/" + folder.getBaseName() } - private string getPackageRelativePath(Module mod) { + /** + * Gets the path to `mod` relative to its enclosing package, including the package name. + */ + string getPackageRelativePath(Module mod) { exists(PackageJson json, string relativePath | not json.isPrivate() and json.getExportedModule(relativePath) = mod and diff --git a/python/ql/test/library-tests/dataflow/model-summaries/InlineTaintTest.ext.yml b/python/ql/test/library-tests/dataflow/model-summaries/InlineTaintTest.ext.yml index 10fbd6df7448..0ed4ca9f172d 100644 --- a/python/ql/test/library-tests/dataflow/model-summaries/InlineTaintTest.ext.yml +++ b/python/ql/test/library-tests/dataflow/model-summaries/InlineTaintTest.ext.yml @@ -18,4 +18,7 @@ extensions: - ["foo", "Member[MS_spread]", "Argument[0]", "ReturnValue.TupleElement[0]", "value"] - ["foo", "Member[MS_spread]", "Argument[1]", "ReturnValue.TupleElement[1]", "value"] - ["foo", "Member[MS_spread_all]", "Argument[0]", "ReturnValue.TupleElement[0,1]", "value"] + - ["foo", "Member[MS_Class].Instance.Member[instance_method]", "Argument[self]", "ReturnValue.TupleElement[0]", "value"] + - ["foo", "Member[MS_Class].Instance.Member[instance_method]", "Argument[0]", "ReturnValue.TupleElement[1]", "value"] + - ["foo", "Member[MS_Class].Instance.Member[explicit_self]", "Argument[self:]", "ReturnValue", "value"] - ["json", "Member[MS_loads]", "Argument[0]", "ReturnValue", "taint"] diff --git a/python/ql/test/library-tests/dataflow/model-summaries/NormalDataflowTest.ext.yml b/python/ql/test/library-tests/dataflow/model-summaries/NormalDataflowTest.ext.yml index 10fbd6df7448..0ed4ca9f172d 100644 --- a/python/ql/test/library-tests/dataflow/model-summaries/NormalDataflowTest.ext.yml +++ b/python/ql/test/library-tests/dataflow/model-summaries/NormalDataflowTest.ext.yml @@ -18,4 +18,7 @@ extensions: - ["foo", "Member[MS_spread]", "Argument[0]", "ReturnValue.TupleElement[0]", "value"] - ["foo", "Member[MS_spread]", "Argument[1]", "ReturnValue.TupleElement[1]", "value"] - ["foo", "Member[MS_spread_all]", "Argument[0]", "ReturnValue.TupleElement[0,1]", "value"] + - ["foo", "Member[MS_Class].Instance.Member[instance_method]", "Argument[self]", "ReturnValue.TupleElement[0]", "value"] + - ["foo", "Member[MS_Class].Instance.Member[instance_method]", "Argument[0]", "ReturnValue.TupleElement[1]", "value"] + - ["foo", "Member[MS_Class].Instance.Member[explicit_self]", "Argument[self:]", "ReturnValue", "value"] - ["json", "Member[MS_loads]", "Argument[0]", "ReturnValue", "taint"] diff --git a/python/ql/test/library-tests/dataflow/model-summaries/model_summaries.py b/python/ql/test/library-tests/dataflow/model-summaries/model_summaries.py index 17f831f6ed12..46b3d6a4db85 100644 --- a/python/ql/test/library-tests/dataflow/model-summaries/model_summaries.py +++ b/python/ql/test/library-tests/dataflow/model-summaries/model_summaries.py @@ -122,6 +122,24 @@ def explicit_identity(x): SINK(a) # $ flow="SOURCE, l:-1 -> a" SINK(b) # $ flow="SOURCE, l:-2 -> b" +from foo import MS_Class + +c = MS_Class() +a, b = c.instance_method(SOURCE) +SINK_F(a) +SINK(b) # $ flow="SOURCE, l:-2 -> b" + +# Call the instance method on the class to expose the self argument +x, y = MS_Class.instance_method(SOURCE, NONSOURCE) +SINK(x) # $ MISSING: flow="SOURCE, l:-1 -> x" +SINK_F(y) + +# Call the instance method on the class to expose the self argument +# That self argument is not referenced by `Argument[self:]` +SINK_F(MS_Class.explicit_self(SOURCE)) +# Instead, `Argument[self:]` refers to a keyword argument named `self` (which you are allowed to do in Python) +SINK(c.explicit_self(self = SOURCE)) # $ flow="SOURCE -> c.explicit_self(..)" + # Modeled flow-summary is not value preserving from json import MS_loads as json_loads diff --git a/ruby/ql/lib/codeql/ruby/Regexp.qll b/ruby/ql/lib/codeql/ruby/Regexp.qll index 1abcee8d2d16..6ca1d40dc632 100644 --- a/ruby/ql/lib/codeql/ruby/Regexp.qll +++ b/ruby/ql/lib/codeql/ruby/Regexp.qll @@ -122,7 +122,9 @@ class StdLibRegExpInterpretation extends RegExpInterpretation::Range { mce.getMethodName() = ["match", "match?"] and this = mce.getArgument(0) and // exclude https://ruby-doc.org/core-2.4.0/Regexp.html#method-i-match - not mce.getReceiver() = RegExpTracking::trackRegexpType() + not mce.getReceiver() = RegExpTracking::trackRegexpType() and + // exclude non-stdlib methods + not exists(mce.getATarget()) ) } } diff --git a/ruby/ql/src/queries/security/cwe-078/examples/file_open.rb b/ruby/ql/src/queries/security/cwe-078/examples/file_open.rb index 3ce1f44817f9..1e0c13d6aca3 100644 --- a/ruby/ql/src/queries/security/cwe-078/examples/file_open.rb +++ b/ruby/ql/src/queries/security/cwe-078/examples/file_open.rb @@ -1,6 +1,9 @@ class UsersController < ActionController::Base - def create - filename = params[:filename] - File.open(filename) - end - end \ No newline at end of file + def create + filename = params[:filename] + File.open(filename) + + web_page = params[:web_page] + Net::HTTP.get(URI.parse(web_page)) + end +end diff --git a/ruby/ql/src/queries/security/cwe-078/examples/kernel_open.rb b/ruby/ql/src/queries/security/cwe-078/examples/kernel_open.rb index 84f8bc8db7d4..ce14c11acede 100644 --- a/ruby/ql/src/queries/security/cwe-078/examples/kernel_open.rb +++ b/ruby/ql/src/queries/security/cwe-078/examples/kernel_open.rb @@ -1,6 +1,11 @@ +require "open-uri" + class UsersController < ActionController::Base def create filename = params[:filename] open(filename) # BAD + + web_page = params[:web_page] + URI.open(web_page) # BAD - calls `Kernel.open` internally end -end \ No newline at end of file +end diff --git a/ruby/ql/test/query-tests/security/cwe-020/IncompleteHostnameRegExp/IncompleteHostnameRegExp.expected b/ruby/ql/test/query-tests/security/cwe-020/IncompleteHostnameRegExp/IncompleteHostnameRegExp.expected index 9110e245cd63..097f43c33e70 100644 --- a/ruby/ql/test/query-tests/security/cwe-020/IncompleteHostnameRegExp/IncompleteHostnameRegExp.expected +++ b/ruby/ql/test/query-tests/security/cwe-020/IncompleteHostnameRegExp/IncompleteHostnameRegExp.expected @@ -28,3 +28,4 @@ | tst-IncompleteHostnameRegExp.rb:48:42:48:67 | ^https?://.+.example\\.com/ | This string, which is used as a regular expression $@, has an unescaped '.' before 'example\\.com/', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.rb:48:13:48:69 | ... + ... | here | | tst-IncompleteHostnameRegExp.rb:48:42:48:67 | ^https?://.+.example\\.com/ | This string, which is used as a regular expression $@, has an unrestricted wildcard '.+' which may cause 'example\\.com/' to be matched anywhere in the URL, outside the hostname. | tst-IncompleteHostnameRegExp.rb:48:13:48:69 | ... + ... | here | | tst-IncompleteHostnameRegExp.rb:59:5:59:20 | foo.example\\.com | This regular expression has an unescaped '.' before 'example\\.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.rb:59:2:59:32 | /^(foo.example\\.com\|whatever)$/ | here | +| tst-IncompleteHostnameRegExp.rb:81:11:81:34 | ^http://test.example.com | This string, which is used as a regular expression $@, has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.rb:77:22:77:22 | x | here | diff --git a/ruby/ql/test/query-tests/security/cwe-020/IncompleteHostnameRegExp/tst-IncompleteHostnameRegExp.rb b/ruby/ql/test/query-tests/security/cwe-020/IncompleteHostnameRegExp/tst-IncompleteHostnameRegExp.rb index 91770040110a..7041e4dc9c46 100644 --- a/ruby/ql/test/query-tests/security/cwe-020/IncompleteHostnameRegExp/tst-IncompleteHostnameRegExp.rb +++ b/ruby/ql/test/query-tests/security/cwe-020/IncompleteHostnameRegExp/tst-IncompleteHostnameRegExp.rb @@ -65,3 +65,17 @@ def convert1(domain) def convert2(domain) return Regexp.new(domain[:hostname]); end + +class A + def self.match?(x) = true +end + +A.match?("^http://test.example.com") # OK + +class B + def self.match?(x) + some_string.match?(x) + end +end + +B.match?("^http://test.example.com") # NOT OK diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index de9f718b347c..10c7efdf045f 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -1119,9 +1119,10 @@ module MakeImpl Lang> { pragma[nomagic] private SndLevelScopeOption getScope(RetNodeEx ret) { - result = SndLevelScopeOption::some(getSecondLevelScope(ret.asNode())) + result = SndLevelScopeOption::some(getSecondLevelScopeCached(ret.asNode())) or - result instanceof SndLevelScopeOption::None and not exists(getSecondLevelScope(ret.asNode())) + result instanceof SndLevelScopeOption::None and + not exists(getSecondLevelScopeCached(ret.asNode())) } pragma[nomagic] diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll index 38c3bba3254f..9524ca9d9aba 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll @@ -616,6 +616,9 @@ module MakeImplCommon Lang> { cached predicate forceCachingInSameStage() { any() } + cached + DataFlowSecondLevelScope getSecondLevelScopeCached(Node n) { result = getSecondLevelScope(n) } + cached predicate nodeEnclosingCallable(Node n, DataFlowCallable c) { c = nodeGetEnclosingCallable(n) }