mirror of
https://github.com/github/codeql.git
synced 2025-12-22 11:46:32 +01:00
Merge pull request #2421 from dbartol/dbartol/IndirectAlias
C++/C#: Cleanup in preparation for indirect alias analysis
This commit is contained in:
@@ -13,14 +13,20 @@ IRUserVariable getIRUserVariable(Language::Function func, Language::Variable var
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a variable referenced by the IR for a function. The variable may
|
||||
* be a user-declared variable (`IRUserVariable`) or a temporary variable
|
||||
* generated by the AST-to-IR translation (`IRTempVariable`).
|
||||
* A variable referenced by the IR for a function. The variable may be a user-declared variable
|
||||
* (`IRUserVariable`) or a temporary variable generated by the AST-to-IR translation
|
||||
* (`IRTempVariable`).
|
||||
*/
|
||||
abstract class IRVariable extends TIRVariable {
|
||||
class IRVariable extends TIRVariable {
|
||||
Language::Function func;
|
||||
|
||||
abstract string toString();
|
||||
IRVariable() {
|
||||
this = TIRUserVariable(_, _, func) or
|
||||
this = TIRTempVariable(func, _, _, _) or
|
||||
this = TIRStringLiteral(func, _, _, _)
|
||||
}
|
||||
|
||||
string toString() { none() }
|
||||
|
||||
/**
|
||||
* Holds if this variable's value cannot be changed within a function. Currently used for string
|
||||
@@ -41,19 +47,19 @@ abstract class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
abstract Language::LanguageType getLanguageType();
|
||||
Language::LanguageType getLanguageType() { none() }
|
||||
|
||||
/**
|
||||
* Gets the AST node that declared this variable, or that introduced this
|
||||
* variable as part of the AST-to-IR translation.
|
||||
*/
|
||||
abstract Language::AST getAST();
|
||||
Language::AST getAST() { none() }
|
||||
|
||||
/**
|
||||
* Gets an identifier string for the variable. This identifier is unique
|
||||
* within the function.
|
||||
*/
|
||||
abstract string getUniqueId();
|
||||
string getUniqueId() { none() }
|
||||
|
||||
/**
|
||||
* Gets the source location of this variable.
|
||||
@@ -72,7 +78,7 @@ abstract class IRVariable extends TIRVariable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a user-declared variable referenced by the IR for a function.
|
||||
* A user-declared variable referenced by the IR for a function.
|
||||
*/
|
||||
class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
Language::Variable var;
|
||||
@@ -97,20 +103,34 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a variable (user-declared or temporary) that is allocated on the
|
||||
* stack. This includes all parameters, non-static local variables, and
|
||||
* temporary variables.
|
||||
* A variable (user-declared or temporary) that is allocated on the stack. This includes all
|
||||
* parameters, non-static local variables, and temporary variables.
|
||||
*/
|
||||
abstract class IRAutomaticVariable extends IRVariable { }
|
||||
class IRAutomaticVariable extends IRVariable {
|
||||
IRAutomaticVariable() {
|
||||
exists(Language::Variable var |
|
||||
this = TIRUserVariable(var, _, func) and
|
||||
Language::isVariableAutomatic(var)
|
||||
)
|
||||
or
|
||||
this = TIRTempVariable(func, _, _, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-declared variable that is allocated on the stack. This includes all parameters and
|
||||
* non-static local variables.
|
||||
*/
|
||||
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
|
||||
override Language::AutomaticVariable var;
|
||||
|
||||
IRAutomaticUserVariable() { Language::isVariableAutomatic(var) }
|
||||
|
||||
final override Language::AutomaticVariable getVariable() { result = var }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-declared variable that is not allocated on the stack. This includes all global variables,
|
||||
* namespace-scope variables, static fields, and static local variables.
|
||||
*/
|
||||
class IRStaticUserVariable extends IRUserVariable {
|
||||
override Language::StaticVariable var;
|
||||
|
||||
@@ -119,10 +139,19 @@ class IRStaticUserVariable extends IRUserVariable {
|
||||
final override Language::StaticVariable getVariable() { result = var }
|
||||
}
|
||||
|
||||
abstract class IRGeneratedVariable extends IRVariable {
|
||||
/**
|
||||
* A variable that is not user-declared. This includes temporary variables generated as part of IR
|
||||
* construction, as well as string literals.
|
||||
*/
|
||||
class IRGeneratedVariable extends IRVariable {
|
||||
Language::AST ast;
|
||||
Language::LanguageType type;
|
||||
|
||||
IRGeneratedVariable() {
|
||||
this = TIRTempVariable(func, ast, _, type) or
|
||||
this = TIRStringLiteral(func, ast, type, _)
|
||||
}
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
final override Language::AST getAST() { result = ast }
|
||||
@@ -144,6 +173,11 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
|
||||
result.getTag() = tag
|
||||
}
|
||||
|
||||
/**
|
||||
* A temporary variable introduced by IR construction. The most common examples are the variable
|
||||
* generated to hold the return value of afunction, or the variable generated to hold the result of
|
||||
* a condition operator (`a ? b : c`).
|
||||
*/
|
||||
class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {
|
||||
TempVariableTag tag;
|
||||
|
||||
@@ -158,18 +192,28 @@ class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVa
|
||||
override string getBaseString() { result = "#temp" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A temporary variable generated to hold the return value of a function.
|
||||
*/
|
||||
class IRReturnVariable extends IRTempVariable {
|
||||
IRReturnVariable() { tag = ReturnValueTempVar() }
|
||||
|
||||
final override string toString() { result = "#return" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A temporary variable generated to hold the exception thrown by a `ThrowValue` instruction.
|
||||
*/
|
||||
class IRThrowVariable extends IRTempVariable {
|
||||
IRThrowVariable() { tag = ThrowTempVar() }
|
||||
|
||||
override string getBaseString() { result = "#throw" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A variable generated to represent the contents of a string literal. This variable acts much like
|
||||
* a read-only global variable.
|
||||
*/
|
||||
class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
Language::StringLiteral literal;
|
||||
|
||||
|
||||
@@ -94,12 +94,21 @@ module InstructionSanity {
|
||||
/**
|
||||
* Holds if instruction `instr` has multiple operands with tag `tag`.
|
||||
*/
|
||||
query predicate duplicateOperand(Instruction instr, OperandTag tag) {
|
||||
strictcount(NonPhiOperand operand |
|
||||
operand = instr.getAnOperand() and
|
||||
operand.getOperandTag() = tag
|
||||
) > 1 and
|
||||
not tag instanceof UnmodeledUseOperandTag
|
||||
query predicate duplicateOperand(
|
||||
Instruction instr, string message, IRFunction func, string funcText
|
||||
) {
|
||||
exists(OperandTag tag, int operandCount |
|
||||
operandCount = strictcount(NonPhiOperand operand |
|
||||
operand = instr.getAnOperand() and
|
||||
operand.getOperandTag() = tag
|
||||
) and
|
||||
operandCount > 1 and
|
||||
not tag instanceof UnmodeledUseOperandTag and
|
||||
message = "Instruction has " + operandCount + " operands with tag '" + tag.toString() + "'" +
|
||||
" in function '$@'." and
|
||||
func = instr.getEnclosingIRFunction() and
|
||||
funcText = Language::getIdentityString(func.getFunction())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,26 +6,6 @@ private import semmle.code.cpp.models.interfaces.Alias
|
||||
|
||||
private class IntValue = Ints::IntValue;
|
||||
|
||||
/**
|
||||
* Converts the bit count in `bits` to a byte count and a bit count in the form
|
||||
* bytes:bits.
|
||||
*/
|
||||
bindingset[bits]
|
||||
string bitsToBytesAndBits(int bits) { result = (bits / 8).toString() + ":" + (bits % 8).toString() }
|
||||
|
||||
/**
|
||||
* Gets a printable string for a bit offset with possibly unknown value.
|
||||
*/
|
||||
bindingset[bitOffset]
|
||||
string getBitOffsetString(IntValue bitOffset) {
|
||||
if Ints::hasValue(bitOffset)
|
||||
then
|
||||
if bitOffset >= 0
|
||||
then result = "+" + bitsToBytesAndBits(bitOffset)
|
||||
else result = "-" + bitsToBytesAndBits(Ints::neg(bitOffset))
|
||||
else result = "+?"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the offset of field `field` in bits.
|
||||
*/
|
||||
@@ -137,7 +117,11 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
|
||||
or
|
||||
// Adding an integer to or subtracting an integer from a pointer propagates
|
||||
// the address with an offset.
|
||||
bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction))
|
||||
exists(PointerOffsetInstruction ptrOffset |
|
||||
ptrOffset = instr and
|
||||
operand = ptrOffset.getLeftOperand() and
|
||||
bitOffset = getPointerBitOffset(ptrOffset)
|
||||
)
|
||||
or
|
||||
// Computing a field address from a pointer propagates the address plus the
|
||||
// offset of the field.
|
||||
|
||||
@@ -865,3 +865,17 @@ private module CachedForDebugging {
|
||||
result.getTag() = var.getTag()
|
||||
}
|
||||
}
|
||||
|
||||
module SSASanity {
|
||||
query predicate multipleOperandMemoryLocations(
|
||||
OldIR::MemoryOperand operand, string message, OldIR::IRFunction func, string funcText
|
||||
) {
|
||||
exists(int locationCount |
|
||||
locationCount = strictcount(Alias::getOperandMemoryLocation(operand)) and
|
||||
locationCount > 1 and
|
||||
func = operand.getEnclosingIRFunction() and
|
||||
funcText = Language::getIdentityString(func.getFunction()) and
|
||||
message = "Operand has " + locationCount.toString() + " memory accesses in function '$@'."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* @name Aliased SSA Sanity Check
|
||||
* @description Performs sanity checks on the SSA construction. This query should have no results.
|
||||
* @kind table
|
||||
* @id cpp/aliased-ssa-sanity-check
|
||||
*/
|
||||
|
||||
import SSASanity
|
||||
@@ -0,0 +1,2 @@
|
||||
private import SSAConstruction as SSA
|
||||
import SSA::SSASanity
|
||||
@@ -13,14 +13,20 @@ IRUserVariable getIRUserVariable(Language::Function func, Language::Variable var
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a variable referenced by the IR for a function. The variable may
|
||||
* be a user-declared variable (`IRUserVariable`) or a temporary variable
|
||||
* generated by the AST-to-IR translation (`IRTempVariable`).
|
||||
* A variable referenced by the IR for a function. The variable may be a user-declared variable
|
||||
* (`IRUserVariable`) or a temporary variable generated by the AST-to-IR translation
|
||||
* (`IRTempVariable`).
|
||||
*/
|
||||
abstract class IRVariable extends TIRVariable {
|
||||
class IRVariable extends TIRVariable {
|
||||
Language::Function func;
|
||||
|
||||
abstract string toString();
|
||||
IRVariable() {
|
||||
this = TIRUserVariable(_, _, func) or
|
||||
this = TIRTempVariable(func, _, _, _) or
|
||||
this = TIRStringLiteral(func, _, _, _)
|
||||
}
|
||||
|
||||
string toString() { none() }
|
||||
|
||||
/**
|
||||
* Holds if this variable's value cannot be changed within a function. Currently used for string
|
||||
@@ -41,19 +47,19 @@ abstract class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
abstract Language::LanguageType getLanguageType();
|
||||
Language::LanguageType getLanguageType() { none() }
|
||||
|
||||
/**
|
||||
* Gets the AST node that declared this variable, or that introduced this
|
||||
* variable as part of the AST-to-IR translation.
|
||||
*/
|
||||
abstract Language::AST getAST();
|
||||
Language::AST getAST() { none() }
|
||||
|
||||
/**
|
||||
* Gets an identifier string for the variable. This identifier is unique
|
||||
* within the function.
|
||||
*/
|
||||
abstract string getUniqueId();
|
||||
string getUniqueId() { none() }
|
||||
|
||||
/**
|
||||
* Gets the source location of this variable.
|
||||
@@ -72,7 +78,7 @@ abstract class IRVariable extends TIRVariable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a user-declared variable referenced by the IR for a function.
|
||||
* A user-declared variable referenced by the IR for a function.
|
||||
*/
|
||||
class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
Language::Variable var;
|
||||
@@ -97,20 +103,34 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a variable (user-declared or temporary) that is allocated on the
|
||||
* stack. This includes all parameters, non-static local variables, and
|
||||
* temporary variables.
|
||||
* A variable (user-declared or temporary) that is allocated on the stack. This includes all
|
||||
* parameters, non-static local variables, and temporary variables.
|
||||
*/
|
||||
abstract class IRAutomaticVariable extends IRVariable { }
|
||||
class IRAutomaticVariable extends IRVariable {
|
||||
IRAutomaticVariable() {
|
||||
exists(Language::Variable var |
|
||||
this = TIRUserVariable(var, _, func) and
|
||||
Language::isVariableAutomatic(var)
|
||||
)
|
||||
or
|
||||
this = TIRTempVariable(func, _, _, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-declared variable that is allocated on the stack. This includes all parameters and
|
||||
* non-static local variables.
|
||||
*/
|
||||
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
|
||||
override Language::AutomaticVariable var;
|
||||
|
||||
IRAutomaticUserVariable() { Language::isVariableAutomatic(var) }
|
||||
|
||||
final override Language::AutomaticVariable getVariable() { result = var }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-declared variable that is not allocated on the stack. This includes all global variables,
|
||||
* namespace-scope variables, static fields, and static local variables.
|
||||
*/
|
||||
class IRStaticUserVariable extends IRUserVariable {
|
||||
override Language::StaticVariable var;
|
||||
|
||||
@@ -119,10 +139,19 @@ class IRStaticUserVariable extends IRUserVariable {
|
||||
final override Language::StaticVariable getVariable() { result = var }
|
||||
}
|
||||
|
||||
abstract class IRGeneratedVariable extends IRVariable {
|
||||
/**
|
||||
* A variable that is not user-declared. This includes temporary variables generated as part of IR
|
||||
* construction, as well as string literals.
|
||||
*/
|
||||
class IRGeneratedVariable extends IRVariable {
|
||||
Language::AST ast;
|
||||
Language::LanguageType type;
|
||||
|
||||
IRGeneratedVariable() {
|
||||
this = TIRTempVariable(func, ast, _, type) or
|
||||
this = TIRStringLiteral(func, ast, type, _)
|
||||
}
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
final override Language::AST getAST() { result = ast }
|
||||
@@ -144,6 +173,11 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
|
||||
result.getTag() = tag
|
||||
}
|
||||
|
||||
/**
|
||||
* A temporary variable introduced by IR construction. The most common examples are the variable
|
||||
* generated to hold the return value of afunction, or the variable generated to hold the result of
|
||||
* a condition operator (`a ? b : c`).
|
||||
*/
|
||||
class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {
|
||||
TempVariableTag tag;
|
||||
|
||||
@@ -158,18 +192,28 @@ class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVa
|
||||
override string getBaseString() { result = "#temp" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A temporary variable generated to hold the return value of a function.
|
||||
*/
|
||||
class IRReturnVariable extends IRTempVariable {
|
||||
IRReturnVariable() { tag = ReturnValueTempVar() }
|
||||
|
||||
final override string toString() { result = "#return" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A temporary variable generated to hold the exception thrown by a `ThrowValue` instruction.
|
||||
*/
|
||||
class IRThrowVariable extends IRTempVariable {
|
||||
IRThrowVariable() { tag = ThrowTempVar() }
|
||||
|
||||
override string getBaseString() { result = "#throw" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A variable generated to represent the contents of a string literal. This variable acts much like
|
||||
* a read-only global variable.
|
||||
*/
|
||||
class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
Language::StringLiteral literal;
|
||||
|
||||
|
||||
@@ -94,12 +94,21 @@ module InstructionSanity {
|
||||
/**
|
||||
* Holds if instruction `instr` has multiple operands with tag `tag`.
|
||||
*/
|
||||
query predicate duplicateOperand(Instruction instr, OperandTag tag) {
|
||||
strictcount(NonPhiOperand operand |
|
||||
operand = instr.getAnOperand() and
|
||||
operand.getOperandTag() = tag
|
||||
) > 1 and
|
||||
not tag instanceof UnmodeledUseOperandTag
|
||||
query predicate duplicateOperand(
|
||||
Instruction instr, string message, IRFunction func, string funcText
|
||||
) {
|
||||
exists(OperandTag tag, int operandCount |
|
||||
operandCount = strictcount(NonPhiOperand operand |
|
||||
operand = instr.getAnOperand() and
|
||||
operand.getOperandTag() = tag
|
||||
) and
|
||||
operandCount > 1 and
|
||||
not tag instanceof UnmodeledUseOperandTag and
|
||||
message = "Instruction has " + operandCount + " operands with tag '" + tag.toString() + "'" +
|
||||
" in function '$@'." and
|
||||
func = instr.getEnclosingIRFunction() and
|
||||
funcText = Language::getIdentityString(func.getFunction())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,14 +13,20 @@ IRUserVariable getIRUserVariable(Language::Function func, Language::Variable var
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a variable referenced by the IR for a function. The variable may
|
||||
* be a user-declared variable (`IRUserVariable`) or a temporary variable
|
||||
* generated by the AST-to-IR translation (`IRTempVariable`).
|
||||
* A variable referenced by the IR for a function. The variable may be a user-declared variable
|
||||
* (`IRUserVariable`) or a temporary variable generated by the AST-to-IR translation
|
||||
* (`IRTempVariable`).
|
||||
*/
|
||||
abstract class IRVariable extends TIRVariable {
|
||||
class IRVariable extends TIRVariable {
|
||||
Language::Function func;
|
||||
|
||||
abstract string toString();
|
||||
IRVariable() {
|
||||
this = TIRUserVariable(_, _, func) or
|
||||
this = TIRTempVariable(func, _, _, _) or
|
||||
this = TIRStringLiteral(func, _, _, _)
|
||||
}
|
||||
|
||||
string toString() { none() }
|
||||
|
||||
/**
|
||||
* Holds if this variable's value cannot be changed within a function. Currently used for string
|
||||
@@ -41,19 +47,19 @@ abstract class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
abstract Language::LanguageType getLanguageType();
|
||||
Language::LanguageType getLanguageType() { none() }
|
||||
|
||||
/**
|
||||
* Gets the AST node that declared this variable, or that introduced this
|
||||
* variable as part of the AST-to-IR translation.
|
||||
*/
|
||||
abstract Language::AST getAST();
|
||||
Language::AST getAST() { none() }
|
||||
|
||||
/**
|
||||
* Gets an identifier string for the variable. This identifier is unique
|
||||
* within the function.
|
||||
*/
|
||||
abstract string getUniqueId();
|
||||
string getUniqueId() { none() }
|
||||
|
||||
/**
|
||||
* Gets the source location of this variable.
|
||||
@@ -72,7 +78,7 @@ abstract class IRVariable extends TIRVariable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a user-declared variable referenced by the IR for a function.
|
||||
* A user-declared variable referenced by the IR for a function.
|
||||
*/
|
||||
class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
Language::Variable var;
|
||||
@@ -97,20 +103,34 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a variable (user-declared or temporary) that is allocated on the
|
||||
* stack. This includes all parameters, non-static local variables, and
|
||||
* temporary variables.
|
||||
* A variable (user-declared or temporary) that is allocated on the stack. This includes all
|
||||
* parameters, non-static local variables, and temporary variables.
|
||||
*/
|
||||
abstract class IRAutomaticVariable extends IRVariable { }
|
||||
class IRAutomaticVariable extends IRVariable {
|
||||
IRAutomaticVariable() {
|
||||
exists(Language::Variable var |
|
||||
this = TIRUserVariable(var, _, func) and
|
||||
Language::isVariableAutomatic(var)
|
||||
)
|
||||
or
|
||||
this = TIRTempVariable(func, _, _, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-declared variable that is allocated on the stack. This includes all parameters and
|
||||
* non-static local variables.
|
||||
*/
|
||||
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
|
||||
override Language::AutomaticVariable var;
|
||||
|
||||
IRAutomaticUserVariable() { Language::isVariableAutomatic(var) }
|
||||
|
||||
final override Language::AutomaticVariable getVariable() { result = var }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-declared variable that is not allocated on the stack. This includes all global variables,
|
||||
* namespace-scope variables, static fields, and static local variables.
|
||||
*/
|
||||
class IRStaticUserVariable extends IRUserVariable {
|
||||
override Language::StaticVariable var;
|
||||
|
||||
@@ -119,10 +139,19 @@ class IRStaticUserVariable extends IRUserVariable {
|
||||
final override Language::StaticVariable getVariable() { result = var }
|
||||
}
|
||||
|
||||
abstract class IRGeneratedVariable extends IRVariable {
|
||||
/**
|
||||
* A variable that is not user-declared. This includes temporary variables generated as part of IR
|
||||
* construction, as well as string literals.
|
||||
*/
|
||||
class IRGeneratedVariable extends IRVariable {
|
||||
Language::AST ast;
|
||||
Language::LanguageType type;
|
||||
|
||||
IRGeneratedVariable() {
|
||||
this = TIRTempVariable(func, ast, _, type) or
|
||||
this = TIRStringLiteral(func, ast, type, _)
|
||||
}
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
final override Language::AST getAST() { result = ast }
|
||||
@@ -144,6 +173,11 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
|
||||
result.getTag() = tag
|
||||
}
|
||||
|
||||
/**
|
||||
* A temporary variable introduced by IR construction. The most common examples are the variable
|
||||
* generated to hold the return value of afunction, or the variable generated to hold the result of
|
||||
* a condition operator (`a ? b : c`).
|
||||
*/
|
||||
class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {
|
||||
TempVariableTag tag;
|
||||
|
||||
@@ -158,18 +192,28 @@ class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVa
|
||||
override string getBaseString() { result = "#temp" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A temporary variable generated to hold the return value of a function.
|
||||
*/
|
||||
class IRReturnVariable extends IRTempVariable {
|
||||
IRReturnVariable() { tag = ReturnValueTempVar() }
|
||||
|
||||
final override string toString() { result = "#return" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A temporary variable generated to hold the exception thrown by a `ThrowValue` instruction.
|
||||
*/
|
||||
class IRThrowVariable extends IRTempVariable {
|
||||
IRThrowVariable() { tag = ThrowTempVar() }
|
||||
|
||||
override string getBaseString() { result = "#throw" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A variable generated to represent the contents of a string literal. This variable acts much like
|
||||
* a read-only global variable.
|
||||
*/
|
||||
class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
Language::StringLiteral literal;
|
||||
|
||||
|
||||
@@ -94,12 +94,21 @@ module InstructionSanity {
|
||||
/**
|
||||
* Holds if instruction `instr` has multiple operands with tag `tag`.
|
||||
*/
|
||||
query predicate duplicateOperand(Instruction instr, OperandTag tag) {
|
||||
strictcount(NonPhiOperand operand |
|
||||
operand = instr.getAnOperand() and
|
||||
operand.getOperandTag() = tag
|
||||
) > 1 and
|
||||
not tag instanceof UnmodeledUseOperandTag
|
||||
query predicate duplicateOperand(
|
||||
Instruction instr, string message, IRFunction func, string funcText
|
||||
) {
|
||||
exists(OperandTag tag, int operandCount |
|
||||
operandCount = strictcount(NonPhiOperand operand |
|
||||
operand = instr.getAnOperand() and
|
||||
operand.getOperandTag() = tag
|
||||
) and
|
||||
operandCount > 1 and
|
||||
not tag instanceof UnmodeledUseOperandTag and
|
||||
message = "Instruction has " + operandCount + " operands with tag '" + tag.toString() + "'" +
|
||||
" in function '$@'." and
|
||||
func = instr.getEnclosingIRFunction() and
|
||||
funcText = Language::getIdentityString(func.getFunction())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,26 +6,6 @@ private import semmle.code.cpp.models.interfaces.Alias
|
||||
|
||||
private class IntValue = Ints::IntValue;
|
||||
|
||||
/**
|
||||
* Converts the bit count in `bits` to a byte count and a bit count in the form
|
||||
* bytes:bits.
|
||||
*/
|
||||
bindingset[bits]
|
||||
string bitsToBytesAndBits(int bits) { result = (bits / 8).toString() + ":" + (bits % 8).toString() }
|
||||
|
||||
/**
|
||||
* Gets a printable string for a bit offset with possibly unknown value.
|
||||
*/
|
||||
bindingset[bitOffset]
|
||||
string getBitOffsetString(IntValue bitOffset) {
|
||||
if Ints::hasValue(bitOffset)
|
||||
then
|
||||
if bitOffset >= 0
|
||||
then result = "+" + bitsToBytesAndBits(bitOffset)
|
||||
else result = "-" + bitsToBytesAndBits(Ints::neg(bitOffset))
|
||||
else result = "+?"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the offset of field `field` in bits.
|
||||
*/
|
||||
@@ -137,7 +117,11 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
|
||||
or
|
||||
// Adding an integer to or subtracting an integer from a pointer propagates
|
||||
// the address with an offset.
|
||||
bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction))
|
||||
exists(PointerOffsetInstruction ptrOffset |
|
||||
ptrOffset = instr and
|
||||
operand = ptrOffset.getLeftOperand() and
|
||||
bitOffset = getPointerBitOffset(ptrOffset)
|
||||
)
|
||||
or
|
||||
// Computing a field address from a pointer propagates the address plus the
|
||||
// offset of the field.
|
||||
|
||||
@@ -865,3 +865,17 @@ private module CachedForDebugging {
|
||||
result.getTag() = var.getTag()
|
||||
}
|
||||
}
|
||||
|
||||
module SSASanity {
|
||||
query predicate multipleOperandMemoryLocations(
|
||||
OldIR::MemoryOperand operand, string message, OldIR::IRFunction func, string funcText
|
||||
) {
|
||||
exists(int locationCount |
|
||||
locationCount = strictcount(Alias::getOperandMemoryLocation(operand)) and
|
||||
locationCount > 1 and
|
||||
func = operand.getEnclosingIRFunction() and
|
||||
funcText = Language::getIdentityString(func.getFunction()) and
|
||||
message = "Operand has " + locationCount.toString() + " memory accesses in function '$@'."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* @name Unaliased SSA Sanity Check
|
||||
* @description Performs sanity checks on the SSA construction. This query should have no results.
|
||||
* @kind table
|
||||
* @id cpp/unaliased-ssa-sanity-check
|
||||
*/
|
||||
|
||||
import SSASanity
|
||||
@@ -0,0 +1,2 @@
|
||||
private import SSAConstruction as SSA
|
||||
import SSA::SSASanity
|
||||
@@ -192,3 +192,33 @@ predicate isGT(IntValue a, IntValue b) { hasValue(a) and hasValue(b) and a > b }
|
||||
*/
|
||||
bindingset[a, b]
|
||||
predicate isGE(IntValue a, IntValue b) { hasValue(a) and hasValue(b) and a >= b }
|
||||
|
||||
/**
|
||||
* Converts the bit count in `bits` to a byte count and a bit count in the form
|
||||
* "bytes:bits". If `bits` represents an integer number of bytes, the ":bits" section is omitted.
|
||||
* If `bits` does not have a known value, the result is "?".
|
||||
*/
|
||||
bindingset[bits]
|
||||
string bitsToBytesAndBits(IntValue bits) {
|
||||
exists(int bytes, int leftoverBits |
|
||||
hasValue(bits) and
|
||||
bytes = bits / 8 and
|
||||
leftoverBits = bits % 8 and
|
||||
if leftoverBits = 0 then result = bytes.toString() else result = bytes + ":" + leftoverBits
|
||||
)
|
||||
or
|
||||
not hasValue(bits) and result = "?"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a printable string for a bit offset with possibly unknown value.
|
||||
*/
|
||||
bindingset[bitOffset]
|
||||
string getBitOffsetString(IntValue bitOffset) {
|
||||
if hasValue(bitOffset)
|
||||
then
|
||||
if bitOffset >= 0
|
||||
then result = "+" + bitsToBytesAndBits(bitOffset)
|
||||
else result = "-" + bitsToBytesAndBits(neg(bitOffset))
|
||||
else result = "+?"
|
||||
}
|
||||
|
||||
@@ -30,5 +30,5 @@ Overlap getOverlap(IntValue defStart, IntValue defEnd, IntValue useStart, IntVal
|
||||
bindingset[start, end]
|
||||
string getIntervalString(IntValue start, IntValue end) {
|
||||
// We represent an interval has half-open, so print it as "[start..end)".
|
||||
result = "[" + intValueToString(start) + ".." + intValueToString(end) + ")"
|
||||
result = "[" + bitsToBytesAndBits(start) + ".." + bitsToBytesAndBits(end) + ")"
|
||||
}
|
||||
|
||||
@@ -1,86 +1,86 @@
|
||||
| escape.cpp:111:18:111:21 | CopyValue | no_+0:0 | no_+0:0 |
|
||||
| escape.cpp:115:19:115:28 | PointerAdd[4] | no_+0:0 | no_+0:0 |
|
||||
| escape.cpp:115:20:115:23 | CopyValue | no_+0:0 | no_+0:0 |
|
||||
| escape.cpp:116:19:116:28 | PointerSub[4] | no_+0:0 | no_+0:0 |
|
||||
| escape.cpp:116:20:116:23 | CopyValue | no_+0:0 | no_+0:0 |
|
||||
| escape.cpp:117:19:117:26 | PointerAdd[4] | no_+0:0 | no_+0:0 |
|
||||
| escape.cpp:117:23:117:26 | CopyValue | no_+0:0 | no_+0:0 |
|
||||
| escape.cpp:118:9:118:12 | CopyValue | no_+0:0 | no_+0:0 |
|
||||
| escape.cpp:120:12:120:15 | CopyValue | no_+0:0 | no_+0:0 |
|
||||
| escape.cpp:123:14:123:17 | CopyValue | no_+0:0 | no_+0:0 |
|
||||
| escape.cpp:124:15:124:18 | CopyValue | no_+0:0 | no_+0:0 |
|
||||
| escape.cpp:127:9:127:12 | CopyValue | no_+0:0 | no_+0:0 |
|
||||
| escape.cpp:129:12:129:15 | CopyValue | no_+0:0 | no_+0:0 |
|
||||
| escape.cpp:134:5:134:18 | Convert | no_Array+0:0 | no_Array+0:0 |
|
||||
| escape.cpp:134:11:134:18 | Convert | no_Array+0:0 | no_Array+0:0 |
|
||||
| escape.cpp:135:5:135:12 | Convert | no_Array+0:0 | no_Array+0:0 |
|
||||
| escape.cpp:135:5:135:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 |
|
||||
| escape.cpp:136:5:136:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 |
|
||||
| escape.cpp:136:7:136:14 | Convert | no_Array+0:0 | no_Array+0:0 |
|
||||
| escape.cpp:137:17:137:24 | Convert | no_Array+0:0 | no_Array+0:0 |
|
||||
| escape.cpp:137:17:137:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 |
|
||||
| escape.cpp:138:17:138:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 |
|
||||
| escape.cpp:138:19:138:26 | Convert | no_Array+0:0 | no_Array+0:0 |
|
||||
| escape.cpp:140:21:140:32 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 |
|
||||
| escape.cpp:140:21:140:32 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 |
|
||||
| escape.cpp:140:21:140:32 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 |
|
||||
| escape.cpp:141:27:141:27 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 |
|
||||
| escape.cpp:142:14:142:14 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 |
|
||||
| escape.cpp:143:19:143:27 | CopyValue | no_Point+0:0 | no_Point+0:0 |
|
||||
| escape.cpp:143:31:143:31 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 |
|
||||
| escape.cpp:144:6:144:14 | CopyValue | no_Point+0:0 | no_Point+0:0 |
|
||||
| escape.cpp:144:18:144:18 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 |
|
||||
| escape.cpp:145:20:145:30 | CopyValue | no_Point+8:0 | no_Point+8:0 |
|
||||
| escape.cpp:145:30:145:30 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 |
|
||||
| escape.cpp:146:5:146:18 | CopyValue | no_Point+8:0 | no_Point+8:0 |
|
||||
| escape.cpp:146:7:146:17 | CopyValue | no_Point+8:0 | no_Point+8:0 |
|
||||
| escape.cpp:146:17:146:17 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 |
|
||||
| escape.cpp:149:5:149:14 | ConvertToNonVirtualBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 |
|
||||
| escape.cpp:149:5:149:14 | ConvertToNonVirtualBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 |
|
||||
| escape.cpp:149:16:149:16 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 |
|
||||
| escape.cpp:150:18:150:27 | ConvertToNonVirtualBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 |
|
||||
| escape.cpp:150:18:150:27 | ConvertToNonVirtualBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 |
|
||||
| escape.cpp:150:29:150:29 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 |
|
||||
| escape.cpp:151:5:151:14 | ConvertToNonVirtualBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 |
|
||||
| escape.cpp:151:16:151:17 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 |
|
||||
| escape.cpp:152:19:152:28 | ConvertToNonVirtualBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 |
|
||||
| escape.cpp:152:30:152:31 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 |
|
||||
| escape.cpp:155:17:155:30 | CopyValue | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 |
|
||||
| escape.cpp:155:17:155:30 | Store | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 |
|
||||
| escape.cpp:158:17:158:28 | CopyValue | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 |
|
||||
| escape.cpp:158:17:158:28 | Store | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 |
|
||||
| escape.cpp:161:19:161:42 | Convert | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 |
|
||||
| escape.cpp:161:19:161:45 | CopyValue | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 |
|
||||
| escape.cpp:161:19:161:45 | PointerAdd[4] | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 |
|
||||
| escape.cpp:161:19:161:45 | Store | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 |
|
||||
| escape.cpp:164:24:164:40 | CopyValue | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 |
|
||||
| escape.cpp:164:24:164:40 | Store | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 |
|
||||
| escape.cpp:167:19:167:28 | CopyValue | passByPtr+0:0 | passByPtr+0:0 |
|
||||
| escape.cpp:170:21:170:29 | CopyValue | passByRef+0:0 | passByRef+0:0 |
|
||||
| escape.cpp:173:22:173:38 | CopyValue | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 |
|
||||
| escape.cpp:176:24:176:39 | CopyValue | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 |
|
||||
| escape.cpp:179:22:179:42 | CopyValue | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 |
|
||||
| escape.cpp:182:24:182:43 | CopyValue | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 |
|
||||
| escape.cpp:185:30:185:40 | CopyValue | passByPtr2+0:0 | passByPtr2+0:0 |
|
||||
| escape.cpp:188:32:188:41 | CopyValue | passByRef2+0:0 | passByRef2+0:0 |
|
||||
| escape.cpp:191:30:191:42 | Call | none | passByPtr3+0:0 |
|
||||
| escape.cpp:191:44:191:54 | CopyValue | passByPtr3+0:0 | passByPtr3+0:0 |
|
||||
| escape.cpp:194:32:194:46 | Call | none | passByRef3+0:0 |
|
||||
| escape.cpp:194:32:194:59 | CopyValue | none | passByRef3+0:0 |
|
||||
| escape.cpp:194:48:194:57 | CopyValue | passByRef3+0:0 | passByRef3+0:0 |
|
||||
| escape.cpp:199:17:199:34 | CopyValue | no_ssa_passByPtr4+0:0 | no_ssa_passByPtr4+0:0 |
|
||||
| escape.cpp:199:37:199:54 | CopyValue | no_ssa_passByPtr5+0:0 | no_ssa_passByPtr5+0:0 |
|
||||
| escape.cpp:202:5:202:19 | Call | none | passByRef6+0:0 |
|
||||
| escape.cpp:202:5:202:32 | CopyValue | none | passByRef6+0:0 |
|
||||
| escape.cpp:202:21:202:30 | CopyValue | passByRef6+0:0 | passByRef6+0:0 |
|
||||
| escape.cpp:205:5:205:19 | Call | none | no_ssa_passByRef7+0:0 |
|
||||
| escape.cpp:205:5:205:39 | CopyValue | none | no_ssa_passByRef7+0:0 |
|
||||
| escape.cpp:205:21:205:37 | CopyValue | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 |
|
||||
| escape.cpp:209:14:209:25 | Call | none | no_ssa_c+0:0 |
|
||||
| escape.cpp:217:14:217:16 | CopyValue | c2+0:0 | c2+0:0 |
|
||||
| escape.cpp:221:8:221:19 | Call | none | c3+0:0 |
|
||||
| escape.cpp:225:17:225:28 | Call | none | c4+0:0 |
|
||||
| escape.cpp:247:2:247:27 | Store | condEscape1+0:0 | condEscape1+0:0 |
|
||||
| escape.cpp:247:16:247:27 | CopyValue | condEscape1+0:0 | condEscape1+0:0 |
|
||||
| escape.cpp:249:9:249:34 | Store | condEscape2+0:0 | condEscape2+0:0 |
|
||||
| escape.cpp:249:23:249:34 | CopyValue | condEscape2+0:0 | condEscape2+0:0 |
|
||||
| escape.cpp:111:18:111:21 | CopyValue | no_+0 | no_+0 |
|
||||
| escape.cpp:115:19:115:28 | PointerAdd[4] | no_+0 | no_+0 |
|
||||
| escape.cpp:115:20:115:23 | CopyValue | no_+0 | no_+0 |
|
||||
| escape.cpp:116:19:116:28 | PointerSub[4] | no_+0 | no_+0 |
|
||||
| escape.cpp:116:20:116:23 | CopyValue | no_+0 | no_+0 |
|
||||
| escape.cpp:117:19:117:26 | PointerAdd[4] | no_+0 | no_+0 |
|
||||
| escape.cpp:117:23:117:26 | CopyValue | no_+0 | no_+0 |
|
||||
| escape.cpp:118:9:118:12 | CopyValue | no_+0 | no_+0 |
|
||||
| escape.cpp:120:12:120:15 | CopyValue | no_+0 | no_+0 |
|
||||
| escape.cpp:123:14:123:17 | CopyValue | no_+0 | no_+0 |
|
||||
| escape.cpp:124:15:124:18 | CopyValue | no_+0 | no_+0 |
|
||||
| escape.cpp:127:9:127:12 | CopyValue | no_+0 | no_+0 |
|
||||
| escape.cpp:129:12:129:15 | CopyValue | no_+0 | no_+0 |
|
||||
| escape.cpp:134:5:134:18 | Convert | no_Array+0 | no_Array+0 |
|
||||
| escape.cpp:134:11:134:18 | Convert | no_Array+0 | no_Array+0 |
|
||||
| escape.cpp:135:5:135:12 | Convert | no_Array+0 | no_Array+0 |
|
||||
| escape.cpp:135:5:135:15 | PointerAdd[4] | no_Array+20 | no_Array+20 |
|
||||
| escape.cpp:136:5:136:15 | PointerAdd[4] | no_Array+20 | no_Array+20 |
|
||||
| escape.cpp:136:7:136:14 | Convert | no_Array+0 | no_Array+0 |
|
||||
| escape.cpp:137:17:137:24 | Convert | no_Array+0 | no_Array+0 |
|
||||
| escape.cpp:137:17:137:27 | PointerAdd[4] | no_Array+20 | no_Array+20 |
|
||||
| escape.cpp:138:17:138:27 | PointerAdd[4] | no_Array+20 | no_Array+20 |
|
||||
| escape.cpp:138:19:138:26 | Convert | no_Array+0 | no_Array+0 |
|
||||
| escape.cpp:140:21:140:32 | FieldAddress[x] | no_Point+0 | no_Point+0 |
|
||||
| escape.cpp:140:21:140:32 | FieldAddress[y] | no_Point+4 | no_Point+4 |
|
||||
| escape.cpp:140:21:140:32 | FieldAddress[z] | no_Point+8 | no_Point+8 |
|
||||
| escape.cpp:141:27:141:27 | FieldAddress[x] | no_Point+0 | no_Point+0 |
|
||||
| escape.cpp:142:14:142:14 | FieldAddress[y] | no_Point+4 | no_Point+4 |
|
||||
| escape.cpp:143:19:143:27 | CopyValue | no_Point+0 | no_Point+0 |
|
||||
| escape.cpp:143:31:143:31 | FieldAddress[y] | no_Point+4 | no_Point+4 |
|
||||
| escape.cpp:144:6:144:14 | CopyValue | no_Point+0 | no_Point+0 |
|
||||
| escape.cpp:144:18:144:18 | FieldAddress[y] | no_Point+4 | no_Point+4 |
|
||||
| escape.cpp:145:20:145:30 | CopyValue | no_Point+8 | no_Point+8 |
|
||||
| escape.cpp:145:30:145:30 | FieldAddress[z] | no_Point+8 | no_Point+8 |
|
||||
| escape.cpp:146:5:146:18 | CopyValue | no_Point+8 | no_Point+8 |
|
||||
| escape.cpp:146:7:146:17 | CopyValue | no_Point+8 | no_Point+8 |
|
||||
| escape.cpp:146:17:146:17 | FieldAddress[z] | no_Point+8 | no_Point+8 |
|
||||
| escape.cpp:149:5:149:14 | ConvertToNonVirtualBase[Derived : Intermediate1] | no_Derived+0 | no_Derived+0 |
|
||||
| escape.cpp:149:5:149:14 | ConvertToNonVirtualBase[Intermediate1 : Base] | no_Derived+0 | no_Derived+0 |
|
||||
| escape.cpp:149:16:149:16 | FieldAddress[b] | no_Derived+0 | no_Derived+0 |
|
||||
| escape.cpp:150:18:150:27 | ConvertToNonVirtualBase[Derived : Intermediate1] | no_Derived+0 | no_Derived+0 |
|
||||
| escape.cpp:150:18:150:27 | ConvertToNonVirtualBase[Intermediate1 : Base] | no_Derived+0 | no_Derived+0 |
|
||||
| escape.cpp:150:29:150:29 | FieldAddress[b] | no_Derived+0 | no_Derived+0 |
|
||||
| escape.cpp:151:5:151:14 | ConvertToNonVirtualBase[Derived : Intermediate2] | no_Derived+12 | no_Derived+12 |
|
||||
| escape.cpp:151:16:151:17 | FieldAddress[i2] | no_Derived+16 | no_Derived+16 |
|
||||
| escape.cpp:152:19:152:28 | ConvertToNonVirtualBase[Derived : Intermediate2] | no_Derived+12 | no_Derived+12 |
|
||||
| escape.cpp:152:30:152:31 | FieldAddress[i2] | no_Derived+16 | no_Derived+16 |
|
||||
| escape.cpp:155:17:155:30 | CopyValue | no_ssa_addrOf+0 | no_ssa_addrOf+0 |
|
||||
| escape.cpp:155:17:155:30 | Store | no_ssa_addrOf+0 | no_ssa_addrOf+0 |
|
||||
| escape.cpp:158:17:158:28 | CopyValue | no_ssa_refTo+0 | no_ssa_refTo+0 |
|
||||
| escape.cpp:158:17:158:28 | Store | no_ssa_refTo+0 | no_ssa_refTo+0 |
|
||||
| escape.cpp:161:19:161:42 | Convert | no_ssa_refToArrayElement+0 | no_ssa_refToArrayElement+0 |
|
||||
| escape.cpp:161:19:161:45 | CopyValue | no_ssa_refToArrayElement+20 | no_ssa_refToArrayElement+20 |
|
||||
| escape.cpp:161:19:161:45 | PointerAdd[4] | no_ssa_refToArrayElement+20 | no_ssa_refToArrayElement+20 |
|
||||
| escape.cpp:161:19:161:45 | Store | no_ssa_refToArrayElement+20 | no_ssa_refToArrayElement+20 |
|
||||
| escape.cpp:164:24:164:40 | CopyValue | no_ssa_refToArray+0 | no_ssa_refToArray+0 |
|
||||
| escape.cpp:164:24:164:40 | Store | no_ssa_refToArray+0 | no_ssa_refToArray+0 |
|
||||
| escape.cpp:167:19:167:28 | CopyValue | passByPtr+0 | passByPtr+0 |
|
||||
| escape.cpp:170:21:170:29 | CopyValue | passByRef+0 | passByRef+0 |
|
||||
| escape.cpp:173:22:173:38 | CopyValue | no_ssa_passByPtr+0 | no_ssa_passByPtr+0 |
|
||||
| escape.cpp:176:24:176:39 | CopyValue | no_ssa_passByRef+0 | no_ssa_passByRef+0 |
|
||||
| escape.cpp:179:22:179:42 | CopyValue | no_ssa_passByPtr_ret+0 | no_ssa_passByPtr_ret+0 |
|
||||
| escape.cpp:182:24:182:43 | CopyValue | no_ssa_passByRef_ret+0 | no_ssa_passByRef_ret+0 |
|
||||
| escape.cpp:185:30:185:40 | CopyValue | passByPtr2+0 | passByPtr2+0 |
|
||||
| escape.cpp:188:32:188:41 | CopyValue | passByRef2+0 | passByRef2+0 |
|
||||
| escape.cpp:191:30:191:42 | Call | none | passByPtr3+0 |
|
||||
| escape.cpp:191:44:191:54 | CopyValue | passByPtr3+0 | passByPtr3+0 |
|
||||
| escape.cpp:194:32:194:46 | Call | none | passByRef3+0 |
|
||||
| escape.cpp:194:32:194:59 | CopyValue | none | passByRef3+0 |
|
||||
| escape.cpp:194:48:194:57 | CopyValue | passByRef3+0 | passByRef3+0 |
|
||||
| escape.cpp:199:17:199:34 | CopyValue | no_ssa_passByPtr4+0 | no_ssa_passByPtr4+0 |
|
||||
| escape.cpp:199:37:199:54 | CopyValue | no_ssa_passByPtr5+0 | no_ssa_passByPtr5+0 |
|
||||
| escape.cpp:202:5:202:19 | Call | none | passByRef6+0 |
|
||||
| escape.cpp:202:5:202:32 | CopyValue | none | passByRef6+0 |
|
||||
| escape.cpp:202:21:202:30 | CopyValue | passByRef6+0 | passByRef6+0 |
|
||||
| escape.cpp:205:5:205:19 | Call | none | no_ssa_passByRef7+0 |
|
||||
| escape.cpp:205:5:205:39 | CopyValue | none | no_ssa_passByRef7+0 |
|
||||
| escape.cpp:205:21:205:37 | CopyValue | no_ssa_passByRef7+0 | no_ssa_passByRef7+0 |
|
||||
| escape.cpp:209:14:209:25 | Call | none | no_ssa_c+0 |
|
||||
| escape.cpp:217:14:217:16 | CopyValue | c2+0 | c2+0 |
|
||||
| escape.cpp:221:8:221:19 | Call | none | c3+0 |
|
||||
| escape.cpp:225:17:225:28 | Call | none | c4+0 |
|
||||
| escape.cpp:247:2:247:27 | Store | condEscape1+0 | condEscape1+0 |
|
||||
| escape.cpp:247:16:247:27 | CopyValue | condEscape1+0 | condEscape1+0 |
|
||||
| escape.cpp:249:9:249:34 | Store | condEscape2+0 | condEscape2+0 |
|
||||
| escape.cpp:249:23:249:34 | CopyValue | condEscape2+0 | condEscape2+0 |
|
||||
|
||||
@@ -4,6 +4,7 @@ import semmle.code.cpp.ir.implementation.raw.IR as Raw
|
||||
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.AliasAnalysis as UnAA
|
||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as Un
|
||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction
|
||||
import semmle.code.cpp.ir.internal.IntegerConstant
|
||||
|
||||
from Raw::Instruction rawInstr, Un::Instruction unInstr, string rawPointsTo, string unPointsTo
|
||||
where
|
||||
@@ -12,21 +13,21 @@ where
|
||||
(
|
||||
exists(Variable var, int rawBitOffset, int unBitOffset |
|
||||
RawAA::resultPointsTo(rawInstr, Raw::getIRUserVariable(_, var), rawBitOffset) and
|
||||
rawPointsTo = var.toString() + RawAA::getBitOffsetString(rawBitOffset) and
|
||||
rawPointsTo = var.toString() + getBitOffsetString(rawBitOffset) and
|
||||
UnAA::resultPointsTo(unInstr, Un::getIRUserVariable(_, var), unBitOffset) and
|
||||
unPointsTo = var.toString() + UnAA::getBitOffsetString(unBitOffset)
|
||||
unPointsTo = var.toString() + getBitOffsetString(unBitOffset)
|
||||
)
|
||||
or
|
||||
exists(Variable var, int unBitOffset |
|
||||
not RawAA::resultPointsTo(rawInstr, Raw::getIRUserVariable(_, var), _) and
|
||||
rawPointsTo = "none" and
|
||||
UnAA::resultPointsTo(unInstr, Un::getIRUserVariable(_, var), unBitOffset) and
|
||||
unPointsTo = var.toString() + UnAA::getBitOffsetString(unBitOffset)
|
||||
unPointsTo = var.toString() + getBitOffsetString(unBitOffset)
|
||||
)
|
||||
or
|
||||
exists(Variable var, int rawBitOffset |
|
||||
RawAA::resultPointsTo(rawInstr, Raw::getIRUserVariable(_, var), rawBitOffset) and
|
||||
rawPointsTo = var.toString() + RawAA::getBitOffsetString(rawBitOffset) and
|
||||
rawPointsTo = var.toString() + getBitOffsetString(rawBitOffset) and
|
||||
not UnAA::resultPointsTo(unInstr, Un::getIRUserVariable(_, var), _) and
|
||||
unPointsTo = "none"
|
||||
)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSASanity.ql
|
||||
@@ -0,0 +1 @@
|
||||
semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSASanity.ql
|
||||
@@ -0,0 +1 @@
|
||||
semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSASanity.ql
|
||||
@@ -0,0 +1 @@
|
||||
semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSASanity.ql
|
||||
Reference in New Issue
Block a user