From 609ca034c0b476e79cd8d709fed4fbc9fb75b6b7 Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Mon, 22 Jul 2019 12:37:21 -0700 Subject: [PATCH] C#/C++: Share IR implementation --- config/identical-files.json | 74 ++++- .../code/cpp/ir/implementation/Opcode.qll | 2 + .../cpp/ir/implementation/TempVariableTag.qll | 3 +- .../aliased_ssa/Instruction.qll | 2 +- .../ir/implementation/aliased_ssa/Operand.qll | 4 +- .../internal/TempVariableTagInternal.qll | 6 + .../cpp/ir/implementation/raw/Instruction.qll | 2 +- .../cpp/ir/implementation/raw/Operand.qll | 4 +- .../unaliased_ssa/Instruction.qll | 2 +- .../implementation/unaliased_ssa/Operand.qll | 4 +- .../code/cpp/ir/internal/IRCppLanguage.qll | 4 + csharp/ql/src/semmle/code/csharp/Type.qll | 29 ++ .../csharp/ir/implementation/EdgeKind.qll | 140 +++++---- .../ir/implementation/IRConfiguration.qll | 19 ++ .../ir/implementation/MemoryAccessKind.qll | 2 - .../code/csharp/ir/implementation/Opcode.qll | 2 + .../ir/implementation/TempVariableTag.qll | 4 +- .../internal/EdgeKindInternal.qll | 1 + .../internal/IRConfigurationInternal.qll | 1 + .../internal/OperandTag.qll | 41 ++- .../internal/OperandTagInternal.qll | 1 + .../implementation/internal/TIRVariable.qll | 12 + .../internal/TIRVariableInternal.qll | 7 + .../internal/TempVariableTagInternal.qll | 6 + .../code/csharp/ir/implementation/raw/IR.qll | 5 +- .../csharp/ir/implementation/raw/IRBlock.qll | 7 +- .../ir/implementation/raw/IRFunction.qll | 19 +- .../ir/implementation/raw/IRVariable.qll | 88 +++--- .../ir/implementation/raw/Instruction.qll | 269 ++++++++---------- .../csharp/ir/implementation/raw/Operand.qll | 118 ++++++-- .../csharp/ir/implementation/raw/PrintIR.qll | 25 +- .../raw/internal/IRBlockImports.qll | 1 + .../raw/internal/IRConstruction.qll | 6 +- .../implementation/raw/internal/IRImports.qll | 2 + .../raw/internal/IRInternal.qll | 1 + .../raw/internal/IRVariableImports.qll | 4 + .../raw/internal/InstructionImports.qll | 4 + .../raw/internal/OperandImports.qll | 3 + .../raw/internal/PrintIRImports.qll | 1 + .../raw/internal/TranslatedCall.qll | 2 +- .../raw/internal/TranslatedCondition.qll | 2 +- .../internal/TranslatedDeclarationEntry.qll | 2 +- .../raw/internal/TranslatedElement.qll | 3 +- .../raw/internal/TranslatedExpr.qll | 2 +- .../raw/internal/TranslatedFunction.qll | 21 +- .../raw/internal/TranslatedInitialization.qll | 2 +- .../raw/internal/TranslatedStmt.qll | 2 +- .../csharp/ir/internal/IRCSharpLanguage.qll | 114 ++++++++ .../csharp/ir/internal/IntegerConstant.qll | 2 - .../code/csharp/ir/internal/Overlap.qll | 2 - .../test/library-tests/ir/ir/raw_ir.expected | 220 +++++++------- 51 files changed, 830 insertions(+), 469 deletions(-) create mode 100644 cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TempVariableTagInternal.qll create mode 100644 csharp/ql/src/semmle/code/csharp/ir/implementation/IRConfiguration.qll create mode 100644 csharp/ql/src/semmle/code/csharp/ir/implementation/internal/EdgeKindInternal.qll create mode 100644 csharp/ql/src/semmle/code/csharp/ir/implementation/internal/IRConfigurationInternal.qll rename csharp/ql/src/semmle/code/csharp/ir/{ => implementation}/internal/OperandTag.qll (92%) create mode 100644 csharp/ql/src/semmle/code/csharp/ir/implementation/internal/OperandTagInternal.qll create mode 100644 csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariable.qll create mode 100644 csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariableInternal.qll create mode 100644 csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TempVariableTagInternal.qll create mode 100644 csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRBlockImports.qll create mode 100644 csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRImports.qll create mode 100644 csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRVariableImports.qll create mode 100644 csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/InstructionImports.qll create mode 100644 csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/OperandImports.qll create mode 100644 csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/PrintIRImports.qll create mode 100644 csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll diff --git a/config/identical-files.json b/config/identical-files.json index 08c3554de5a..756511e536e 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -39,42 +39,82 @@ "IR Instruction": [ "cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll", "cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll", - "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll" + "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll", + "csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll" ], "IR IRBlock": [ "cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRBlock.qll", "cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRBlock.qll", - "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll" + "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll", + "csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRBlock.qll" ], "IR IRVariable": [ "cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll", "cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll", - "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll" + "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll", + "csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll" ], "IR IRFunction": [ "cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRFunction.qll", "cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRFunction.qll", - "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRFunction.qll" + "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRFunction.qll", + "csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRFunction.qll" ], "IR Operand": [ "cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll", "cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll", - "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll" + "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll", + "csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll" ], "IR IR": [ "cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IR.qll", "cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IR.qll", - "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll" + "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll", + "csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IR.qll" ], "IR IRSanity": [ "cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.qll", "cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.qll", - "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll" + "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll", + "csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRSanity.qll" ], "IR PrintIR": [ "cpp/ql/src/semmle/code/cpp/ir/implementation/raw/PrintIR.qll", "cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll", - "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll" + "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll", + "csharp/ql/src/semmle/code/csharp/ir/implementation/raw/PrintIR.qll" + ], + "IR IntegerConstant": [ + "cpp/ql/src/semmle/code/cpp/ir/internal/IntegerConstant.qll", + "csharp/ql/src/semmle/code/csharp/ir/internal/IntegerConstant.qll" + ], + "IR IntegerInteval": [ + "cpp/ql/src/semmle/code/cpp/ir/internal/IntegerInterval.qll", + "csharp/ql/src/semmle/code/csharp/ir/internal/IntegerInterval.qll" + ], + "IR IntegerPartial": [ + "cpp/ql/src/semmle/code/cpp/ir/internal/IntegerPartial.qll", + "csharp/ql/src/semmle/code/csharp/ir/internal/IntegerPartial.qll" + ], + "IR Overlap": [ + "cpp/ql/src/semmle/code/cpp/ir/internal/Overlap.qll", + "csharp/ql/src/semmle/code/csharp/ir/internal/Overlap.qll" + ], + "IR EdgeKind": [ + "cpp/ql/src/semmle/code/cpp/ir/implementation/EdgeKind.qll", + "csharp/ql/src/semmle/code/csharp/ir/implementation/EdgeKind.qll" + ], + "IR MemoryAccessKind": [ + "cpp/ql/src/semmle/code/cpp/ir/implementation/MemoryAccessKind.qll", + "csharp/ql/src/semmle/code/csharp/ir/implementation/MemoryAccessKind.qll" + ], + "IR TempVariableTag": [ + "cpp/ql/src/semmle/code/cpp/ir/implementation/TempVariableTag.qll", + "csharp/ql/src/semmle/code/csharp/ir/implementation/TempVariableTag.qll" + ], + "IR Opcode": [ + "cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll", + "csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll" ], "C++ IR InstructionImports": [ "cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionImports.qll", @@ -148,5 +188,23 @@ "C++ IR PrintDominance": [ "cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/PrintDominance.qll", "cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/PrintDominance.qll" + ], + "C# IR InstructionImports": [ + "csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/InstructionImports.qll" + ], + "C# IR IRImports": [ + "csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRImports.qll" + ], + "C# IR IRBlockImports": [ + "csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRBlockImports.qll" + ], + "C# IR IRVariableImports": [ + "csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRVariableImports.qll" + ], + "C# IR OperandImports": [ + "csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/OperandImports.qll" + ], + "C# IR PrintIRImports": [ + "csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/PrintIRImports.qll" ] } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll index fd08d24bc73..5f884ac0bcb 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll @@ -42,6 +42,7 @@ private newtype TOpcode = TDynamicCastToVoid() or TVariableAddress() or TFieldAddress() or + TIndexedElementAddress() or TFunctionAddress() or TConstant() or TStringConstant() or @@ -190,6 +191,7 @@ module Opcode { class DynamicCastToVoid extends UnaryOpcode, TDynamicCastToVoid { override final string toString() { result = "DynamicCastToVoid" } } class VariableAddress extends Opcode, TVariableAddress { override final string toString() { result = "VariableAddress" } } class FieldAddress extends UnaryOpcode, TFieldAddress { override final string toString() { result = "FieldAddress" } } + class IndexedElementAddress extends BinaryOpcode, TIndexedElementAddress { override final string toString() { result = "IndexedElementAddress" } } class FunctionAddress extends Opcode, TFunctionAddress { override final string toString() { result = "FunctionAddress" } } class Constant extends Opcode, TConstant { override final string toString() { result = "Constant" } } class StringConstant extends Opcode, TStringConstant { override final string toString() { result = "StringConstant" } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/TempVariableTag.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/TempVariableTag.qll index fe0eceab578..da5cfca3f02 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/TempVariableTag.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/TempVariableTag.qll @@ -1,4 +1,5 @@ -private import semmle.code.cpp.ir.internal.TempVariableTag +private import internal.TempVariableTagInternal +private import Imports::TempVariableTag class TempVariableTag extends TTempVariableTag { string toString() { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index 3066feb2791..7b621c95dcc 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -512,7 +512,7 @@ class Instruction extends Construction::TInstruction { else if getResultType() instanceof Language::UnknownType then result = Construction::getInstructionResultSize(this) else ( - result = getResultType().getSize() + result = Language::getTypeSize(getResultType()) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll index 23cc9dd3638..29af8267cb7 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll @@ -186,7 +186,7 @@ class Operand extends TOperand { * a known constant size, this predicate does not hold. */ int getSize() { - result = getType().getSize() + result = Language::getTypeSize(getType()) } } @@ -450,7 +450,7 @@ class SideEffectOperand extends TypedOperand { if getType() instanceof Language::UnknownType then result = Construction::getInstructionOperandSize(useInstr, tag) else - result = getType().getSize() + result = Language::getTypeSize(getType()) } override MemoryAccessKind getMemoryAccess() { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TempVariableTagInternal.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TempVariableTagInternal.qll new file mode 100644 index 00000000000..c5e07a351ab --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TempVariableTagInternal.qll @@ -0,0 +1,6 @@ +import semmle.code.cpp.ir.internal.IRCppLanguage as Language +private import semmle.code.cpp.ir.internal.TempVariableTag as TempVariableTag_ + +module Imports { + module TempVariableTag = TempVariableTag_; +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index 3066feb2791..7b621c95dcc 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -512,7 +512,7 @@ class Instruction extends Construction::TInstruction { else if getResultType() instanceof Language::UnknownType then result = Construction::getInstructionResultSize(this) else ( - result = getResultType().getSize() + result = Language::getTypeSize(getResultType()) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll index 23cc9dd3638..29af8267cb7 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll @@ -186,7 +186,7 @@ class Operand extends TOperand { * a known constant size, this predicate does not hold. */ int getSize() { - result = getType().getSize() + result = Language::getTypeSize(getType()) } } @@ -450,7 +450,7 @@ class SideEffectOperand extends TypedOperand { if getType() instanceof Language::UnknownType then result = Construction::getInstructionOperandSize(useInstr, tag) else - result = getType().getSize() + result = Language::getTypeSize(getType()) } override MemoryAccessKind getMemoryAccess() { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index 3066feb2791..7b621c95dcc 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -512,7 +512,7 @@ class Instruction extends Construction::TInstruction { else if getResultType() instanceof Language::UnknownType then result = Construction::getInstructionResultSize(this) else ( - result = getResultType().getSize() + result = Language::getTypeSize(getResultType()) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll index 23cc9dd3638..29af8267cb7 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll @@ -186,7 +186,7 @@ class Operand extends TOperand { * a known constant size, this predicate does not hold. */ int getSize() { - result = getType().getSize() + result = Language::getTypeSize(getType()) } } @@ -450,7 +450,7 @@ class SideEffectOperand extends TypedOperand { if getType() instanceof Language::UnknownType then result = Construction::getInstructionOperandSize(useInstr, tag) else - result = getType().getSize() + result = Language::getTypeSize(getType()) } override MemoryAccessKind getMemoryAccess() { diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll index 45d5c5ffcb2..84b6d7fbeb9 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll @@ -52,6 +52,10 @@ predicate hasAsmOperandIndex(int operandIndex) { ) } +int getTypeSize(Type type) { + result = type.getSize() +} + int getPointerSize() { exists(Cpp::NullPointerType nullptr | result = nullptr.getSize() diff --git a/csharp/ql/src/semmle/code/csharp/Type.qll b/csharp/ql/src/semmle/code/csharp/Type.qll index c1f35c098ce..98f9e6db361 100644 --- a/csharp/ql/src/semmle/code/csharp/Type.qll +++ b/csharp/ql/src/semmle/code/csharp/Type.qll @@ -422,6 +422,9 @@ class ValueType extends ValueOrRefType, @value_type { * (`FloatingPointType`), or a decimal type (`DecimalType`). */ class SimpleType extends ValueType, @simple_type { + /** Gets the size of this type, in bytes. */ + int getSize() { none() } + /** Gets the minimum integral value of this type, if any. */ int minValue() { none() } @@ -436,6 +439,8 @@ class SimpleType extends ValueType, @simple_type { */ class BoolType extends SimpleType, @bool_type { override string toStringWithTypes() { result = "bool" } + + override int getSize() { result = 1 } } /** @@ -444,6 +449,8 @@ class BoolType extends SimpleType, @bool_type { class CharType extends SimpleType, @char_type { override string toStringWithTypes() { result = "char" } + override int getSize() { result = 2 } + override int minValue() { result = 0 } override int maxValue() { result = 65535 } @@ -481,6 +488,8 @@ class SignedIntegralType extends IntegralType, @signed_integral_type { } class SByteType extends SignedIntegralType, @sbyte_type { override string toStringWithTypes() { result = "sbyte" } + override int getSize() { result = 1 } + override int minValue() { result = -128 } override int maxValue() { result = 127 } @@ -492,6 +501,8 @@ class SByteType extends SignedIntegralType, @sbyte_type { class ShortType extends SignedIntegralType, @short_type { override string toStringWithTypes() { result = "short" } + override int getSize() { result = 2 } + override int minValue() { result = -32768 } override int maxValue() { result = 32767 } @@ -503,6 +514,8 @@ class ShortType extends SignedIntegralType, @short_type { class IntType extends SignedIntegralType, @int_type { override string toStringWithTypes() { result = "int" } + override int getSize() { result = 4 } + override int minValue() { result = -2147483647 - 1 } override int maxValue() { result = 2147483647 } @@ -513,6 +526,8 @@ class IntType extends SignedIntegralType, @int_type { */ class LongType extends SignedIntegralType, @long_type { override string toStringWithTypes() { result = "long" } + + override int getSize() { result = 8 } } /** @@ -521,6 +536,8 @@ class LongType extends SignedIntegralType, @long_type { class ByteType extends UnsignedIntegralType, @byte_type { override string toStringWithTypes() { result = "byte" } + override int getSize() { result = 1 } + override int maxValue() { result = 255 } } @@ -530,6 +547,8 @@ class ByteType extends UnsignedIntegralType, @byte_type { class UShortType extends UnsignedIntegralType, @ushort_type { override string toStringWithTypes() { result = "ushort" } + override int getSize() { result = 2 } + override int maxValue() { result = 65535 } } @@ -538,6 +557,8 @@ class UShortType extends UnsignedIntegralType, @ushort_type { */ class UIntType extends UnsignedIntegralType, @uint_type { override string toStringWithTypes() { result = "uint" } + + override int getSize() { result = 4 } } /** @@ -545,6 +566,8 @@ class UIntType extends UnsignedIntegralType, @uint_type { */ class ULongType extends UnsignedIntegralType, @ulong_type { override string toStringWithTypes() { result = "ulong" } + + override int getSize() { result = 8 } } /** @@ -559,6 +582,8 @@ class FloatingPointType extends SimpleType, @floating_point_type { } */ class FloatType extends FloatingPointType, @float_type { override string toStringWithTypes() { result = "float" } + + override int getSize() { result = 4 } } /** @@ -566,6 +591,8 @@ class FloatType extends FloatingPointType, @float_type { */ class DoubleType extends FloatingPointType, @double_type { override string toStringWithTypes() { result = "double" } + + override int getSize() { result = 8 } } /** @@ -573,6 +600,8 @@ class DoubleType extends FloatingPointType, @double_type { */ class DecimalType extends SimpleType, @decimal_type { override string toStringWithTypes() { result = "decimal" } + + override int getSize() { result = 16 } } /** diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/EdgeKind.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/EdgeKind.qll index a29435a3923..3266c8b1661 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/EdgeKind.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/EdgeKind.qll @@ -1,19 +1,15 @@ -// TODO: Fix the switch -import csharp +private import internal.EdgeKindInternal private newtype TEdgeKind = - TGotoEdge() or // Single successor (including fall-through) - TTrueEdge() or // 'true' edge of conditional branch - TFalseEdge() or // 'false' edge of conditional branch - TExceptionEdge() or // Thrown exception - TDefaultEdge() or // 'default' label of switch - TCaseEdge() + TGotoEdge() or // Single successor (including fall-through) + TTrueEdge() or // 'true' edge of conditional branch + TFalseEdge() or // 'false' edge of conditional branch + TExceptionEdge() or // Thrown exception + TDefaultEdge() or // 'default' label of switch + TCaseEdge(string minValue, string maxValue) { // Case label of switch + Language::hasCaseEdge(minValue, maxValue) + } -// TCaseEdge(Expr expr, string condition) { // Case label of switch -// exists(CaseStmt caseStmt | -// hasCaseEdge(caseStmt, minValue, maxValue) -// ) -// } /** * Represents the kind of an edge in the IR control flow graph. Each * `Instruction` or `IRBlock` has at most one successor of any single @@ -28,99 +24,99 @@ abstract class EdgeKind extends TEdgeKind { * or `IRBlock`. */ class GotoEdge extends EdgeKind, TGotoEdge { - final override string toString() { result = "Goto" } + override final string toString() { + result = "Goto" + } } -GotoEdge gotoEdge() { result = TGotoEdge() } +GotoEdge gotoEdge() { + result = TGotoEdge() +} /** * A "true" edge, representing the successor of a conditional branch when the * condition is non-zero. */ class TrueEdge extends EdgeKind, TTrueEdge { - final override string toString() { result = "True" } + override final string toString() { + result = "True" + } } -TrueEdge trueEdge() { result = TTrueEdge() } +TrueEdge trueEdge() { + result = TTrueEdge() +} /** * A "false" edge, representing the successor of a conditional branch when the * condition is zero. */ class FalseEdge extends EdgeKind, TFalseEdge { - final override string toString() { result = "False" } + override final string toString() { + result = "False" + } } -FalseEdge falseEdge() { result = TFalseEdge() } +FalseEdge falseEdge() { + result = TFalseEdge() +} /** * An "exception" edge, representing the successor of an instruction when that * instruction's evaluation throws an exception. */ class ExceptionEdge extends EdgeKind, TExceptionEdge { - final override string toString() { result = "Exception" } + override final string toString() { + result = "Exception" + } } -ExceptionEdge exceptionEdge() { result = TExceptionEdge() } +ExceptionEdge exceptionEdge() { + result = TExceptionEdge() +} /** * A "default" edge, representing the successor of a `Switch` instruction when * none of the case values matches the condition value. */ class DefaultEdge extends EdgeKind, TDefaultEdge { - final override string toString() { result = "Default" } + override final string toString() { + result = "Default" + } } -DefaultEdge defaultEdge() { result = TDefaultEdge() } +DefaultEdge defaultEdge() { + result = TDefaultEdge() +} -///** -// * A "case" edge, representing the successor of a `Switch` instruction when the -// * the condition value matches a correponding `case` label. -// */ +/** + * A "case" edge, representing the successor of a `Switch` instruction when the + * the condition value matches a correponding `case` label. + */ class CaseEdge extends EdgeKind, TCaseEdge { - final override string toString() { result = "CASE" } + string minValue; + string maxValue; + + CaseEdge() { + this = TCaseEdge(minValue, maxValue) + } + + override final string toString() { + if minValue = maxValue then + result = "Case[" + minValue + "]" + else + result = "Case[" + minValue + ".." + maxValue + "]" + } + + string getMinValue() { + result = minValue + } + + string getMaxValue() { + result = maxValue + } +} + +CaseEdge caseEdge(string minValue, string maxValue) { + result = TCaseEdge(minValue, maxValue) } -//class CaseEdge extends EdgeKind, TCaseEdge { -// string minValue; -// string maxValue; -// -// CaseEdge() { -// this = TCaseEdge(minValue, maxValue) -// } -// -// override final string toString() { -// if minValue = maxValue then -// result = "Case[" + minValue + "]" -// else -// result = "Case[" + minValue + ".." + maxValue + "]" -// } -// -// string getMinValue() { -// result = minValue -// } -// -// string getMaxValue() { -// result = maxValue -// } -//} -// -//CaseEdge caseEdge(string minValue, string maxValue) { -// result = TCaseEdge(minValue, maxValue) -//} -// -//private predicate hasCaseEdge(CaseStmt caseStmt, string minValue, -// string maxValue) { -// minValue = caseStmt.getExpr().stripCasts().getValue() and -// if exists(caseStmt.getEndExpr()) then -// maxValue = caseStmt.getEndExpr().getFullyConverted().getValue() -// else -// maxValue = minValue -//} -// -//EdgeKind getCaseEdge(SwitchStmt switchStmt) { -// exists(CaseEdge edge | -// result = edge and -// hasCaseEdge(switchStmt, edge.getMinValue(), edge.getMaxValue()) -// ) or -// (switchStmt instanceof DefaultCase and result instanceof DefaultEdge) -//} diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/IRConfiguration.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/IRConfiguration.qll new file mode 100644 index 00000000000..e4a1f1cecf1 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/IRConfiguration.qll @@ -0,0 +1,19 @@ +private import internal.IRConfigurationInternal + +private newtype TIRConfiguration = MkIRConfiguration() + +/** + * The query can extend this class to control which functions have IR generated for them. + */ +class IRConfiguration extends TIRConfiguration { + string toString() { + result = "IRConfiguration" + } + + /** + * Holds if IR should be created for function `func`. By default, holds for all functions. + */ + predicate shouldCreateIRForFunction(Language::Function func) { + any() + } +} diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/MemoryAccessKind.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/MemoryAccessKind.qll index a17f3b3f6cd..db45b8a2678 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/MemoryAccessKind.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/MemoryAccessKind.qll @@ -1,5 +1,3 @@ -import csharp - private newtype TMemoryAccessKind = TIndirectMemoryAccess() or TIndirectMayMemoryAccess() or diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll index 3c5813e41ed..6aef58dd634 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll @@ -1,6 +1,7 @@ private newtype TOpcode = TNoOp() or TUninitialized() or + TError() or TInitializeParameter() or TInitializeThis() or TEnterFunction() or @@ -148,6 +149,7 @@ abstract class BufferAccessOpcode extends MemoryAccessOpcode {} module Opcode { class NoOp extends Opcode, TNoOp { override final string toString() { result = "NoOp" } } class Uninitialized extends MemoryAccessOpcode, TUninitialized { override final string toString() { result = "Uninitialized" } } + class Error extends Opcode, TError { override final string toString() { result = "Error" } } class InitializeParameter extends MemoryAccessOpcode, TInitializeParameter { override final string toString() { result = "InitializeParameter" } } class InitializeThis extends Opcode, TInitializeThis { override final string toString() { result = "InitializeThis" } } class EnterFunction extends Opcode, TEnterFunction { override final string toString() { result = "EnterFunction" } } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/TempVariableTag.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/TempVariableTag.qll index ae034da7e41..da5cfca3f02 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/TempVariableTag.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/TempVariableTag.qll @@ -1,5 +1,5 @@ -import csharp -private import semmle.code.csharp.ir.internal.TempVariableTag +private import internal.TempVariableTagInternal +private import Imports::TempVariableTag class TempVariableTag extends TTempVariableTag { string toString() { diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/EdgeKindInternal.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/EdgeKindInternal.qll new file mode 100644 index 00000000000..0ee01a30ac3 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/EdgeKindInternal.qll @@ -0,0 +1 @@ +import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/IRConfigurationInternal.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/IRConfigurationInternal.qll new file mode 100644 index 00000000000..0ee01a30ac3 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/IRConfigurationInternal.qll @@ -0,0 +1 @@ +import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language diff --git a/csharp/ql/src/semmle/code/csharp/ir/internal/OperandTag.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/OperandTag.qll similarity index 92% rename from csharp/ql/src/semmle/code/csharp/ir/internal/OperandTag.qll rename to csharp/ql/src/semmle/code/csharp/ir/implementation/internal/OperandTag.qll index 3e9b7e813dd..ae32229522f 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/internal/OperandTag.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/OperandTag.qll @@ -1,12 +1,4 @@ -import csharp - -private int getMaxCallArgIndex() { - result = max(int argIndex | - exists(MethodCall call | - exists(call.getArgument(argIndex)) - ) - ) -} +private import OperandTagInternal private newtype TOperandTag = TAddressOperand() or @@ -22,10 +14,13 @@ private newtype TOperandTag = TCallTargetOperand() or TThisArgumentOperand() or TPositionalArgumentOperand(int argIndex) { - argIndex in [0..getMaxCallArgIndex()] + Language::hasPositionalArgIndex(argIndex) } or TChiTotalOperand() or - TChiPartialOperand() + TChiPartialOperand() or + TAsmOperand(int index) { + Language::hasAsmOperandIndex(index) + } /** * Identifies the kind of operand on an instruction. Each `Instruction` has at @@ -359,3 +354,27 @@ class ChiPartialOperandTag extends MemoryOperandTag, TChiPartialOperand { ChiPartialOperandTag chiPartialOperand() { result = TChiPartialOperand() } + +class AsmOperandTag extends RegisterOperandTag, TAsmOperand { + int index; + + AsmOperandTag() { + this = TAsmOperand(index) + } + + override final string toString() { + result = "AsmOperand(" + index + ")" + } + + override final int getSortOrder() { + result = 15 + index + } + + override final string getLabel() { + result = index.toString() + ":" + } +} + +AsmOperandTag asmOperand(int index) { + result = TAsmOperand(index) +} \ No newline at end of file diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/OperandTagInternal.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/OperandTagInternal.qll new file mode 100644 index 00000000000..0ee01a30ac3 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/OperandTagInternal.qll @@ -0,0 +1 @@ +import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariable.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariable.qll new file mode 100644 index 00000000000..c0edfe0e553 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariable.qll @@ -0,0 +1,12 @@ +private import TIRVariableInternal +private import Imports::TempVariableTag + +newtype TIRVariable = + TIRUserVariable(Language::Variable var, Language::Type type, + Language::Function func) { + Construction::hasUserVariable(func, var, type) + } or + TIRTempVariable(Language::Function func, Language::AST ast, TempVariableTag tag, + Language::Type type) { + Construction::hasTempVariable(func, ast, tag, type) + } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariableInternal.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariableInternal.qll new file mode 100644 index 00000000000..4dee687dabd --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariableInternal.qll @@ -0,0 +1,7 @@ +import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language +import semmle.code.csharp.ir.implementation.raw.internal.IRConstruction as Construction +private import semmle.code.csharp.ir.implementation.TempVariableTag as TempVariableTag_ + +module Imports { + module TempVariableTag = TempVariableTag_; +} diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TempVariableTagInternal.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TempVariableTagInternal.qll new file mode 100644 index 00000000000..354a09f0f58 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TempVariableTagInternal.qll @@ -0,0 +1,6 @@ +import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language +private import semmle.code.csharp.ir.internal.TempVariableTag as TempVariableTag_ + +module Imports { + module TempVariableTag = TempVariableTag_; +} diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IR.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IR.qll index 6fc59169197..5bc9493f4ab 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IR.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IR.qll @@ -3,8 +3,9 @@ import Instruction import IRBlock import IRVariable import Operand -import semmle.code.csharp.ir.implementation.EdgeKind -import semmle.code.csharp.ir.implementation.MemoryAccessKind +private import internal.IRImports as Imports +import Imports::EdgeKind +import Imports::MemoryAccessKind private newtype TIRPropertyProvider = MkIRPropertyProvider() diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRBlock.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRBlock.qll index dcd8872c9fb..c62a2dbc5ea 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRBlock.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRBlock.qll @@ -1,6 +1,7 @@ private import internal.IRInternal import Instruction -import semmle.code.csharp.ir.implementation.EdgeKind +private import internal.IRBlockImports as Imports +import Imports::EdgeKind private import Cached /** @@ -19,7 +20,7 @@ class IRBlockBase extends TIRBlock { result = getFirstInstruction(this).toString() } - final Location getLocation() { + final Language::Location getLocation() { result = getFirstInstruction().getLocation() } @@ -67,7 +68,7 @@ class IRBlockBase extends TIRBlock { result = getFirstInstruction(this).getEnclosingIRFunction() } - final Callable getEnclosingFunction() { + final Language::Function getEnclosingFunction() { result = getFirstInstruction(this).getEnclosingFunction() } } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRFunction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRFunction.qll index 24baf7e7a86..1dd61fb9db1 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRFunction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRFunction.qll @@ -1,38 +1,37 @@ private import internal.IRInternal import Instruction -import csharp private newtype TIRFunction = - MkIRFunction(Callable callable) { - Construction::functionHasIR(callable) + MkIRFunction(Language::Function func) { + Construction::functionHasIR(func) } /** * Represents the IR for a function. */ class IRFunction extends TIRFunction { - Callable callable; + Language::Function func; IRFunction() { - this = MkIRFunction(callable) + this = MkIRFunction(func) } final string toString() { - result = "IR: " + callable.toString() + result = "IR: " + func.toString() } /** * Gets the function whose IR is represented. */ - final Callable getFunction() { - result = callable + final Language::Function getFunction() { + result = func } /** * Gets the location of the function. */ - final Location getLocation() { - result = callable.getLocation() + final Language::Location getLocation() { + result = func.getLocation() } /** diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll index 33d8bb31814..b8c6af20a60 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll @@ -1,15 +1,14 @@ private import internal.IRInternal import IRFunction -import csharp -import semmle.code.csharp.ir.implementation.TempVariableTag -private import semmle.code.csharp.ir.internal.IRUtilities -private import semmle.code.csharp.ir.internal.TempVariableTag -private import semmle.code.csharp.ir.internal.TIRVariable -private import semmle.code.csharp.ir.Util +private import internal.IRVariableImports as Imports +import Imports::TempVariableTag +private import Imports::IRUtilities +private import Imports::TTempVariableTag +private import Imports::TIRVariable -IRUserVariable getIRUserVariable(Callable callable, Variable var) { +IRUserVariable getIRUserVariable(Language::Function func, Language::Variable var) { result.getVariable() = var and - result.getEnclosingFunction() = callable + result.getEnclosingFunction() = func } /** @@ -18,20 +17,20 @@ IRUserVariable getIRUserVariable(Callable callable, Variable var) { * generated by the AST-to-IR translation (`IRTempVariable`). */ abstract class IRVariable extends TIRVariable { - Callable callable; + Language::Function func; abstract string toString(); /** * Gets the type of the variable. */ - abstract Type getType(); + abstract Language::Type getType(); /** * Gets the AST node that declared this variable, or that introduced this * variable as part of the AST-to-IR translation. */ - abstract Locatable getAST(); + abstract Language::AST getAST(); /** * Gets an identifier string for the variable. This identifier is unique @@ -42,7 +41,7 @@ abstract class IRVariable extends TIRVariable { /** * Gets the source location of this variable. */ - final Location getLocation() { + final Language::Location getLocation() { result = getAST().getLocation() } @@ -50,43 +49,48 @@ abstract class IRVariable extends TIRVariable { * Gets the IR for the function that references this variable. */ final IRFunction getEnclosingIRFunction() { - result.getFunction() = callable + result.getFunction() = func } /** * Gets the function that references this variable. */ - final Callable getEnclosingFunction() { - result = callable + final Language::Function getEnclosingFunction() { + result = func } } /** * Represents a user-declared variable referenced by the IR for a function. */ -abstract class IRUserVariable extends IRVariable { - Variable var; +class IRUserVariable extends IRVariable, TIRUserVariable { + Language::Variable var; + Language::Type type; + + IRUserVariable() { + this = TIRUserVariable(var, type, func) + } override final string toString() { - result = var.toString() + result = getVariable().toString() } - override final Type getType() { - result = getVariableType(var) - } - - override final Locatable getAST() { + override final Language::AST getAST() { result = var } override final string getUniqueId() { - result = var.toString() + " " + var.getLocation().toString() + result = getVariable().toString() + " " + getVariable().getLocation().toString() + } + + override final Language::Type getType() { + result = type } /** * Gets the original user-declared variable. */ - final Variable getVariable() { + Language::Variable getVariable() { result = var } } @@ -99,45 +103,49 @@ abstract class IRUserVariable extends IRVariable { abstract class IRAutomaticVariable extends IRVariable { } -class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable, - TIRAutomaticUserVariable { - LocalScopeVariable localVar; +class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable { + override Language::AutomaticVariable var; IRAutomaticUserVariable() { - this = TIRAutomaticUserVariable(localVar, callable) and - var = localVar + Language::isVariableAutomatic(var) } - final LocalScopeVariable getLocalVariable() { - result = localVar + final override Language::AutomaticVariable getVariable() { + result = var } } -class IRStaticUserVariable extends IRUserVariable, TIRStaticUserVariable { +class IRStaticUserVariable extends IRUserVariable { + override Language::StaticVariable var; + IRStaticUserVariable() { - this = TIRStaticUserVariable(var, callable) + not Language::isVariableAutomatic(var) + } + + final override Language::StaticVariable getVariable() { + result = var } } -IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) { +IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { result.getAST() = ast and result.getTag() = tag } class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Locatable ast; + Language::AST ast; TempVariableTag tag; - Type type; + Language::Type type; IRTempVariable() { - this = TIRTempVariable(callable, ast, tag, type) + this = TIRTempVariable(func, ast, tag, type) } - override final Type getType() { + override final Language::Type getType() { result = type } - override final Locatable getAST() { + override final Language::AST getAST() { result = ast } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll index 316ca2f7b2f..34d2d21d6e0 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll @@ -3,13 +3,11 @@ import IRFunction import IRBlock import IRVariable import Operand -import csharp -import semmle.code.csharp.ir.implementation.EdgeKind -import semmle.code.csharp.ir.implementation.MemoryAccessKind -import semmle.code.csharp.ir.implementation.Opcode -private import semmle.code.csharp.ir.implementation.Opcode -private import semmle.code.csharp.ir.internal.OperandTag -private import semmle.code.csharp.ir.Util +private import internal.InstructionImports as Imports +import Imports::EdgeKind +import Imports::MemoryAccessKind +import Imports::Opcode +private import Imports::OperandTag module InstructionSanity { /** @@ -51,7 +49,6 @@ module InstructionSanity { * Holds if instruction `instr` is missing an expected operand with tag `tag`. */ query predicate missingOperand(Instruction instr, string message, IRFunction func, string funcText) { - instr.getAST().fromSource() and exists(OperandTag tag | expectsOperand(instr, tag) and not exists(NonPhiOperand operand | @@ -61,7 +58,7 @@ module InstructionSanity { message = "Instruction '" + instr.getOpcode().toString() + "' is missing an expected operand with tag '" + tag.toString() + "' in function '$@'." and func = instr.getEnclosingIRFunction() and - funcText = func.getFunction().getName() + funcText = Language::getIdentityString(func.getFunction()) ) } @@ -69,20 +66,19 @@ module InstructionSanity { * Holds if instruction `instr` has an unexpected operand with tag `tag`. */ query predicate unexpectedOperand(Instruction instr, OperandTag tag) { - instr.getAST().fromSource() and exists(NonPhiOperand operand | operand = instr.getAnOperand() and operand.getOperandTag() = tag) and not expectsOperand(instr, tag) and not (instr instanceof CallInstruction and tag instanceof ArgumentOperandTag) and - not (instr instanceof BuiltInInstruction and tag instanceof PositionalArgumentOperandTag) + not (instr instanceof BuiltInInstruction and tag instanceof PositionalArgumentOperandTag) and + not (instr instanceof InlineAsmInstruction and tag instanceof AsmOperandTag) } /** * Holds if instruction `instr` has multiple operands with tag `tag`. */ query predicate duplicateOperand(Instruction instr, OperandTag tag) { - instr.getAST().fromSource() and strictcount(NonPhiOperand operand | operand = instr.getAnOperand() and operand.getOperandTag() = tag @@ -95,7 +91,6 @@ module InstructionSanity { * the predecessor block `pred`. */ query predicate missingPhiOperand(PhiInstruction instr, IRBlock pred) { - instr.getAST().fromSource() and pred.getEnclosingFunction().fromSource() and pred = instr.getBlock().getAPredecessor() and not exists(PhiInputOperand operand | operand = instr.getAnOperand() and @@ -104,10 +99,10 @@ module InstructionSanity { } query predicate missingOperandType(Operand operand, string message) { - exists(Callable callable | + exists(Language::Function func | not exists(operand.getType()) and - callable = operand.getUseInstruction().getEnclosingFunction() and - message = "Operand missing type in function '" + callable.getName() + "'." + func = operand.getUse().getEnclosingFunction() and + message = "Operand missing type in function '" + Language::getIdentityString(func) + "'." ) } @@ -115,7 +110,6 @@ module InstructionSanity { * Holds if an instruction, other than `ExitFunction`, has no successors. */ query predicate instructionWithoutSuccessor(Instruction instr) { - instr.getAST().fromSource() and not exists(instr.getASuccessor()) and not instr instanceof ExitFunctionInstruction and // Phi instructions aren't linked into the instruction-level flow graph. @@ -130,7 +124,6 @@ module InstructionSanity { query predicate ambiguousSuccessors( Instruction source, EdgeKind kind, int n, Instruction target ) { - source.getAST().fromSource() and target.getAST().fromSource() and n = strictcount(Instruction t | source.getSuccessor(kind) = t) and n > 1 and source.getSuccessor(kind) = target @@ -140,15 +133,13 @@ module InstructionSanity { * Holds if `instr` in `f` is part of a loop even though the AST of `f` * contains no element that can cause loops. */ - query predicate unexplainedLoop(Callable f, Instruction instr) { - instr.getAST().fromSource() and f.fromSource() and + query predicate unexplainedLoop(Language::Function f, Instruction instr) { exists(IRBlock block | instr.getBlock() = block and block.getEnclosingFunction() = f and block.getASuccessor+() = block ) and - not exists(LoopStmt l | l.getEnclosingCallable() = f) and - not exists(GotoStmt s | s.getEnclosingCallable() = f) + not Language::hasPotentialLoop(f) } /** @@ -156,7 +147,6 @@ module InstructionSanity { * predecessors. */ query predicate unnecessaryPhiInstruction(PhiInstruction instr) { - instr.getAST().fromSource() and count(instr.getBlock().getAPredecessor()) < 2 } @@ -165,9 +155,8 @@ module InstructionSanity { * a different function. */ query predicate operandAcrossFunctions(Operand operand, Instruction instr, Instruction defInstr) { - instr.getAST().fromSource() and defInstr.getAST().fromSource() and - operand.getUseInstruction() = instr and - operand.getDefinitionInstruction() = defInstr and + operand.getUse() = instr and + operand.getAnyDef() = defInstr and instr.getEnclosingIRFunction() != defInstr.getEnclosingIRFunction() } @@ -175,13 +164,11 @@ module InstructionSanity { * Holds if instruction `instr` is not in exactly one block. */ query predicate instructionWithoutUniqueBlock(Instruction instr, int blockCount) { - instr.getAST().fromSource() and blockCount = count(instr.getBlock()) and blockCount != 1 } private predicate forwardEdge(IRBlock b1, IRBlock b2) { - b1.getEnclosingFunction().fromSource() and b2.getEnclosingFunction().fromSource() and b1.getASuccessor() = b2 and not b1.getBackEdgeSuccessor(_) = b2 } @@ -192,7 +179,6 @@ module InstructionSanity { * This check ensures we don't have too _few_ back edges. */ query predicate containsLoopOfForwardEdges(IRFunction f) { - f.getFunction().fromSource() and exists(IRBlock block | forwardEdge+(block, block) and block.getEnclosingIRFunction() = f @@ -208,12 +194,11 @@ module InstructionSanity { * This check ensures we don't have too _many_ back edges. */ query predicate lostReachability(IRBlock block) { - block.getEnclosingFunction().fromSource() and exists(IRFunction f, IRBlock entry | entry = f.getEntryBlock() and entry.getASuccessor+() = block and not forwardEdge+(entry, block) and - not exists(GotoStmt s | s.getEnclosingCallable() = f.getFunction()) + not Language::hasGoto(f.getFunction()) ) } @@ -221,8 +206,7 @@ module InstructionSanity { * Holds if the number of back edges differs between the `Instruction` graph * and the `IRBlock` graph. */ - query predicate backEdgeCountMismatch(Callable f, int fromInstr, int fromBlock) { - f.fromSource() and + query predicate backEdgeCountMismatch(Language::Function f, int fromInstr, int fromBlock) { fromInstr = count(Instruction i1, Instruction i2 | i1.getEnclosingFunction() = f and i1.getBackEdgeSuccessor(_) = i2 ) and @@ -279,7 +263,7 @@ class Instruction extends Construction::TInstruction { } private string getResultPrefix() { - if getResultType() instanceof VoidType then + if getResultType() instanceof Language::VoidType then result = "v" else if hasMemoryResult() then if isResultModeled() then @@ -316,20 +300,19 @@ class Instruction extends Construction::TInstruction { bindingset[type] private string getValueCategoryString(string type) { - if isLValue() then - result = "lval<" + type + ">" + if isGLValue() then + result = "glval<" + type + ">" else result = type } - // TODO: Memory model in C#? string getResultTypeString() { exists(string valcat | valcat = getValueCategoryString(getResultType().toString()) and - if (getResultType() instanceof UnknownType and - not isLValue())/* and - exists(getResultSize()))*/ then ( - result = valcat + "[" + /*getResultSize().toString()*/8.toString() + "]" + if (getResultType() instanceof Language::UnknownType and + not isGLValue() and + exists(getResultSize())) then ( + result = valcat + "[" + getResultSize().toString() + "]" ) else result = valcat @@ -393,7 +376,7 @@ class Instruction extends Construction::TInstruction { /** * Gets the function that contains this instruction. */ - final Callable getEnclosingFunction() { + final Language::Function getEnclosingFunction() { result = getEnclosingIRFunction().getFunction() } @@ -407,28 +390,28 @@ class Instruction extends Construction::TInstruction { /** * Gets the AST that caused this instruction to be generated. */ - final Locatable getAST() { + final Language::AST getAST() { result = Construction::getInstructionAST(this) } /** * Gets the location of the source code for this instruction. */ - final Location getLocation() { + final Language::Location getLocation() { result = getAST().getLocation() } /** * Gets the `Expr` whose result is computed by this instruction, if any. */ - final Expr getConvertedResultExpression() { + final Language::Expr getConvertedResultExpression() { result = Construction::getInstructionConvertedResultExpression(this) } /** * Gets the unconverted `Expr` whose result is computed by this instruction, if any. */ - final Expr getUnconvertedResultExpression() { + final Language::Expr getUnconvertedResultExpression() { result = Construction::getInstructionUnconvertedResultExpression(this) } @@ -439,7 +422,7 @@ class Instruction extends Construction::TInstruction { * If `isGLValue()` holds, then the result type of this instruction should be * thought of as "pointer to `getResultType()`". */ - final Type getResultType() { + final Language::Type getResultType() { Construction::instructionHasType(this, result, _) } @@ -461,31 +444,28 @@ class Instruction extends Construction::TInstruction { * result of the `Load` instruction is a prvalue of type `int`, representing * the integer value loaded from variable `x`. */ - final predicate isLValue() { + final predicate isGLValue() { Construction::instructionHasType(this, _, true) } -// TODO: Memory model in C# -// /** -// * Gets the size of the result produced by this instruction, in bytes. If the -// * result does not have a known constant size, this predicate does not hold. -// * -// * If `this.isGLValue()` holds for this instruction, the value of -// * `getResultSize()` will always be the size of a pointer. -// */ -// final int getResultSize() { -// if isGLValue() then ( -// // a glvalue is always pointer-sized. -// exists(NullPointerType nullptr | -// result = nullptr.getSize() -// ) -// ) -// else if getResultType() instanceof UnknownType then -// result = Construction::getInstructionResultSize(this) -// else ( -// result = getResultType().getSize() -// ) -// } + /** + * Gets the size of the result produced by this instruction, in bytes. If the + * result does not have a known constant size, this predicate does not hold. + * + * If `this.isGLValue()` holds for this instruction, the value of + * `getResultSize()` will always be the size of a pointer. + */ + final int getResultSize() { + if isGLValue() then ( + // a glvalue is always pointer-sized. + result = Language::getPointerSize() + ) + else if getResultType() instanceof Language::UnknownType then + result = Construction::getInstructionResultSize(this) + else ( + result = Language::getTypeSize(getResultType()) + ) + } /** * Gets the opcode that specifies the operation performed by this instruction. @@ -495,17 +475,18 @@ class Instruction extends Construction::TInstruction { } /** - * Gets all direct uses of the result of this instruction. + * Gets all direct uses of the result of this instruction. The result can be + * an `Operand` for which `isDefinitionInexact` holds. */ final Operand getAUse() { - result.getDefinitionInstruction() = this + result.getAnyDef() = this } /** * Gets all of this instruction's operands. */ final Operand getAnOperand() { - result.getUseInstruction() = this + result.getUse() = this } /** @@ -524,13 +505,22 @@ class Instruction extends Construction::TInstruction { } /** - * Returns the operand that holds the memory address to which the instruction stores its + * Gets the operand that holds the memory address to which this instruction stores its * result, if any. For example, in `m3 = Store r1, r2`, the result of `getResultAddressOperand()` * is `r1`. */ final AddressOperand getResultAddressOperand() { getResultMemoryAccess().usesAddressOperand() and - result.getUseInstruction() = this + result.getUse() = this + } + + /** + * Gets the instruction that holds the exact memory address to which this instruction stores its + * result, if any. For example, in `m3 = Store r1, r2`, the result of `getResultAddressOperand()` + * is the instruction that defines `r1`. + */ + final Instruction getResultAddress() { + result = getResultAddressOperand().getDef() } /** @@ -621,7 +611,7 @@ class VariableInstruction extends Instruction { } class FieldInstruction extends Instruction { - Field field; + Language::Field field; FieldInstruction() { field = Construction::getInstructionField(this) @@ -631,13 +621,13 @@ class FieldInstruction extends Instruction { result = field.toString() } - final Field getField() { + final Language::Field getField() { result = field } } class FunctionInstruction extends Instruction { - Callable funcSymbol; + Language::Function funcSymbol; FunctionInstruction() { funcSymbol = Construction::getInstructionFunction(this) @@ -647,7 +637,7 @@ class FunctionInstruction extends Instruction { result = funcSymbol.toString() } - final Callable getFunctionSymbol() { + final Language::Function getFunctionSymbol() { result = funcSymbol } } @@ -685,7 +675,7 @@ class InitializeParameterInstruction extends VariableInstruction { getOpcode() instanceof Opcode::InitializeParameter } - final Parameter getParameter() { + final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } @@ -713,7 +703,23 @@ class FieldAddressInstruction extends FieldInstruction { } final Instruction getObjectAddress() { - result = getObjectAddressOperand().getDefinitionInstruction() + result = getObjectAddressOperand().getDef() + } +} + +/** + * An instruction that produces a well-defined but unknown result and has + * unknown side effects, including side effects that are not conservatively + * modeled in the SSA graph. + * + * This type of instruction appears when there is an `ErrorExpr` in the AST, + * meaning that the extractor could not understand the expression and therefore + * produced a partial AST. Queries that give alerts when some action is _not_ + * taken may want to ignore any function that contains an `ErrorInstruction`. + */ +class ErrorInstruction extends Instruction { + ErrorInstruction() { + getOpcode() instanceof Opcode::Error } } @@ -727,9 +733,9 @@ class UninitializedInstruction extends VariableInstruction { } /** - * Gets the `LocalVariable` that is uninitialized. + * Gets the variable that is uninitialized. */ - final LocalVariable getLocalVariable() { + final Language::Variable getLocalVariable() { result = var.(IRUserVariable).getVariable() } } @@ -762,7 +768,7 @@ class ReturnValueInstruction extends ReturnInstruction { } final Instruction getReturnValue() { - result = getReturnValueOperand().getDefinitionInstruction() + result = getReturnValueOperand().getDef() } } @@ -776,7 +782,7 @@ class CopyInstruction extends Instruction { } final Instruction getSourceValue() { - result = getSourceValueOperand().getDefinitionInstruction() + result = getSourceValueOperand().getDef() } } @@ -800,7 +806,7 @@ class LoadInstruction extends CopyInstruction { } final Instruction getSourceAddress() { - result = getSourceAddressOperand().getDefinitionInstruction() + result = getSourceAddressOperand().getDef() } override final LoadOperand getSourceValueOperand() { @@ -822,7 +828,7 @@ class StoreInstruction extends CopyInstruction { } final Instruction getDestinationAddress() { - result = getDestinationAddressOperand().getDefinitionInstruction() + result = getDestinationAddressOperand().getDef() } override final StoreValueOperand getSourceValueOperand() { @@ -840,7 +846,7 @@ class ConditionalBranchInstruction extends Instruction { } final Instruction getCondition() { - result = getConditionOperand().getDefinitionInstruction() + result = getConditionOperand().getDef() } final Instruction getTrueSuccessor() { @@ -866,28 +872,28 @@ class ConstantInstruction extends ConstantValueInstruction { class IntegerConstantInstruction extends ConstantInstruction { IntegerConstantInstruction() { - getResultType() instanceof IntegralType + getResultType() instanceof Language::IntegralType } } class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { - getResultType() instanceof FloatingPointType + getResultType() instanceof Language::FloatingPointType } } class StringConstantInstruction extends Instruction { - StringLiteral value; + Language::StringLiteral value; StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) } override final string getImmediateString() { - result = value.toString().replaceAll("\n", " ").replaceAll("\r", "").replaceAll("\t", " ") + result = Language::getStringLiteralText(value) } - final StringLiteral getValue() { + final Language::StringLiteral getValue() { result = value } } @@ -906,11 +912,11 @@ class BinaryInstruction extends Instruction { } final Instruction getLeft() { - result = getLeftOperand().getDefinitionInstruction() + result = getLeftOperand().getDef() } final Instruction getRight() { - result = getRightOperand().getDefinitionInstruction() + result = getRightOperand().getDef() } /** @@ -1060,7 +1066,7 @@ class UnaryInstruction extends Instruction { } final Instruction getUnary() { - result = getUnaryOperand().getDefinitionInstruction() + result = getUnaryOperand().getDef() } } @@ -1075,8 +1081,8 @@ class ConvertInstruction extends UnaryInstruction { * related by inheritance. */ class InheritanceConversionInstruction extends UnaryInstruction { - Class baseClass; - Class derivedClass; + Language::Class baseClass; + Language::Class derivedClass; InheritanceConversionInstruction() { Construction::getInstructionInheritance(this, baseClass, derivedClass) @@ -1086,29 +1092,28 @@ class InheritanceConversionInstruction extends UnaryInstruction { result = derivedClass.toString() + " : " + baseClass.toString() } -// TODO: WHAT IS THE EQUIV IN C# -// /** -// * Gets the `ClassDerivation` for the inheritance relationship between -// * the base and derived classes. This predicate does not hold if the -// * conversion is to an indirect virtual base class. -// */ -// final ClassDerivation getDerivation() { -// result.getBaseClass() = baseClass and result.getDerivedClass() = derivedClass -// } + /** + * Gets the `ClassDerivation` for the inheritance relationship between + * the base and derived classes. This predicate does not hold if the + * conversion is to an indirect virtual base class. + */ + final Language::ClassDerivation getDerivation() { + result.getBaseClass() = baseClass and result.getDerivedClass() = derivedClass + } /** * Gets the base class of the conversion. This will be either a direct * base class of the derived class, or a virtual base class of the * derived class. */ - final Class getBaseClass() { + final Language::Class getBaseClass() { result = baseClass } /** * Gets the derived class of the conversion. */ - final Class getDerivedClass() { + final Language::Class getDerivedClass() { result = derivedClass } } @@ -1291,7 +1296,7 @@ class SwitchInstruction extends Instruction { } final Instruction getExpression() { - result = getExpressionOperand().getDefinitionInstruction() + result = getExpressionOperand().getDef() } final Instruction getACaseSuccessor() { @@ -1326,7 +1331,7 @@ class CallInstruction extends Instruction { * function pointer. */ final Instruction getCallTarget() { - result = getCallTargetOperand().getDefinitionInstruction() + result = getCallTargetOperand().getDef() } /** @@ -1339,7 +1344,7 @@ class CallInstruction extends Instruction { /** * Gets the `Function` that the call targets, if this is statically known. */ - final Callable getStaticCallTarget() { + final Language::Function getStaticCallTarget() { result = getCallTarget().(FunctionInstruction).getFunctionSymbol() } @@ -1347,7 +1352,7 @@ class CallInstruction extends Instruction { * Gets all of the arguments of the call, including the `this` pointer, if any. */ final Instruction getAnArgument() { - result = getAnArgumentOperand().getDefinitionInstruction() + result = getAnArgumentOperand().getDef() } /** @@ -1361,7 +1366,7 @@ class CallInstruction extends Instruction { * Gets the `this` pointer argument of the call, if any. */ final Instruction getThisArgument() { - result = getThisArgumentOperand().getDefinitionInstruction() + result = getThisArgumentOperand().getDef() } /** @@ -1376,7 +1381,7 @@ class CallInstruction extends Instruction { * Gets the argument at the specified index. */ final Instruction getPositionalArgument(int index) { - result = getPositionalArgumentOperand(index).getDefinitionInstruction() + result = getPositionalArgumentOperand(index).getDef() } } @@ -1532,7 +1537,7 @@ class ThrowValueInstruction extends ThrowInstruction { * Gets the address of the exception thrown by this instruction. */ final Instruction getExceptionAddress() { - result = getExceptionAddressOperand().getDefinitionInstruction() + result = getExceptionAddressOperand().getDef() } /** @@ -1546,7 +1551,7 @@ class ThrowValueInstruction extends ThrowInstruction { * Gets the exception thrown by this instruction. */ final Instruction getException() { - result = getExceptionOperand().getDefinitionInstruction() + result = getExceptionOperand().getDef() } } @@ -1581,7 +1586,7 @@ class CatchInstruction extends Instruction { * An instruction that catches an exception of a specific type. */ class CatchByTypeInstruction extends CatchInstruction { - Type exceptionType; + Language::Type exceptionType; CatchByTypeInstruction() { getOpcode() instanceof Opcode::CatchByType and @@ -1595,7 +1600,7 @@ class CatchByTypeInstruction extends CatchInstruction { /** * Gets the type of exception to be caught. */ - final Type getExceptionType() { + final Language::Type getExceptionType() { result = exceptionType } } @@ -1676,7 +1681,7 @@ class PhiInstruction extends Instruction { */ pragma[noinline] final Instruction getAnInput() { - result = this.getAnInputOperand().getDefinitionInstruction() + result = this.getAnInputOperand().getDef() } } @@ -1744,7 +1749,7 @@ class ChiInstruction extends Instruction { * memory write. */ final Instruction getTotal() { - result = getTotalOperand().getDefinitionInstruction() + result = getTotalOperand().getDef() } /** @@ -1758,7 +1763,7 @@ class ChiInstruction extends Instruction { * Gets the operand that represents the new value written by the memory write. */ final Instruction getPartial() { - result = getPartialOperand().getDefinitionInstruction() + result = getPartialOperand().getDef() } } @@ -1782,25 +1787,3 @@ class BuiltInInstruction extends Instruction { getOpcode() instanceof BuiltInOpcode } } - -class IndexedElementInstruction extends Instruction { - ArrayAccess arrAccess; - - IndexedElementInstruction() { - arrAccess = Construction::getInstructionArrayAccess(this) - } - - override final string getImmediateString() { - result = arrAccess.toString() - } - - final ArrayAccess getArrayAccess() { - result = arrAccess - } -} - -class IndexedElementAddressInstruction extends VariableInstruction { - IndexedElementAddressInstruction() { - getOpcode() instanceof Opcode::IndexedElementAddress - } -} \ No newline at end of file diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll index cd2fe9ec627..29af8267cb7 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll @@ -1,22 +1,47 @@ private import internal.IRInternal import Instruction import IRBlock -import csharp -import semmle.code.csharp.ir.implementation.MemoryAccessKind -import semmle.code.csharp.ir.internal.Overlap -private import semmle.code.csharp.ir.internal.OperandTag +private import internal.OperandImports as Imports +import Imports::MemoryAccessKind +import Imports::Overlap +private import Imports::OperandTag +cached private newtype TOperand = TRegisterOperand(Instruction useInstr, RegisterOperandTag tag, Instruction defInstr) { - defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) + defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and + not isInCycle(useInstr) } or TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap) { - defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) + defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and + not isInCycle(useInstr) } or TPhiOperand(PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap) { defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap) } +/** Gets a non-phi instruction that defines an operand of `instr`. */ +private Instruction getNonPhiOperandDef(Instruction instr) { + result = Construction::getRegisterOperandDefinition(instr, _) + or + result = Construction::getMemoryOperandDefinition(instr, _, _) +} + +/** + * Holds if `instr` is part of a cycle in the operand graph that doesn't go + * through a phi instruction and therefore should be impossible. + * + * If such cycles are present, either due to a programming error in the IR + * generation or due to a malformed database, it can cause infinite loops in + * analyses that assume a cycle-free graph of non-phi operands. Therefore it's + * better to remove these operands than to leave cycles in the operand graph. + */ +pragma[noopt] +private predicate isInCycle(Instruction instr) { + instr instanceof Instruction and + getNonPhiOperandDef+(instr) = instr +} + /** * A source operand of an `Instruction`. The operand represents a value consumed by the instruction. */ @@ -25,26 +50,62 @@ class Operand extends TOperand { result = "Operand" } - final Location getLocation() { - result = getUseInstruction().getLocation() + final Language::Location getLocation() { + result = getUse().getLocation() } final IRFunction getEnclosingIRFunction() { - result = getUseInstruction().getEnclosingIRFunction() + result = getUse().getEnclosingIRFunction() } - + /** * Gets the `Instruction` that consumes this operand. */ - Instruction getUseInstruction() { + Instruction getUse() { none() } /** + * Gets the `Instruction` whose result is the value of the operand. Unlike + * `getDef`, this also has a result when `isDefinitionInexact` holds, which + * means that the resulting instruction may only _partially_ or _potentially_ + * be the value of this operand. + */ + Instruction getAnyDef() { + none() + } + + /** + * Gets the `Instruction` whose result is the value of the operand. Unlike + * `getAnyDef`, this also has no result when `isDefinitionInexact` holds, + * which means that the resulting instruction must always be exactly the be + * the value of this operand. + */ + final Instruction getDef() { + result = this.getAnyDef() and + getDefinitionOverlap() instanceof MustExactlyOverlap + } + + /** + * DEPRECATED: renamed to `getUse`. + * + * Gets the `Instruction` that consumes this operand. + */ + deprecated + final Instruction getUseInstruction() { + result = getUse() + } + + /** + * DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this + * predicate is `getAnyDef`, but most uses of this predicate should probably + * be replaced with `getDef`. + * * Gets the `Instruction` whose result is the value of the operand. */ - Instruction getDefinitionInstruction() { - none() + deprecated + final Instruction getDefinitionInstruction() { + result = getAnyDef() } /** @@ -76,7 +137,7 @@ class Operand extends TOperand { * For example: `this:r3_5` */ final string getDumpString() { - result = getDumpLabel() + getInexactSpecifier() + getDefinitionInstruction().getResultId() + result = getDumpLabel() + getInexactSpecifier() + getAnyDef().getResultId() } /** @@ -105,8 +166,8 @@ class Operand extends TOperand { * the definition type, such as in the case of a partial read or a read from a pointer that * has been cast to a different type. */ - Type getType() { - result = getDefinitionInstruction().getResultType() + Language::Type getType() { + result = getAnyDef().getResultType() } /** @@ -116,8 +177,8 @@ class Operand extends TOperand { * not hold, the value of the operand represents a value whose type is * given by `getResultType()`. */ - predicate isLValue() { - getDefinitionInstruction().isLValue() + predicate isGLValue() { + getAnyDef().isGLValue() } /** @@ -125,7 +186,7 @@ class Operand extends TOperand { * a known constant size, this predicate does not hold. */ int getSize() { - result = 8 //getType().getSize() TODO: C# memory layout + result = Language::getTypeSize(getType()) } } @@ -138,7 +199,7 @@ class MemoryOperand extends Operand { this = TPhiOperand(_, _, _, _) } - override predicate isLValue() { + override predicate isGLValue() { // A `MemoryOperand` can never be a glvalue none() } @@ -157,7 +218,7 @@ class MemoryOperand extends Operand { */ final AddressOperand getAddressOperand() { getMemoryAccess().usesAddressOperand() and - result.getUseInstruction() = getUseInstruction() + result.getUse() = getUse() } } @@ -174,11 +235,11 @@ class NonPhiOperand extends Operand { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, _) } - override final Instruction getUseInstruction() { + override final Instruction getUse() { result = useInstr } - override final Instruction getDefinitionInstruction() { + override final Instruction getAnyDef() { result = defInstr } @@ -223,7 +284,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe class TypedOperand extends NonPhiMemoryOperand { override TypedOperandTag tag; - override final Type getType() { + override final Language::Type getType() { result = Construction::getInstructionOperandType(useInstr, tag) } } @@ -386,11 +447,10 @@ class SideEffectOperand extends TypedOperand { override SideEffectOperandTag tag; override final int getSize() { - if getType() instanceof UnknownType then + if getType() instanceof Language::UnknownType then result = Construction::getInstructionOperandSize(useInstr, tag) else - // TODO: Memory layout in C# - result = 8 //getType().getSize() + result = Language::getTypeSize(getType()) } override MemoryAccessKind getMemoryAccess() { @@ -437,11 +497,11 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand { result = "Phi" } - override final PhiInstruction getUseInstruction() { + override final PhiInstruction getUse() { result = useInstr } - override final Instruction getDefinitionInstruction() { + override final Instruction getAnyDef() { result = defInstr } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/PrintIR.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/PrintIR.qll index c03d946979c..4bad5e3fd3e 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/PrintIR.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/PrintIR.qll @@ -1,7 +1,7 @@ +private import internal.IRInternal private import IR -import csharp -import semmle.code.csharp.ir.IRConfiguration -//private import semmle.code.csharp.Print +private import internal.PrintIRImports as Imports +import Imports::IRConfiguration private newtype TPrintIRConfiguration = MkPrintIRConfiguration() @@ -17,12 +17,12 @@ class PrintIRConfiguration extends TPrintIRConfiguration { * Holds if the IR for `func` should be printed. By default, holds for all * functions. */ - predicate shouldPrintFunction(Callable func) { + predicate shouldPrintFunction(Language::Function func) { any() } } -private predicate shouldPrintFunction(Callable func) { +private predicate shouldPrintFunction(Language::Function func) { exists(PrintIRConfiguration config | config.shouldPrintFunction(func) ) @@ -32,7 +32,7 @@ private predicate shouldPrintFunction(Callable func) { * Override of `IRConfiguration` to only create IR for the functions that are to be dumped. */ private class FilteredIRConfiguration extends IRConfiguration { - override predicate shouldCreateIRForFunction(Callable func) { + override predicate shouldCreateIRForFunction(Language::Function func) { shouldPrintFunction(func) } } @@ -69,7 +69,7 @@ abstract class PrintableIRNode extends TPrintableIRNode { /** * Gets the location to be emitted for the node. */ - abstract Location getLocation(); + abstract Language::Location getLocation(); /** * Gets the label to be emitted for the node. @@ -126,17 +126,16 @@ class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction { result = irFunc.toString() } - override Location getLocation() { + override Language::Location getLocation() { result = irFunc.getLocation() } override string getLabel() { - // TODO: C++ USED THE PRINT MODULE, NOT SURE TOsTRING DOES THE JOB - result = irFunc.getFunction().toString() + result = Language::getIdentityString(irFunc.getFunction()) } override int getOrder() { - this = rank[result + 1](PrintableIRFunction orderedFunc, Location location | + this = rank[result + 1](PrintableIRFunction orderedFunc, Language::Location location | location = orderedFunc.getIRFunction().getLocation() | orderedFunc order by location.getFile().getAbsolutePath(), location.getStartLine(), location.getStartColumn(), orderedFunc.getLabel() @@ -166,7 +165,7 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock { result = getLabel() } - override Location getLocation() { + override Language::Location getLocation() { result = block.getLocation() } @@ -214,7 +213,7 @@ class PrintableInstruction extends PrintableIRNode, TPrintableInstruction { result = instr.toString() } - override Location getLocation() { + override Language::Location getLocation() { result = instr.getLocation() } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRBlockImports.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRBlockImports.qll new file mode 100644 index 00000000000..9aa0d93de1f --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRBlockImports.qll @@ -0,0 +1 @@ +import semmle.code.csharp.ir.implementation.EdgeKind as EdgeKind diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll index 33da8058460..72145fbf8d9 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll @@ -1,6 +1,6 @@ import csharp import semmle.code.csharp.ir.implementation.raw.IR -private import semmle.code.csharp.ir.internal.OperandTag +private import semmle.code.csharp.ir.implementation.internal.OperandTag private import semmle.code.csharp.ir.internal.TempVariableTag private import InstructionTag private import TranslatedCondition @@ -30,6 +30,10 @@ cached private module Cached { element.hasInstruction(_, tag, _, _) } + cached predicate hasUserVariable(Callable callable, Variable var, Type type) { + getTranslatedFunction(callable).hasUserVariable(var, type) + } + cached predicate hasTempVariable(Callable callable, Locatable ast, TempVariableTag tag, Type type) { exists(TranslatedElement element | diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRImports.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRImports.qll new file mode 100644 index 00000000000..b5abc1049f3 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRImports.qll @@ -0,0 +1,2 @@ +import semmle.code.csharp.ir.implementation.EdgeKind as EdgeKind +import semmle.code.csharp.ir.implementation.MemoryAccessKind as MemoryAccessKind diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRInternal.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRInternal.qll index abfb61b38e3..3c0c2d9cc42 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRInternal.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRInternal.qll @@ -1 +1,2 @@ +import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language import IRConstruction as Construction diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRVariableImports.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRVariableImports.qll new file mode 100644 index 00000000000..20c299416ef --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRVariableImports.qll @@ -0,0 +1,4 @@ +import semmle.code.csharp.ir.implementation.TempVariableTag as TempVariableTag +import semmle.code.csharp.ir.internal.IRUtilities as IRUtilities +import semmle.code.csharp.ir.internal.TempVariableTag as TTempVariableTag +import semmle.code.csharp.ir.implementation.internal.TIRVariable as TIRVariable diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/InstructionImports.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/InstructionImports.qll new file mode 100644 index 00000000000..da9b8e6e877 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/InstructionImports.qll @@ -0,0 +1,4 @@ +import semmle.code.csharp.ir.implementation.EdgeKind as EdgeKind +import semmle.code.csharp.ir.implementation.MemoryAccessKind as MemoryAccessKind +import semmle.code.csharp.ir.implementation.Opcode as Opcode +import semmle.code.csharp.ir.implementation.internal.OperandTag as OperandTag diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/OperandImports.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/OperandImports.qll new file mode 100644 index 00000000000..13667df7276 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/OperandImports.qll @@ -0,0 +1,3 @@ +import semmle.code.csharp.ir.implementation.MemoryAccessKind as MemoryAccessKind +import semmle.code.csharp.ir.internal.Overlap as Overlap +import semmle.code.csharp.ir.implementation.internal.OperandTag as OperandTag diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/PrintIRImports.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/PrintIRImports.qll new file mode 100644 index 00000000000..a74b4bffbc4 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/PrintIRImports.qll @@ -0,0 +1 @@ +import semmle.code.csharp.ir.IRConfiguration as IRConfiguration diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedCall.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedCall.qll index c57416c88f5..a19df805e1c 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedCall.qll @@ -1,6 +1,6 @@ import csharp private import semmle.code.csharp.ir.implementation.Opcode -private import semmle.code.csharp.ir.internal.OperandTag +private import semmle.code.csharp.ir.implementation.internal.OperandTag private import InstructionTag private import TranslatedElement private import TranslatedExpr diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedCondition.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedCondition.qll index 9364c34c930..2f7581eedcc 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedCondition.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedCondition.qll @@ -1,6 +1,6 @@ import csharp private import semmle.code.csharp.ir.implementation.Opcode -private import semmle.code.csharp.ir.internal.OperandTag +private import semmle.code.csharp.ir.implementation.internal.OperandTag private import InstructionTag private import TranslatedElement private import TranslatedExpr diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll index 14e6f9e10ce..b2f3aa84518 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll @@ -1,7 +1,7 @@ import csharp private import semmle.code.csharp.ir.implementation.Opcode private import semmle.code.csharp.ir.internal.IRUtilities -private import semmle.code.csharp.ir.internal.OperandTag +private import semmle.code.csharp.ir.implementation.internal.OperandTag private import InstructionTag private import TranslatedElement private import TranslatedExpr diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedElement.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedElement.qll index f7583273196..f5b75a8d161 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedElement.qll @@ -1,9 +1,8 @@ import csharp -import csharp import semmle.code.csharp.ir.implementation.raw.IR private import semmle.code.csharp.ir.IRConfiguration private import semmle.code.csharp.ir.implementation.Opcode -private import semmle.code.csharp.ir.internal.OperandTag +private import semmle.code.csharp.ir.implementation.internal.OperandTag private import semmle.code.csharp.ir.internal.TempVariableTag private import InstructionTag private import TranslatedCondition diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedExpr.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedExpr.qll index 55fbffcb90c..f8022d121d5 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -1,6 +1,6 @@ import csharp private import semmle.code.csharp.ir.implementation.Opcode -private import semmle.code.csharp.ir.internal.OperandTag +private import semmle.code.csharp.ir.implementation.internal.OperandTag private import semmle.code.csharp.ir.internal.TempVariableTag private import InstructionTag private import TranslatedCondition diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedFunction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedFunction.qll index 5c95c379d50..72a8c054590 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedFunction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedFunction.qll @@ -2,7 +2,7 @@ import csharp import semmle.code.csharp.ir.implementation.raw.IR private import semmle.code.csharp.ir.implementation.Opcode private import semmle.code.csharp.ir.internal.IRUtilities -private import semmle.code.csharp.ir.internal.OperandTag +private import semmle.code.csharp.ir.implementation.internal.OperandTag private import semmle.code.csharp.ir.internal.TempVariableTag private import InstructionTag private import TranslatedElement @@ -315,6 +315,25 @@ class TranslatedFunction extends TranslatedElement, result = callable.getDeclaringType() } + /** + * Holds if this function defines or accesses variable `var` with type `type`. This includes all + * parameters and local variables, plus any static fields that are directly accessed by the + * function. + */ + final predicate hasUserVariable(Variable var, Type type) { + ( + ( + var.(Member).isStatic() and + exists(VariableAccess access | + access.getTarget() = var and + access.getEnclosingCallable() = callable + ) + ) or + var.(LocalScopeVariable).getCallable() = callable + ) and + type = getVariableType(var) + } + private final Type getReturnType() { result = callable.getReturnType() } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedInitialization.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedInitialization.qll index 1b8c9a574b1..f61f9ae41a7 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedInitialization.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedInitialization.qll @@ -1,6 +1,6 @@ import csharp private import semmle.code.csharp.ir.implementation.Opcode -private import semmle.code.csharp.ir.internal.OperandTag +private import semmle.code.csharp.ir.implementation.internal.OperandTag private import InstructionTag private import TranslatedElement private import TranslatedExpr diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedStmt.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedStmt.qll index 7fb52b3a087..f8afb4f5a57 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedStmt.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedStmt.qll @@ -1,6 +1,6 @@ import csharp private import semmle.code.csharp.ir.internal.TempVariableTag -private import semmle.code.csharp.ir.internal.OperandTag +private import semmle.code.csharp.ir.implementation.internal.OperandTag private import InstructionTag private import TranslatedCondition private import TranslatedDeclarationEntry diff --git a/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll b/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll new file mode 100644 index 00000000000..f319a9e07b8 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll @@ -0,0 +1,114 @@ +private import csharp as Cpp + +class Function = Cpp::Callable; +class Location = Cpp::Location; +class AST = Cpp::Element; + +class Type = Cpp::Type; +//REVIEW: This might not exist in the database. +class UnknownType = Cpp::UnknownType; +class VoidType = Cpp::VoidType; +class IntegralType = Cpp::IntegralType; +class FloatingPointType = Cpp::FloatingPointType; + +private newtype TClassDerivation = + // Note that this is the `Class` type exported from this module, not CSharp::Class. + MkClassDerivation(Class base, Class derived) { + derived.getABaseType() = base + } + +class ClassDerivation extends MkClassDerivation { + Class baseClass; + Class derivedClass; + + ClassDerivation() { + this = MkClassDerivation(baseClass, derivedClass) + } + + string toString() { + result = "ClassDerivation" + } + + final Class getBaseClass() { + result = baseClass + } + + final Class getDerivedClass() { + result = derivedClass + } + + final int getByteOffset() { + // Inheritance never requires adjusting the `this` pointer in C#. + result = 0 + } +} + +class StringLiteral = Cpp::StringLiteral; + +class Variable = Cpp::Variable; +class AutomaticVariable = Cpp::LocalScopeVariable; +class StaticVariable = Cpp::Variable; +class Parameter = Cpp::Parameter; +class Field = Cpp::Field; + +// TODO: Remove necessity for these. +class Expr = Cpp::Expr; +class Class = Cpp::RefType; // Used for inheritance conversions + +string getIdentityString(Function func) { + // REVIEW: Is this enough to make it unique? +// result = func.getQualifiedName() + result = func.getName() +} + +predicate hasCaseEdge(string minValue, string maxValue) { + // TODO: Need to handle `switch` statements that switch on an integer. + none() +} + +predicate hasPositionalArgIndex(int argIndex) { + exists(Cpp::MethodCall call | + exists(call.getArgument(argIndex)) + ) +} + +predicate hasAsmOperandIndex(int operandIndex) { + none() +} + +int getTypeSize(Type type) { + // REVIEW: Is this complete? + result = type.(Cpp::SimpleType).getSize() or + result = getTypeSize(type.(Cpp::Enum).getUnderlyingType()) or + // TODO: Generate a reasonable size + type instanceof Cpp::Struct and result = 16 or + type instanceof Cpp::RefType and result = getPointerSize() or + type instanceof Cpp::PointerType and result = getPointerSize() or + result = getTypeSize(type.(Cpp::TupleType).getUnderlyingType()) or + // TODO: Add room for extra field + result = getTypeSize(type.(Cpp::NullableType).getUnderlyingType()) or + type instanceof Cpp::VoidType and result = 0 +} + +int getPointerSize() { + // TODO: Deal with sizes in general + result = 8 +} + +predicate isVariableAutomatic(Variable var) { + var instanceof Cpp::LocalScopeVariable +} + +string getStringLiteralText(StringLiteral s) { + // REVIEW: Is this the right escaping? + result = s.toString() +} + +predicate hasPotentialLoop(Function f) { + exists(Cpp::LoopStmt l | l.getEnclosingCallable() = f) or + exists(Cpp::GotoStmt s | s.getEnclosingCallable() = f) +} + +predicate hasGoto(Function f) { + exists(Cpp::GotoStmt s | s.getEnclosingCallable() = f) +} diff --git a/csharp/ql/src/semmle/code/csharp/ir/internal/IntegerConstant.qll b/csharp/ql/src/semmle/code/csharp/ir/internal/IntegerConstant.qll index 457ac88e887..d6e74a28414 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/internal/IntegerConstant.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/internal/IntegerConstant.qll @@ -1,5 +1,3 @@ -import csharp - class IntValue = int; /** diff --git a/csharp/ql/src/semmle/code/csharp/ir/internal/Overlap.qll b/csharp/ql/src/semmle/code/csharp/ir/internal/Overlap.qll index eaec56a69e2..1680129bf22 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/internal/Overlap.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/internal/Overlap.qll @@ -1,5 +1,3 @@ -import csharp - private newtype TOverlap = TMayPartiallyOverlap() or TMustTotallyOverlap() or diff --git a/csharp/ql/test/library-tests/ir/ir/raw_ir.expected b/csharp/ql/test/library-tests/ir/ir/raw_ir.expected index 265e53bcf71..25a99d95a91 100644 --- a/csharp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/csharp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -1,135 +1,135 @@ array_acc.cs: # 4| f # 4| Block 0 -# 4| v0_0(Void) = EnterFunction : -# 4| mu0_1(Object) = AliasedDefinition : -# 4| mu0_2(Object) = UnmodeledDefinition : -# 4| r0_3(lval) = InitializeThis : -# 5| r0_4(lval) = VariableAddress[arr] : -# 5| mu0_5(Int32[]) = Uninitialized[arr] : &:r0_4 -# 5| r0_6(Int32) = Constant[0] : -# 5| r0_7(lval) = IndexedElementAddress : r0_4, r0_6 -# 5| r0_8(Int32) = Constant[101] : -# 5| mu0_9(Int32) = Store : &:r0_7, r0_8 -# 5| r0_10(Int32) = Constant[1] : -# 5| r0_11(lval) = IndexedElementAddress : r0_4, r0_10 -# 5| r0_12(Int32) = Constant[102] : -# 5| mu0_13(Int32) = Store : &:r0_11, r0_12 -# 6| r0_14(Int32) = Constant[5] : -# 6| r0_15(lval) = VariableAddress[arr] : -# 6| r0_16(Int32) = Constant[1] : -# 6| r0_17(lval) = IndexedElementAddress : r0_15, r0_16 -# 6| mu0_18(Int32) = Store : &:r0_17, r0_14 -# 4| v0_19(Void) = ReturnVoid : -# 4| v0_20(Void) = UnmodeledUse : mu* -# 4| v0_21(Void) = ExitFunction : +# 4| v0_0(Void) = EnterFunction : +# 4| mu0_1(Object) = AliasedDefinition : +# 4| mu0_2(Object) = UnmodeledDefinition : +# 4| r0_3(glval) = InitializeThis : +# 5| r0_4(glval) = VariableAddress[arr] : +# 5| mu0_5(Int32[]) = Uninitialized[arr] : &:r0_4 +# 5| r0_6(Int32) = Constant[0] : +# 5| r0_7(glval) = IndexedElementAddress : r0_4, r0_6 +# 5| r0_8(Int32) = Constant[101] : +# 5| mu0_9(Int32) = Store : &:r0_7, r0_8 +# 5| r0_10(Int32) = Constant[1] : +# 5| r0_11(glval) = IndexedElementAddress : r0_4, r0_10 +# 5| r0_12(Int32) = Constant[102] : +# 5| mu0_13(Int32) = Store : &:r0_11, r0_12 +# 6| r0_14(Int32) = Constant[5] : +# 6| r0_15(glval) = VariableAddress[arr] : +# 6| r0_16(Int32) = Constant[1] : +# 6| r0_17(glval) = IndexedElementAddress : r0_15, r0_16 +# 6| mu0_18(Int32) = Store : &:r0_17, r0_14 +# 4| v0_19(Void) = ReturnVoid : +# 4| v0_20(Void) = UnmodeledUse : mu* +# 4| v0_21(Void) = ExitFunction : func_with_param_call.cs: # 4| f # 4| Block 0 -# 4| v0_0(Void) = EnterFunction : -# 4| mu0_1(Object) = AliasedDefinition : -# 4| mu0_2(Object) = UnmodeledDefinition : -# 4| r0_3(lval) = InitializeThis : -# 4| r0_4(lval) = VariableAddress[x] : -# 4| mu0_5(Int32) = InitializeParameter[x] : &:r0_4 -# 4| r0_6(lval) = VariableAddress[y] : -# 4| mu0_7(Int32) = InitializeParameter[y] : &:r0_6 -# 5| r0_8(lval) = VariableAddress[#return] : -# 5| r0_9(lval) = VariableAddress[x] : -# 5| r0_10(Int32) = Load : &:r0_9, ~mu0_2 -# 5| r0_11(lval) = VariableAddress[y] : -# 5| r0_12(Int32) = Load : &:r0_11, ~mu0_2 -# 5| r0_13(Int32) = Add : r0_10, r0_12 -# 5| mu0_14(Int32) = Store : &:r0_8, r0_13 -# 4| r0_15(lval) = VariableAddress[#return] : -# 4| v0_16(Void) = ReturnValue : &:r0_15, ~mu0_2 -# 4| v0_17(Void) = UnmodeledUse : mu* -# 4| v0_18(Void) = ExitFunction : +# 4| v0_0(Void) = EnterFunction : +# 4| mu0_1(Object) = AliasedDefinition : +# 4| mu0_2(Object) = UnmodeledDefinition : +# 4| r0_3(glval) = InitializeThis : +# 4| r0_4(glval) = VariableAddress[x] : +# 4| mu0_5(Int32) = InitializeParameter[x] : &:r0_4 +# 4| r0_6(glval) = VariableAddress[y] : +# 4| mu0_7(Int32) = InitializeParameter[y] : &:r0_6 +# 5| r0_8(glval) = VariableAddress[#return] : +# 5| r0_9(glval) = VariableAddress[x] : +# 5| r0_10(Int32) = Load : &:r0_9, ~mu0_2 +# 5| r0_11(glval) = VariableAddress[y] : +# 5| r0_12(Int32) = Load : &:r0_11, ~mu0_2 +# 5| r0_13(Int32) = Add : r0_10, r0_12 +# 5| mu0_14(Int32) = Store : &:r0_8, r0_13 +# 4| r0_15(glval) = VariableAddress[#return] : +# 4| v0_16(Void) = ReturnValue : &:r0_15, ~mu0_2 +# 4| v0_17(Void) = UnmodeledUse : mu* +# 4| v0_18(Void) = ExitFunction : # 8| g # 8| Block 0 -# 8| v0_0(Void) = EnterFunction : -# 8| mu0_1(Object) = AliasedDefinition : -# 8| mu0_2(Object) = UnmodeledDefinition : -# 8| r0_3(lval) = InitializeThis : -# 9| r0_4(lval) = VariableAddress[#return] : -# 9| r0_5(lval) = FunctionAddress[f] : -# 9| r0_6(Int32) = Constant[2] : -# 9| r0_7(Int32) = Constant[3] : -# 9| r0_8(Int32) = Call : func:r0_5, 0:r0_6, 1:r0_7 -# 9| v0_9(Void) = ^CallSideEffect : ~mu0_2 -# 9| mu0_10(Int32) = Store : &:r0_4, r0_8 -# 8| r0_11(lval) = VariableAddress[#return] : -# 8| v0_12(Void) = ReturnValue : &:r0_11, ~mu0_2 -# 8| v0_13(Void) = UnmodeledUse : mu* -# 8| v0_14(Void) = ExitFunction : +# 8| v0_0(Void) = EnterFunction : +# 8| mu0_1(Object) = AliasedDefinition : +# 8| mu0_2(Object) = UnmodeledDefinition : +# 8| r0_3(glval) = InitializeThis : +# 9| r0_4(glval) = VariableAddress[#return] : +# 9| r0_5(glval) = FunctionAddress[f] : +# 9| r0_6(Int32) = Constant[2] : +# 9| r0_7(Int32) = Constant[3] : +# 9| r0_8(Int32) = Call : func:r0_5, 0:r0_6, 1:r0_7 +# 9| v0_9(Void) = ^CallSideEffect : ~mu0_2 +# 9| mu0_10(Int32) = Store : &:r0_4, r0_8 +# 8| r0_11(glval) = VariableAddress[#return] : +# 8| v0_12(Void) = ReturnValue : &:r0_11, ~mu0_2 +# 8| v0_13(Void) = UnmodeledUse : mu* +# 8| v0_14(Void) = ExitFunction : simple_call.cs: # 4| f # 4| Block 0 -# 4| v0_0(Void) = EnterFunction : -# 4| mu0_1(Object) = AliasedDefinition : -# 4| mu0_2(Object) = UnmodeledDefinition : -# 4| r0_3(lval) = InitializeThis : -# 5| r0_4(lval) = VariableAddress[#return] : -# 5| r0_5(Int32) = Constant[0] : -# 5| mu0_6(Int32) = Store : &:r0_4, r0_5 -# 4| r0_7(lval) = VariableAddress[#return] : -# 4| v0_8(Void) = ReturnValue : &:r0_7, ~mu0_2 -# 4| v0_9(Void) = UnmodeledUse : mu* -# 4| v0_10(Void) = ExitFunction : +# 4| v0_0(Void) = EnterFunction : +# 4| mu0_1(Object) = AliasedDefinition : +# 4| mu0_2(Object) = UnmodeledDefinition : +# 4| r0_3(glval) = InitializeThis : +# 5| r0_4(glval) = VariableAddress[#return] : +# 5| r0_5(Int32) = Constant[0] : +# 5| mu0_6(Int32) = Store : &:r0_4, r0_5 +# 4| r0_7(glval) = VariableAddress[#return] : +# 4| v0_8(Void) = ReturnValue : &:r0_7, ~mu0_2 +# 4| v0_9(Void) = UnmodeledUse : mu* +# 4| v0_10(Void) = ExitFunction : # 8| g # 8| Block 0 -# 8| v0_0(Void) = EnterFunction : -# 8| mu0_1(Object) = AliasedDefinition : -# 8| mu0_2(Object) = UnmodeledDefinition : -# 8| r0_3(lval) = InitializeThis : -# 9| r0_4(lval) = VariableAddress[#return] : -# 9| r0_5(lval) = FunctionAddress[f] : -# 9| r0_6(Int32) = Call : func:r0_5 -# 9| v0_7(Void) = ^CallSideEffect : ~mu0_2 -# 9| mu0_8(Int32) = Store : &:r0_4, r0_6 -# 8| r0_9(lval) = VariableAddress[#return] : -# 8| v0_10(Void) = ReturnValue : &:r0_9, ~mu0_2 -# 8| v0_11(Void) = UnmodeledUse : mu* -# 8| v0_12(Void) = ExitFunction : +# 8| v0_0(Void) = EnterFunction : +# 8| mu0_1(Object) = AliasedDefinition : +# 8| mu0_2(Object) = UnmodeledDefinition : +# 8| r0_3(glval) = InitializeThis : +# 9| r0_4(glval) = VariableAddress[#return] : +# 9| r0_5(glval) = FunctionAddress[f] : +# 9| r0_6(Int32) = Call : func:r0_5 +# 9| v0_7(Void) = ^CallSideEffect : ~mu0_2 +# 9| mu0_8(Int32) = Store : &:r0_4, r0_6 +# 8| r0_9(glval) = VariableAddress[#return] : +# 8| v0_10(Void) = ReturnValue : &:r0_9, ~mu0_2 +# 8| v0_11(Void) = UnmodeledUse : mu* +# 8| v0_12(Void) = ExitFunction : simple_function.cs: # 4| f # 4| Block 0 -# 4| v0_0(Void) = EnterFunction : -# 4| mu0_1(Object) = AliasedDefinition : -# 4| mu0_2(Object) = UnmodeledDefinition : -# 4| r0_3(lval) = InitializeThis : -# 5| r0_4(lval) = VariableAddress[#return] : -# 5| r0_5(Int32) = Constant[0] : -# 5| mu0_6(Int32) = Store : &:r0_4, r0_5 -# 4| r0_7(lval) = VariableAddress[#return] : -# 4| v0_8(Void) = ReturnValue : &:r0_7, ~mu0_2 -# 4| v0_9(Void) = UnmodeledUse : mu* -# 4| v0_10(Void) = ExitFunction : +# 4| v0_0(Void) = EnterFunction : +# 4| mu0_1(Object) = AliasedDefinition : +# 4| mu0_2(Object) = UnmodeledDefinition : +# 4| r0_3(glval) = InitializeThis : +# 5| r0_4(glval) = VariableAddress[#return] : +# 5| r0_5(Int32) = Constant[0] : +# 5| mu0_6(Int32) = Store : &:r0_4, r0_5 +# 4| r0_7(glval) = VariableAddress[#return] : +# 4| v0_8(Void) = ReturnValue : &:r0_7, ~mu0_2 +# 4| v0_9(Void) = UnmodeledUse : mu* +# 4| v0_10(Void) = ExitFunction : variables.cs: # 4| f # 4| Block 0 -# 4| v0_0(Void) = EnterFunction : -# 4| mu0_1(Object) = AliasedDefinition : -# 4| mu0_2(Object) = UnmodeledDefinition : -# 4| r0_3(lval) = InitializeThis : -# 5| r0_4(lval) = VariableAddress[x] : -# 5| mu0_5(Int32) = Uninitialized[x] : &:r0_4 -# 5| r0_6(lval) = VariableAddress[y] : -# 5| r0_7(Int32) = Constant[5] : -# 5| mu0_8(Int32) = Store : &:r0_6, r0_7 -# 6| r0_9(Int32) = Constant[4] : -# 6| r0_10(lval) = VariableAddress[x] : -# 6| mu0_11(Int32) = Store : &:r0_10, r0_9 -# 7| r0_12(lval) = VariableAddress[y] : -# 7| r0_13(Int32) = Load : &:r0_12, ~mu0_2 -# 7| r0_14(lval) = VariableAddress[x] : -# 7| mu0_15(Int32) = Store : &:r0_14, r0_13 -# 4| v0_16(Void) = ReturnVoid : -# 4| v0_17(Void) = UnmodeledUse : mu* -# 4| v0_18(Void) = ExitFunction : +# 4| v0_0(Void) = EnterFunction : +# 4| mu0_1(Object) = AliasedDefinition : +# 4| mu0_2(Object) = UnmodeledDefinition : +# 4| r0_3(glval) = InitializeThis : +# 5| r0_4(glval) = VariableAddress[x] : +# 5| mu0_5(Int32) = Uninitialized[x] : &:r0_4 +# 5| r0_6(glval) = VariableAddress[y] : +# 5| r0_7(Int32) = Constant[5] : +# 5| mu0_8(Int32) = Store : &:r0_6, r0_7 +# 6| r0_9(Int32) = Constant[4] : +# 6| r0_10(glval) = VariableAddress[x] : +# 6| mu0_11(Int32) = Store : &:r0_10, r0_9 +# 7| r0_12(glval) = VariableAddress[y] : +# 7| r0_13(Int32) = Load : &:r0_12, ~mu0_2 +# 7| r0_14(glval) = VariableAddress[x] : +# 7| mu0_15(Int32) = Store : &:r0_14, r0_13 +# 4| v0_16(Void) = ReturnVoid : +# 4| v0_17(Void) = UnmodeledUse : mu* +# 4| v0_18(Void) = ExitFunction :