Force LF line endings for .ql, .qll, and .qlref files

This commit is contained in:
Dave Bartolomeo
2018-08-24 11:58:58 -07:00
parent 59ddda881e
commit d920fc7d94
108 changed files with 7195 additions and 7182 deletions

13
.gitattributes vendored Normal file
View File

@@ -0,0 +1,13 @@
# The following file types will be normalized to LF line endings in the Git
# database, and will keep those LF line endings in the working tree even on
# Windows. Any other files will have whatever line endings they had when they
# were committed. If you add new entires below, you should renormalize the
# affected files by running the following from the root of this repo (requires
# Git 2.16 or greater):
#
# git add --renormalize .
# git status [just to show what files were renormalized]
# git commit -m "Normalize line endings"
*.ql eol=lf
*.qll eol=lf
*.qlref eol=lf

View File

@@ -1,9 +1,9 @@
/** /**
* @name Print AST * @name Print AST
* @description Outputs a representation of the Abstract Syntax Tree. * @description Outputs a representation of the Abstract Syntax Tree.
* @id cpp/print-ast * @id cpp/print-ast
* @kind graph * @kind graph
*/ */
import cpp import cpp
import PrintAST import PrintAST

File diff suppressed because it is too large Load Diff

View File

@@ -1,141 +1,141 @@
import cpp import cpp
private newtype TEdgeKind = private newtype TEdgeKind =
TGotoEdge() or // Single successor (including fall-through) TGotoEdge() or // Single successor (including fall-through)
TTrueEdge() or // 'true' edge of conditional branch TTrueEdge() or // 'true' edge of conditional branch
TFalseEdge() or // 'false' edge of conditional branch TFalseEdge() or // 'false' edge of conditional branch
TExceptionEdge() or // Thrown exception TExceptionEdge() or // Thrown exception
TDefaultEdge() or // 'default' label of switch TDefaultEdge() or // 'default' label of switch
TCaseEdge(string minValue, string maxValue) { // Case label of switch TCaseEdge(string minValue, string maxValue) { // Case label of switch
exists(SwitchCase switchCase | exists(SwitchCase switchCase |
hasCaseEdge(switchCase, minValue, maxValue) hasCaseEdge(switchCase, minValue, maxValue)
) )
} }
/** /**
* Represents the kind of an edge in the IR control flow graph. Each * Represents the kind of an edge in the IR control flow graph. Each
* `Instruction` or `IRBlock` has at most one successor of any single * `Instruction` or `IRBlock` has at most one successor of any single
* `EdgeKind`. * `EdgeKind`.
*/ */
abstract class EdgeKind extends TEdgeKind { abstract class EdgeKind extends TEdgeKind {
abstract string toString(); abstract string toString();
} }
/** /**
* A "goto" edge, representing the unconditional successor of an `Instruction` * A "goto" edge, representing the unconditional successor of an `Instruction`
* or `IRBlock`. * or `IRBlock`.
*/ */
class GotoEdge extends EdgeKind, TGotoEdge { class GotoEdge extends EdgeKind, TGotoEdge {
override final string toString() { override final string toString() {
result = "Goto" result = "Goto"
} }
} }
GotoEdge gotoEdge() { GotoEdge gotoEdge() {
result = TGotoEdge() result = TGotoEdge()
} }
/** /**
* A "true" edge, representing the successor of a conditional branch when the * A "true" edge, representing the successor of a conditional branch when the
* condition is non-zero. * condition is non-zero.
*/ */
class TrueEdge extends EdgeKind, TTrueEdge { class TrueEdge extends EdgeKind, TTrueEdge {
override final string toString() { override final string toString() {
result = "True" result = "True"
} }
} }
TrueEdge trueEdge() { TrueEdge trueEdge() {
result = TTrueEdge() result = TTrueEdge()
} }
/** /**
* A "false" edge, representing the successor of a conditional branch when the * A "false" edge, representing the successor of a conditional branch when the
* condition is zero. * condition is zero.
*/ */
class FalseEdge extends EdgeKind, TFalseEdge { class FalseEdge extends EdgeKind, TFalseEdge {
override final string toString() { override final string toString() {
result = "False" result = "False"
} }
} }
FalseEdge falseEdge() { FalseEdge falseEdge() {
result = TFalseEdge() result = TFalseEdge()
} }
/** /**
* An "exception" edge, representing the successor of an instruction when that * An "exception" edge, representing the successor of an instruction when that
* instruction's evaluation throws an exception. * instruction's evaluation throws an exception.
*/ */
class ExceptionEdge extends EdgeKind, TExceptionEdge { class ExceptionEdge extends EdgeKind, TExceptionEdge {
override final string toString() { override final string toString() {
result = "Exception" result = "Exception"
} }
} }
ExceptionEdge exceptionEdge() { ExceptionEdge exceptionEdge() {
result = TExceptionEdge() result = TExceptionEdge()
} }
/** /**
* A "default" edge, representing the successor of a `Switch` instruction when * A "default" edge, representing the successor of a `Switch` instruction when
* none of the case values matches the condition value. * none of the case values matches the condition value.
*/ */
class DefaultEdge extends EdgeKind, TDefaultEdge { class DefaultEdge extends EdgeKind, TDefaultEdge {
override final string toString() { override final string toString() {
result = "Default" result = "Default"
} }
} }
DefaultEdge defaultEdge() { DefaultEdge defaultEdge() {
result = TDefaultEdge() result = TDefaultEdge()
} }
/** /**
* A "case" edge, representing the successor of a `Switch` instruction when the * A "case" edge, representing the successor of a `Switch` instruction when the
* the condition value matches a correponding `case` label. * the condition value matches a correponding `case` label.
*/ */
class CaseEdge extends EdgeKind, TCaseEdge { class CaseEdge extends EdgeKind, TCaseEdge {
string minValue; string minValue;
string maxValue; string maxValue;
CaseEdge() { CaseEdge() {
this = TCaseEdge(minValue, maxValue) this = TCaseEdge(minValue, maxValue)
} }
override final string toString() { override final string toString() {
if minValue = maxValue then if minValue = maxValue then
result = "Case[" + minValue + "]" result = "Case[" + minValue + "]"
else else
result = "Case[" + minValue + ".." + maxValue + "]" result = "Case[" + minValue + ".." + maxValue + "]"
} }
string getMinValue() { string getMinValue() {
result = minValue result = minValue
} }
string getMaxValue() { string getMaxValue() {
result = maxValue result = maxValue
} }
} }
CaseEdge caseEdge(string minValue, string maxValue) { CaseEdge caseEdge(string minValue, string maxValue) {
result = TCaseEdge(minValue, maxValue) result = TCaseEdge(minValue, maxValue)
} }
private predicate hasCaseEdge(SwitchCase switchCase, string minValue, private predicate hasCaseEdge(SwitchCase switchCase, string minValue,
string maxValue) { string maxValue) {
minValue = switchCase.getExpr().getFullyConverted().getValue() and minValue = switchCase.getExpr().getFullyConverted().getValue() and
if exists(switchCase.getEndExpr()) then if exists(switchCase.getEndExpr()) then
maxValue = switchCase.getEndExpr().getFullyConverted().getValue() maxValue = switchCase.getEndExpr().getFullyConverted().getValue()
else else
maxValue = minValue maxValue = minValue
} }
EdgeKind getCaseEdge(SwitchCase switchCase) { EdgeKind getCaseEdge(SwitchCase switchCase) {
exists(CaseEdge edge | exists(CaseEdge edge |
result = edge and result = edge and
hasCaseEdge(switchCase, edge.getMinValue(), edge.getMaxValue()) hasCaseEdge(switchCase, edge.getMinValue(), edge.getMaxValue())
) or ) or
(switchCase instanceof DefaultCase and result instanceof DefaultEdge) (switchCase instanceof DefaultCase and result instanceof DefaultEdge)
} }

View File

@@ -1 +1 @@
import internal.IRImpl import internal.IRImpl

View File

@@ -1,54 +1,54 @@
import cpp import cpp
newtype TMemoryAccessKind = newtype TMemoryAccessKind =
TIndirectMemoryAccess() or TIndirectMemoryAccess() or
TEscapedMemoryAccess() or TEscapedMemoryAccess() or
TPhiMemoryAccess() or TPhiMemoryAccess() or
TUnmodeledMemoryAccess() TUnmodeledMemoryAccess()
/** /**
* Describes the set of memory locations memory accessed by a memory operand or * Describes the set of memory locations memory accessed by a memory operand or
* memory result. * memory result.
*/ */
class MemoryAccessKind extends TMemoryAccessKind { class MemoryAccessKind extends TMemoryAccessKind {
abstract string toString(); abstract string toString();
} }
/** /**
* The operand or result accesses memory at the address specified by the * The operand or result accesses memory at the address specified by the
* `LoadStoreAddressOperand` on the same instruction. * `LoadStoreAddressOperand` on the same instruction.
*/ */
class IndirectMemoryAccess extends MemoryAccessKind, TIndirectMemoryAccess { class IndirectMemoryAccess extends MemoryAccessKind, TIndirectMemoryAccess {
override string toString() { override string toString() {
result = "indirect" result = "indirect"
} }
} }
/** /**
* The operand or result accesses all memory whose address has escaped. * The operand or result accesses all memory whose address has escaped.
*/ */
class EscapedMemoryAccess extends MemoryAccessKind, TEscapedMemoryAccess { class EscapedMemoryAccess extends MemoryAccessKind, TEscapedMemoryAccess {
override string toString() { override string toString() {
result = "escaped" result = "escaped"
} }
} }
/** /**
* The operand is a Phi operand, which accesses the same memory as its * The operand is a Phi operand, which accesses the same memory as its
* definition. * definition.
*/ */
class PhiMemoryAccess extends MemoryAccessKind, TPhiMemoryAccess { class PhiMemoryAccess extends MemoryAccessKind, TPhiMemoryAccess {
override string toString() { override string toString() {
result = "phi" result = "phi"
} }
} }
/** /**
* The operand accesses memory not modeled in SSA. Used only on the result of * The operand accesses memory not modeled in SSA. Used only on the result of
* `UnmodeledDefinition` and on the operands of `UnmodeledUse`. * `UnmodeledDefinition` and on the operands of `UnmodeledUse`.
*/ */
class UnmodeledMemoryAccess extends MemoryAccessKind, TUnmodeledMemoryAccess { class UnmodeledMemoryAccess extends MemoryAccessKind, TUnmodeledMemoryAccess {
override string toString() { override string toString() {
result = "unmodeled" result = "unmodeled"
} }
} }

View File

@@ -1 +1 @@
import internal.Opcode import internal.Opcode

View File

@@ -1,8 +1,8 @@
/** /**
* @name Print IR * @name Print IR
* @description Outputs a representation of the IR graph * @description Outputs a representation of the IR graph
* @id cpp/print-ir * @id cpp/print-ir
* @kind graph * @kind graph
*/ */
import PrintIR import PrintIR

View File

@@ -1 +1 @@
import internal.PrintIRImpl import internal.PrintIRImpl

View File

@@ -1,8 +1,8 @@
import cpp import cpp
private import internal.TempVariableTag private import internal.TempVariableTag
class TempVariableTag extends TTempVariableTag { class TempVariableTag extends TTempVariableTag {
string toString() { string toString() {
result = "Tag" result = "Tag"
} }
} }

View File

@@ -1,44 +1,44 @@
import cpp import cpp
private newtype TValueCategory = private newtype TValueCategory =
TLValue() or TLValue() or
TXValue() or TXValue() or
TPRValue() TPRValue()
abstract class ValueCategory extends TValueCategory { abstract class ValueCategory extends TValueCategory {
abstract string toString(); abstract string toString();
} }
abstract class GLValue extends ValueCategory { abstract class GLValue extends ValueCategory {
} }
abstract class RValue extends ValueCategory { abstract class RValue extends ValueCategory {
} }
class LValue extends GLValue, TLValue { class LValue extends GLValue, TLValue {
override string toString() { override string toString() {
result = "lvalue" result = "lvalue"
} }
} }
class XValue extends GLValue, RValue, TXValue { class XValue extends GLValue, RValue, TXValue {
override string toString() { override string toString() {
result = "xvalue" result = "xvalue"
} }
} }
class PRValue extends RValue, TPRValue { class PRValue extends RValue, TPRValue {
override string toString() { override string toString() {
result = "prvalue" result = "prvalue"
} }
} }
ValueCategory getExprValueCategory(Expr expr) { ValueCategory getExprValueCategory(Expr expr) {
( (
expr.isLValueCategory() and result instanceof LValue expr.isLValueCategory() and result instanceof LValue
) or ( ) or (
expr.isXValueCategory() and result instanceof XValue expr.isXValueCategory() and result instanceof XValue
) or ( ) or (
expr.isPRValueCategory() and result instanceof PRValue expr.isPRValueCategory() and result instanceof PRValue
) )
} }

View File

@@ -1,97 +1,97 @@
private import IRInternal private import IRInternal
import Instruction import Instruction
import cpp import cpp
private newtype TFunctionIR = private newtype TFunctionIR =
MkFunctionIR(Function func) { MkFunctionIR(Function func) {
Construction::functionHasIR(func) Construction::functionHasIR(func)
} }
/** /**
* Represents the IR for a function. * Represents the IR for a function.
*/ */
class FunctionIR extends TFunctionIR { class FunctionIR extends TFunctionIR {
Function func; Function func;
FunctionIR() { FunctionIR() {
this = MkFunctionIR(func) this = MkFunctionIR(func)
} }
final string toString() { final string toString() {
result = "IR: " + func.toString() result = "IR: " + func.toString()
} }
/** /**
* Gets the function whose IR is represented. * Gets the function whose IR is represented.
*/ */
final Function getFunction() { final Function getFunction() {
result = func result = func
} }
/** /**
* Gets the location of the function. * Gets the location of the function.
*/ */
final Location getLocation() { final Location getLocation() {
result = func.getLocation() result = func.getLocation()
} }
/** /**
* Gets the entry point for this function. * Gets the entry point for this function.
*/ */
pragma[noinline] pragma[noinline]
final EnterFunctionInstruction getEnterFunctionInstruction() { final EnterFunctionInstruction getEnterFunctionInstruction() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
/** /**
* Gets the exit point for this function. * Gets the exit point for this function.
*/ */
pragma[noinline] pragma[noinline]
final ExitFunctionInstruction getExitFunctionInstruction() { final ExitFunctionInstruction getExitFunctionInstruction() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
pragma[noinline] pragma[noinline]
final UnmodeledDefinitionInstruction getUnmodeledDefinitionInstruction() { final UnmodeledDefinitionInstruction getUnmodeledDefinitionInstruction() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
/** /**
* Gets the single return instruction for this function. * Gets the single return instruction for this function.
*/ */
pragma[noinline] pragma[noinline]
final ReturnInstruction getReturnInstruction() { final ReturnInstruction getReturnInstruction() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
/** /**
* Gets the variable used to hold the return value of this function. If this * Gets the variable used to hold the return value of this function. If this
* function does not return a value, this predicate does not hold. * function does not return a value, this predicate does not hold.
*/ */
pragma[noinline] pragma[noinline]
final IRReturnVariable getReturnVariable() { final IRReturnVariable getReturnVariable() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
/** /**
* Gets the block containing the entry point of this function. * Gets the block containing the entry point of this function.
*/ */
pragma[noinline] pragma[noinline]
final IRBlock getEntryBlock() { final IRBlock getEntryBlock() {
result.getFirstInstruction() = getEnterFunctionInstruction() result.getFirstInstruction() = getEnterFunctionInstruction()
} }
/** /**
* Gets all instructions in this function. * Gets all instructions in this function.
*/ */
final Instruction getAnInstruction() { final Instruction getAnInstruction() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
/** /**
* Gets all blocks in this function. * Gets all blocks in this function.
*/ */
final IRBlock getABlock() { final IRBlock getABlock() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
} }

View File

@@ -1,165 +1,165 @@
import cpp import cpp
import semmle.code.cpp.ir.IR import semmle.code.cpp.ir.IR
private import InstructionTag private import InstructionTag
private import TempVariableTag private import TempVariableTag
private import TranslatedElement private import TranslatedElement
private import TranslatedFunction private import TranslatedFunction
class InstructionTagType extends TInstructionTag { class InstructionTagType extends TInstructionTag {
final string toString() { final string toString() {
result = "Tag" result = "Tag"
} }
} }
private TranslatedElement getInstructionTranslatedElement( private TranslatedElement getInstructionTranslatedElement(
Instruction instruction) { Instruction instruction) {
result = getInstructionTranslatedElementAndTag(instruction, _) result = getInstructionTranslatedElementAndTag(instruction, _)
} }
private TranslatedElement getInstructionTranslatedElementAndTag( private TranslatedElement getInstructionTranslatedElementAndTag(
Instruction instruction, InstructionTag tag) { Instruction instruction, InstructionTag tag) {
result.getAST() = instruction.getAST() and result.getAST() = instruction.getAST() and
tag = instruction.getTag() and tag = instruction.getTag() and
result.hasInstruction(_, tag, _, _) result.hasInstruction(_, tag, _, _)
} }
private TranslatedElement getTempVariableTranslatedElement( private TranslatedElement getTempVariableTranslatedElement(
IRTempVariable var) { IRTempVariable var) {
result.getAST() = var.getAST() and result.getAST() = var.getAST() and
result.hasTempVariable(var.getTag(), _) result.hasTempVariable(var.getTag(), _)
} }
import Cached import Cached
cached private module Cached { cached private module Cached {
cached predicate functionHasIR(Function func) { cached predicate functionHasIR(Function func) {
exists(getTranslatedFunction(func)) exists(getTranslatedFunction(func))
} }
cached int getMaxCallArgIndex() { cached int getMaxCallArgIndex() {
result = max(int argIndex | result = max(int argIndex |
exists(FunctionCall call | exists(FunctionCall call |
exists(call.getArgument(argIndex)) exists(call.getArgument(argIndex))
) )
) )
} }
cached newtype TInstruction = cached newtype TInstruction =
MkInstruction(FunctionIR funcIR, Opcode opcode, Locatable ast, MkInstruction(FunctionIR funcIR, Opcode opcode, Locatable ast,
InstructionTag tag, Type resultType, boolean isGLValue) { InstructionTag tag, Type resultType, boolean isGLValue) {
hasInstruction(funcIR.getFunction(), opcode, ast, tag, hasInstruction(funcIR.getFunction(), opcode, ast, tag,
resultType, isGLValue) resultType, isGLValue)
} }
private predicate hasInstruction(Function func, Opcode opcode, Locatable ast, private predicate hasInstruction(Function func, Opcode opcode, Locatable ast,
InstructionTag tag, Type resultType, boolean isGLValue) { InstructionTag tag, Type resultType, boolean isGLValue) {
exists(TranslatedElement element | exists(TranslatedElement element |
element.getAST() = ast and element.getAST() = ast and
func = element.getFunction() and func = element.getFunction() and
element.hasInstruction(opcode, tag, resultType, isGLValue) element.hasInstruction(opcode, tag, resultType, isGLValue)
) )
} }
cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag,
Type type) { Type type) {
exists(TranslatedElement element | exists(TranslatedElement element |
element.getAST() = ast and element.getAST() = ast and
func = element.getFunction() and func = element.getFunction() and
element.hasTempVariable(tag, type) element.hasTempVariable(tag, type)
) )
} }
cached predicate hasModeledMemoryResult(Instruction instruction) { cached predicate hasModeledMemoryResult(Instruction instruction) {
none() none()
} }
cached Instruction getInstructionOperand(Instruction instruction, OperandTag tag) { cached Instruction getInstructionOperand(Instruction instruction, OperandTag tag) {
result = getInstructionTranslatedElement(instruction).getInstructionOperand( result = getInstructionTranslatedElement(instruction).getInstructionOperand(
instruction.getTag(), tag) instruction.getTag(), tag)
} }
cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) { cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) {
none() none()
} }
cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) { cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
result = getInstructionTranslatedElement(instruction).getInstructionSuccessor( result = getInstructionTranslatedElement(instruction).getInstructionSuccessor(
instruction.getTag(), kind) instruction.getTag(), kind)
} }
cached IRVariable getInstructionVariable(Instruction instruction) { cached IRVariable getInstructionVariable(Instruction instruction) {
result = getInstructionTranslatedElement(instruction).getInstructionVariable( result = getInstructionTranslatedElement(instruction).getInstructionVariable(
instruction.getTag()) instruction.getTag())
} }
cached Field getInstructionField(Instruction instruction) { cached Field getInstructionField(Instruction instruction) {
exists(TranslatedElement element, InstructionTag tag | exists(TranslatedElement element, InstructionTag tag |
instructionOrigin(instruction, element, tag) and instructionOrigin(instruction, element, tag) and
result = element.getInstructionField(tag) result = element.getInstructionField(tag)
) )
} }
cached Function getInstructionFunction(Instruction instruction) { cached Function getInstructionFunction(Instruction instruction) {
exists(InstructionTag tag | exists(InstructionTag tag |
result = getInstructionTranslatedElementAndTag(instruction, tag) result = getInstructionTranslatedElementAndTag(instruction, tag)
.getInstructionFunction(tag) .getInstructionFunction(tag)
) )
} }
cached string getInstructionConstantValue(Instruction instruction) { cached string getInstructionConstantValue(Instruction instruction) {
result = result =
getInstructionTranslatedElement(instruction).getInstructionConstantValue( getInstructionTranslatedElement(instruction).getInstructionConstantValue(
instruction.getTag()) instruction.getTag())
} }
cached StringLiteral getInstructionStringLiteral(Instruction instruction) { cached StringLiteral getInstructionStringLiteral(Instruction instruction) {
result = result =
getInstructionTranslatedElement(instruction).getInstructionStringLiteral( getInstructionTranslatedElement(instruction).getInstructionStringLiteral(
instruction.getTag()) instruction.getTag())
} }
cached Type getInstructionExceptionType(Instruction instruction) { cached Type getInstructionExceptionType(Instruction instruction) {
result = result =
getInstructionTranslatedElement(instruction).getInstructionExceptionType( getInstructionTranslatedElement(instruction).getInstructionExceptionType(
instruction.getTag()) instruction.getTag())
} }
cached predicate getInstructionInheritance(Instruction instruction, cached predicate getInstructionInheritance(Instruction instruction,
Class baseClass, Class derivedClass) { Class baseClass, Class derivedClass) {
getInstructionTranslatedElement(instruction).getInstructionInheritance( getInstructionTranslatedElement(instruction).getInstructionInheritance(
instruction.getTag(), baseClass, derivedClass) instruction.getTag(), baseClass, derivedClass)
} }
pragma[noinline] pragma[noinline]
private predicate instructionOrigin(Instruction instruction, private predicate instructionOrigin(Instruction instruction,
TranslatedElement element, InstructionTag tag) { TranslatedElement element, InstructionTag tag) {
element = getInstructionTranslatedElement(instruction) and element = getInstructionTranslatedElement(instruction) and
tag = instruction.getTag() tag = instruction.getTag()
} }
cached int getInstructionElementSize(Instruction instruction) { cached int getInstructionElementSize(Instruction instruction) {
exists(TranslatedElement element, InstructionTag tag | exists(TranslatedElement element, InstructionTag tag |
instructionOrigin(instruction, element, tag) and instructionOrigin(instruction, element, tag) and
result = element.getInstructionElementSize(tag) result = element.getInstructionElementSize(tag)
) )
} }
cached int getInstructionResultSize(Instruction instruction) { cached int getInstructionResultSize(Instruction instruction) {
exists(TranslatedElement element, InstructionTag tag | exists(TranslatedElement element, InstructionTag tag |
instructionOrigin(instruction, element, tag) and instructionOrigin(instruction, element, tag) and
result = element.getInstructionResultSize(tag) result = element.getInstructionResultSize(tag)
) )
} }
} }
import CachedForDebugging import CachedForDebugging
cached private module CachedForDebugging { cached private module CachedForDebugging {
cached string getTempVariableUniqueId(IRTempVariable var) { cached string getTempVariableUniqueId(IRTempVariable var) {
result = getTempVariableTranslatedElement(var).getId() + ":" + result = getTempVariableTranslatedElement(var).getId() + ":" +
getTempVariableTagId(var.getTag()) getTempVariableTagId(var.getTag())
} }
cached string getInstructionUniqueId(Instruction instruction) { cached string getInstructionUniqueId(Instruction instruction) {
result = getInstructionTranslatedElement(instruction).getId() + ":" + result = getInstructionTranslatedElement(instruction).getId() + ":" +
getInstructionTagId(instruction.getTag()) getInstructionTagId(instruction.getTag())
} }
} }

View File

@@ -1 +1 @@
import IRConstruction as Construction import IRConstruction as Construction

View File

@@ -1,3 +1,3 @@
private import IRImpl private import IRImpl
import InstructionSanity import InstructionSanity

View File

@@ -1,202 +1,202 @@
private import IRInternal private import IRInternal
import FunctionIR import FunctionIR
import cpp import cpp
import semmle.code.cpp.ir.TempVariableTag import semmle.code.cpp.ir.TempVariableTag
private import semmle.code.cpp.ir.internal.TempVariableTag private import semmle.code.cpp.ir.internal.TempVariableTag
private newtype TIRVariable = private newtype TIRVariable =
TIRAutomaticUserVariable(LocalScopeVariable var, FunctionIR funcIR) { TIRAutomaticUserVariable(LocalScopeVariable var, FunctionIR funcIR) {
exists(Function func | exists(Function func |
func = funcIR.getFunction() and func = funcIR.getFunction() and
( (
var.getFunction() = func or var.getFunction() = func or
var.(Parameter).getCatchBlock().getEnclosingFunction() = func var.(Parameter).getCatchBlock().getEnclosingFunction() = func
) )
) )
} or } or
TIRStaticUserVariable(Variable var, FunctionIR funcIR) { TIRStaticUserVariable(Variable var, FunctionIR funcIR) {
( (
var instanceof GlobalOrNamespaceVariable or var instanceof GlobalOrNamespaceVariable or
var instanceof MemberVariable and not var instanceof Field var instanceof MemberVariable and not var instanceof Field
) and ) and
exists(VariableAccess access | exists(VariableAccess access |
access.getTarget() = var and access.getTarget() = var and
access.getEnclosingFunction() = funcIR.getFunction() access.getEnclosingFunction() = funcIR.getFunction()
) )
} or } or
TIRTempVariable(FunctionIR funcIR, Locatable ast, TempVariableTag tag, TIRTempVariable(FunctionIR funcIR, Locatable ast, TempVariableTag tag,
Type type) { Type type) {
Construction::hasTempVariable(funcIR.getFunction(), ast, tag, type) Construction::hasTempVariable(funcIR.getFunction(), ast, tag, type)
} }
IRUserVariable getIRUserVariable(Function func, Variable var) { IRUserVariable getIRUserVariable(Function func, Variable var) {
result.getVariable() = var and result.getVariable() = var and
result.getFunction() = func result.getFunction() = func
} }
/** /**
* Represents a variable referenced by the IR for a function. The variable may * Represents a variable referenced by the IR for a function. The variable may
* be a user-declared variable (`IRUserVariable`) or a temporary variable * be a user-declared variable (`IRUserVariable`) or a temporary variable
* generated by the AST-to-IR translation (`IRTempVariable`). * generated by the AST-to-IR translation (`IRTempVariable`).
*/ */
abstract class IRVariable extends TIRVariable { abstract class IRVariable extends TIRVariable {
FunctionIR funcIR; FunctionIR funcIR;
abstract string toString(); abstract string toString();
/** /**
* Gets the type of the variable. * Gets the type of the variable.
*/ */
abstract Type getType(); abstract Type getType();
/** /**
* Gets the AST node that declared this variable, or that introduced this * Gets the AST node that declared this variable, or that introduced this
* variable as part of the AST-to-IR translation. * variable as part of the AST-to-IR translation.
*/ */
abstract Locatable getAST(); abstract Locatable getAST();
/** /**
* Gets an identifier string for the variable. This identifier is unique * Gets an identifier string for the variable. This identifier is unique
* within the function. * within the function.
*/ */
abstract string getUniqueId(); abstract string getUniqueId();
/** /**
* Gets the source location of this variable. * Gets the source location of this variable.
*/ */
final Location getLocation() { final Location getLocation() {
result = getAST().getLocation() result = getAST().getLocation()
} }
/** /**
* Gets the IR for the function that references this variable. * Gets the IR for the function that references this variable.
*/ */
final FunctionIR getFunctionIR() { final FunctionIR getFunctionIR() {
result = funcIR result = funcIR
} }
/** /**
* Gets the function that references this variable. * Gets the function that references this variable.
*/ */
final Function getFunction() { final Function getFunction() {
result = funcIR.getFunction() result = funcIR.getFunction()
} }
} }
/** /**
* Represents a user-declared variable referenced by the IR for a function. * Represents a user-declared variable referenced by the IR for a function.
*/ */
abstract class IRUserVariable extends IRVariable { abstract class IRUserVariable extends IRVariable {
Variable var; Variable var;
override final string toString() { override final string toString() {
result = var.toString() result = var.toString()
} }
override final Type getType() { override final Type getType() {
result = var.getType().getUnspecifiedType() result = var.getType().getUnspecifiedType()
} }
override final Locatable getAST() { override final Locatable getAST() {
result = var result = var
} }
override final string getUniqueId() { override final string getUniqueId() {
result = var.toString() + " " + var.getLocation().toString() result = var.toString() + " " + var.getLocation().toString()
} }
/** /**
* Gets the original user-declared variable. * Gets the original user-declared variable.
*/ */
final Variable getVariable() { final Variable getVariable() {
result = var result = var
} }
} }
/** /**
* Represents a variable (user-declared or temporary) that is allocated on the * Represents a variable (user-declared or temporary) that is allocated on the
* stack. This includes all parameters, non-static local variables, and * stack. This includes all parameters, non-static local variables, and
* temporary variables. * temporary variables.
*/ */
abstract class IRAutomaticVariable extends IRVariable { abstract class IRAutomaticVariable extends IRVariable {
} }
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable, class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable,
TIRAutomaticUserVariable { TIRAutomaticUserVariable {
LocalScopeVariable localVar; LocalScopeVariable localVar;
IRAutomaticUserVariable() { IRAutomaticUserVariable() {
this = TIRAutomaticUserVariable(localVar, funcIR) and this = TIRAutomaticUserVariable(localVar, funcIR) and
var = localVar var = localVar
} }
final LocalScopeVariable getLocalVariable() { final LocalScopeVariable getLocalVariable() {
result = localVar result = localVar
} }
} }
class IRStaticUserVariable extends IRUserVariable, TIRStaticUserVariable { class IRStaticUserVariable extends IRUserVariable, TIRStaticUserVariable {
IRStaticUserVariable() { IRStaticUserVariable() {
this = TIRStaticUserVariable(var, funcIR) this = TIRStaticUserVariable(var, funcIR)
} }
} }
IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) { IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) {
result.getAST() = ast and result.getAST() = ast and
result.getTag() = tag result.getTag() = tag
} }
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
Locatable ast; Locatable ast;
TempVariableTag tag; TempVariableTag tag;
Type type; Type type;
IRTempVariable() { IRTempVariable() {
this = TIRTempVariable(funcIR, ast, tag, type) this = TIRTempVariable(funcIR, ast, tag, type)
} }
override final Type getType() { override final Type getType() {
result = type result = type
} }
override final Locatable getAST() { override final Locatable getAST() {
result = ast result = ast
} }
override final string getUniqueId() { override final string getUniqueId() {
result = "Temp: " + Construction::getTempVariableUniqueId(this) result = "Temp: " + Construction::getTempVariableUniqueId(this)
} }
final TempVariableTag getTag() { final TempVariableTag getTag() {
result = tag result = tag
} }
override string toString() { override string toString() {
result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" +
ast.getLocation().getStartColumn().toString() ast.getLocation().getStartColumn().toString()
} }
string getBaseString() { string getBaseString() {
result = "#temp" result = "#temp"
} }
} }
class IRReturnVariable extends IRTempVariable { class IRReturnVariable extends IRTempVariable {
IRReturnVariable() { IRReturnVariable() {
tag = ReturnValueTempVar() tag = ReturnValueTempVar()
} }
override final string toString() { override final string toString() {
result = "#return" result = "#return"
} }
} }
class IRThrowVariable extends IRTempVariable { class IRThrowVariable extends IRTempVariable {
IRThrowVariable() { IRThrowVariable() {
tag = ThrowTempVar() tag = ThrowTempVar()
} }
override string getBaseString() { override string getBaseString() {
result = "#throw" result = "#throw"
} }
} }

View File

@@ -1,152 +1,152 @@
import cpp import cpp
private predicate fieldIsInitialized(Field field) { private predicate fieldIsInitialized(Field field) {
exists(ClassAggregateLiteral initList | exists(ClassAggregateLiteral initList |
initList.isInitialized(field) initList.isInitialized(field)
) or ) or
exists(ConstructorFieldInit init | exists(ConstructorFieldInit init |
field = init.getTarget() field = init.getTarget()
) )
} }
private predicate elementIsInitialized(int elementIndex) { private predicate elementIsInitialized(int elementIndex) {
exists(ArrayAggregateLiteral initList | exists(ArrayAggregateLiteral initList |
initList.isInitialized(elementIndex) initList.isInitialized(elementIndex)
) )
} }
newtype TInstructionTag = newtype TInstructionTag =
OnlyInstructionTag() or // Single instruction (not including implicit Load) OnlyInstructionTag() or // Single instruction (not including implicit Load)
InitializeThisTag() or InitializeThisTag() or
InitializerVariableAddressTag() or InitializerVariableAddressTag() or
InitializerLoadStringTag() or InitializerLoadStringTag() or
InitializerStoreTag() or InitializerStoreTag() or
ZeroPadStringConstantTag() or ZeroPadStringConstantTag() or
ZeroPadStringElementIndexTag() or ZeroPadStringElementIndexTag() or
ZeroPadStringElementAddressTag() or ZeroPadStringElementAddressTag() or
ZeroPadStringStoreTag() or ZeroPadStringStoreTag() or
AssignOperationLoadTag() or AssignOperationLoadTag() or
AssignOperationConvertLeftTag() or AssignOperationConvertLeftTag() or
AssignOperationOpTag() or AssignOperationOpTag() or
AssignOperationConvertResultTag() or AssignOperationConvertResultTag() or
AssignmentStoreTag() or AssignmentStoreTag() or
CrementLoadTag() or CrementLoadTag() or
CrementConstantTag() or CrementConstantTag() or
CrementOpTag() or CrementOpTag() or
CrementStoreTag() or CrementStoreTag() or
EnterFunctionTag() or EnterFunctionTag() or
ReturnValueAddressTag() or ReturnValueAddressTag() or
ReturnTag() or ReturnTag() or
ExitFunctionTag() or ExitFunctionTag() or
UnmodeledDefinitionTag() or UnmodeledDefinitionTag() or
UnmodeledUseTag() or UnmodeledUseTag() or
SwitchBranchTag() or SwitchBranchTag() or
CallTargetTag() or CallTargetTag() or
CallTag() or CallTag() or
AllocationSizeTag() or AllocationSizeTag() or
AllocationElementSizeTag() or AllocationElementSizeTag() or
AllocationExtentConvertTag() or AllocationExtentConvertTag() or
ValueConditionConditionalBranchTag() or ValueConditionConditionalBranchTag() or
ConditionValueTrueTempAddressTag() or ConditionValueTrueTempAddressTag() or
ConditionValueTrueConstantTag() or ConditionValueTrueConstantTag() or
ConditionValueTrueStoreTag() or ConditionValueTrueStoreTag() or
ConditionValueFalseTempAddressTag() or ConditionValueFalseTempAddressTag() or
ConditionValueFalseConstantTag() or ConditionValueFalseConstantTag() or
ConditionValueFalseStoreTag() or ConditionValueFalseStoreTag() or
ConditionValueResultTempAddressTag() or ConditionValueResultTempAddressTag() or
ConditionValueResultLoadTag() or ConditionValueResultLoadTag() or
BoolConversionConstantTag() or BoolConversionConstantTag() or
BoolConversionCompareTag() or BoolConversionCompareTag() or
LoadTag() or // Implicit load due to lvalue-to-rvalue conversion LoadTag() or // Implicit load due to lvalue-to-rvalue conversion
CatchTag() or CatchTag() or
ThrowTag() or ThrowTag() or
UnwindTag() or UnwindTag() or
InitializerFieldAddressTag(Field field) { InitializerFieldAddressTag(Field field) {
fieldIsInitialized(field) fieldIsInitialized(field)
} or } or
InitializerFieldDefaultValueTag(Field field) { InitializerFieldDefaultValueTag(Field field) {
fieldIsInitialized(field) fieldIsInitialized(field)
} or } or
InitializerFieldDefaultValueStoreTag(Field field) { InitializerFieldDefaultValueStoreTag(Field field) {
fieldIsInitialized(field) fieldIsInitialized(field)
} or } or
InitializerElementIndexTag(int elementIndex) { InitializerElementIndexTag(int elementIndex) {
elementIsInitialized(elementIndex) elementIsInitialized(elementIndex)
} or } or
InitializerElementAddressTag(int elementIndex) { InitializerElementAddressTag(int elementIndex) {
elementIsInitialized(elementIndex) elementIsInitialized(elementIndex)
} or } or
InitializerElementDefaultValueTag(int elementIndex) { InitializerElementDefaultValueTag(int elementIndex) {
elementIsInitialized(elementIndex) elementIsInitialized(elementIndex)
} or } or
InitializerElementDefaultValueStoreTag(int elementIndex) { InitializerElementDefaultValueStoreTag(int elementIndex) {
elementIsInitialized(elementIndex) elementIsInitialized(elementIndex)
} }
/** /**
* Gets a unique string for the instruction tag. Primarily used for generating * Gets a unique string for the instruction tag. Primarily used for generating
* instruction IDs to ensure stable IR dumps. * instruction IDs to ensure stable IR dumps.
*/ */
string getInstructionTagId(TInstructionTag tag) { string getInstructionTagId(TInstructionTag tag) {
tag = OnlyInstructionTag() and result = "Only" or // Single instruction (not including implicit Load) tag = OnlyInstructionTag() and result = "Only" or // Single instruction (not including implicit Load)
tag = InitializerVariableAddressTag() and result = "InitVarAddr" or tag = InitializerVariableAddressTag() and result = "InitVarAddr" or
tag = InitializerStoreTag() and result = "InitStore" or tag = InitializerStoreTag() and result = "InitStore" or
tag = ZeroPadStringConstantTag() and result = "ZeroPadConst" or tag = ZeroPadStringConstantTag() and result = "ZeroPadConst" or
tag = ZeroPadStringElementIndexTag() and result = "ZeroPadElemIndex" or tag = ZeroPadStringElementIndexTag() and result = "ZeroPadElemIndex" or
tag = ZeroPadStringElementAddressTag() and result = "ZeroPadElemAddr" or tag = ZeroPadStringElementAddressTag() and result = "ZeroPadElemAddr" or
tag = ZeroPadStringStoreTag() and result = "ZeroPadStore" or tag = ZeroPadStringStoreTag() and result = "ZeroPadStore" or
tag = AssignOperationLoadTag() and result = "AssignOpLoad" or tag = AssignOperationLoadTag() and result = "AssignOpLoad" or
tag = AssignOperationConvertLeftTag() and result = "AssignOpConvLeft" or tag = AssignOperationConvertLeftTag() and result = "AssignOpConvLeft" or
tag = AssignOperationOpTag() and result = "AssignOpOp" or tag = AssignOperationOpTag() and result = "AssignOpOp" or
tag = AssignOperationConvertResultTag() and result = "AssignOpConvRes" or tag = AssignOperationConvertResultTag() and result = "AssignOpConvRes" or
tag = AssignmentStoreTag() and result = "AssignStore" or tag = AssignmentStoreTag() and result = "AssignStore" or
tag = CrementLoadTag() and result = "CrementLoad" or tag = CrementLoadTag() and result = "CrementLoad" or
tag = CrementConstantTag() and result = "CrementConst" or tag = CrementConstantTag() and result = "CrementConst" or
tag = CrementOpTag() and result = "CrementOp" or tag = CrementOpTag() and result = "CrementOp" or
tag = CrementStoreTag() and result = "CrementStore" or tag = CrementStoreTag() and result = "CrementStore" or
tag = EnterFunctionTag() and result = "EnterFunc" or tag = EnterFunctionTag() and result = "EnterFunc" or
tag = ReturnValueAddressTag() and result = "RetValAddr" or tag = ReturnValueAddressTag() and result = "RetValAddr" or
tag = ReturnTag() and result = "Ret" or tag = ReturnTag() and result = "Ret" or
tag = ExitFunctionTag() and result = "ExitFunc" or tag = ExitFunctionTag() and result = "ExitFunc" or
tag = UnmodeledDefinitionTag() and result = "UnmodeledDef" or tag = UnmodeledDefinitionTag() and result = "UnmodeledDef" or
tag = UnmodeledUseTag() and result = "UnmodeledUse" or tag = UnmodeledUseTag() and result = "UnmodeledUse" or
tag = SwitchBranchTag() and result = "SwitchBranch" or tag = SwitchBranchTag() and result = "SwitchBranch" or
tag = CallTargetTag() and result = "CallTarget" or tag = CallTargetTag() and result = "CallTarget" or
tag = CallTag() and result = "Call" or tag = CallTag() and result = "Call" or
tag = AllocationSizeTag() and result = "AllocSize" or tag = AllocationSizeTag() and result = "AllocSize" or
tag = AllocationElementSizeTag() and result = "AllocElemSize" or tag = AllocationElementSizeTag() and result = "AllocElemSize" or
tag = AllocationExtentConvertTag() and result = "AllocExtConv" or tag = AllocationExtentConvertTag() and result = "AllocExtConv" or
tag = ValueConditionConditionalBranchTag() and result = "ValCondCondBranch" or tag = ValueConditionConditionalBranchTag() and result = "ValCondCondBranch" or
tag = ConditionValueTrueTempAddressTag() and result = "CondValTrueTempAddr" or tag = ConditionValueTrueTempAddressTag() and result = "CondValTrueTempAddr" or
tag = ConditionValueTrueConstantTag() and result = "CondValTrueConst" or tag = ConditionValueTrueConstantTag() and result = "CondValTrueConst" or
tag = ConditionValueTrueStoreTag() and result = "CondValTrueStore" or tag = ConditionValueTrueStoreTag() and result = "CondValTrueStore" or
tag = ConditionValueFalseTempAddressTag() and result = "CondValFalseTempAddr" or tag = ConditionValueFalseTempAddressTag() and result = "CondValFalseTempAddr" or
tag = ConditionValueFalseConstantTag() and result = "CondValFalseConst" or tag = ConditionValueFalseConstantTag() and result = "CondValFalseConst" or
tag = ConditionValueFalseStoreTag() and result = "CondValFalseStore" or tag = ConditionValueFalseStoreTag() and result = "CondValFalseStore" or
tag = ConditionValueResultTempAddressTag() and result = "CondValResTempAddr" or tag = ConditionValueResultTempAddressTag() and result = "CondValResTempAddr" or
tag = ConditionValueResultLoadTag() and result = "CondValResLoad" or tag = ConditionValueResultLoadTag() and result = "CondValResLoad" or
tag = BoolConversionConstantTag() and result = "BoolConvConst" or tag = BoolConversionConstantTag() and result = "BoolConvConst" or
tag = BoolConversionCompareTag() and result = "BoolConvComp" or tag = BoolConversionCompareTag() and result = "BoolConvComp" or
tag = LoadTag() and result = "Load" or // Implicit load due to lvalue-to-rvalue conversion tag = LoadTag() and result = "Load" or // Implicit load due to lvalue-to-rvalue conversion
tag = CatchTag() and result = "Catch" or tag = CatchTag() and result = "Catch" or
tag = ThrowTag() and result = "Throw" or tag = ThrowTag() and result = "Throw" or
tag = UnwindTag() and result = "Unwind" or tag = UnwindTag() and result = "Unwind" or
exists(Field field, Class cls, int index, string tagName | exists(Field field, Class cls, int index, string tagName |
field = cls.getCanonicalMember(index) and field = cls.getCanonicalMember(index) and
( (
tag = InitializerFieldAddressTag(field) and tagName = "InitFieldAddr" or tag = InitializerFieldAddressTag(field) and tagName = "InitFieldAddr" or
tag = InitializerFieldDefaultValueTag(field) and tagName = "InitFieldDefVal" or tag = InitializerFieldDefaultValueTag(field) and tagName = "InitFieldDefVal" or
tag = InitializerFieldDefaultValueStoreTag(field) and tagName = "InitFieldDefValStore" tag = InitializerFieldDefaultValueStoreTag(field) and tagName = "InitFieldDefValStore"
) and ) and
result = tagName + "(" + index + ")" result = tagName + "(" + index + ")"
) or ) or
exists(int index, string tagName | exists(int index, string tagName |
( (
tag = InitializerElementIndexTag(index) and tagName = "InitElemIndex" or tag = InitializerElementIndexTag(index) and tagName = "InitElemIndex" or
tag = InitializerElementAddressTag(index) and tagName = "InitElemAddr" or tag = InitializerElementAddressTag(index) and tagName = "InitElemAddr" or
tag = InitializerElementDefaultValueTag(index) and tagName = "InitElemDefVal" or tag = InitializerElementDefaultValueTag(index) and tagName = "InitElemDefVal" or
tag = InitializerElementDefaultValueStoreTag(index) and tagName = "InitElemDefValStore" tag = InitializerElementDefaultValueStoreTag(index) and tagName = "InitElemDefValStore"
) and ) and
result = tagName + "(" + index + ")" result = tagName + "(" + index + ")"
) )
} }

View File

@@ -1,154 +1,154 @@
private newtype TOpcode = private newtype TOpcode =
TNoOp() or TNoOp() or
TUninitialized() or TUninitialized() or
TInitializeParameter() or TInitializeParameter() or
TInitializeThis() or TInitializeThis() or
TEnterFunction() or TEnterFunction() or
TExitFunction() or TExitFunction() or
TReturnValue() or TReturnValue() or
TReturnVoid() or TReturnVoid() or
TCopyValue() or TCopyValue() or
TLoad() or TLoad() or
TStore() or TStore() or
TAdd() or TAdd() or
TSub() or TSub() or
TMul() or TMul() or
TDiv() or TDiv() or
TRem() or TRem() or
TNegate() or TNegate() or
TShiftLeft() or TShiftLeft() or
TShiftRight() or TShiftRight() or
TBitAnd() or TBitAnd() or
TBitOr() or TBitOr() or
TBitXor() or TBitXor() or
TBitComplement() or TBitComplement() or
TLogicalNot() or TLogicalNot() or
TCompareEQ() or TCompareEQ() or
TCompareNE() or TCompareNE() or
TCompareLT() or TCompareLT() or
TCompareGT() or TCompareGT() or
TCompareLE() or TCompareLE() or
TCompareGE() or TCompareGE() or
TPointerAdd() or TPointerAdd() or
TPointerSub() or TPointerSub() or
TPointerDiff() or TPointerDiff() or
TConvert() or TConvert() or
TConvertToBase() or TConvertToBase() or
TConvertToVirtualBase() or TConvertToVirtualBase() or
TConvertToDerived() or TConvertToDerived() or
TCheckedConvertOrNull() or TCheckedConvertOrNull() or
TCheckedConvertOrThrow() or TCheckedConvertOrThrow() or
TDynamicCastToVoid() or TDynamicCastToVoid() or
TVariableAddress() or TVariableAddress() or
TFieldAddress() or TFieldAddress() or
TFunctionAddress() or TFunctionAddress() or
TConstant() or TConstant() or
TStringConstant() or TStringConstant() or
TConditionalBranch() or TConditionalBranch() or
TSwitch() or TSwitch() or
TInvoke() or TInvoke() or
TCatchByType() or TCatchByType() or
TCatchAny() or TCatchAny() or
TThrowValue() or TThrowValue() or
TReThrow() or TReThrow() or
TUnwind() or TUnwind() or
TUnmodeledDefinition() or TUnmodeledDefinition() or
TUnmodeledUse() or TUnmodeledUse() or
TPhi() or TPhi() or
TVarArgsStart() or TVarArgsStart() or
TVarArgsEnd() or TVarArgsEnd() or
TVarArg() or TVarArg() or
TVarArgCopy() TVarArgCopy()
class Opcode extends TOpcode { class Opcode extends TOpcode {
string toString() { string toString() {
result = "UnknownOpcode" result = "UnknownOpcode"
} }
} }
abstract class UnaryOpcode extends Opcode {} abstract class UnaryOpcode extends Opcode {}
abstract class BinaryOpcode extends Opcode {} abstract class BinaryOpcode extends Opcode {}
abstract class PointerArithmeticOpcode extends BinaryOpcode {} abstract class PointerArithmeticOpcode extends BinaryOpcode {}
abstract class PointerOffsetOpcode extends PointerArithmeticOpcode {} abstract class PointerOffsetOpcode extends PointerArithmeticOpcode {}
abstract class CompareOpcode extends BinaryOpcode {} abstract class CompareOpcode extends BinaryOpcode {}
abstract class CopyOpcode extends Opcode {} abstract class CopyOpcode extends Opcode {}
abstract class MemoryAccessOpcode extends Opcode {} abstract class MemoryAccessOpcode extends Opcode {}
abstract class ReturnOpcode extends Opcode {} abstract class ReturnOpcode extends Opcode {}
abstract class ThrowOpcode extends Opcode {} abstract class ThrowOpcode extends Opcode {}
abstract class CatchOpcode extends Opcode {} abstract class CatchOpcode extends Opcode {}
abstract class OpcodeWithCondition extends Opcode {} abstract class OpcodeWithCondition extends Opcode {}
abstract class BuiltInOpcode extends Opcode {} abstract class BuiltInOpcode extends Opcode {}
module Opcode { module Opcode {
class NoOp extends Opcode, TNoOp { override final string toString() { result = "NoOp" } } class NoOp extends Opcode, TNoOp { override final string toString() { result = "NoOp" } }
class Uninitialized extends MemoryAccessOpcode, TUninitialized { override final string toString() { result = "Uninitialized" } } class Uninitialized extends MemoryAccessOpcode, TUninitialized { override final string toString() { result = "Uninitialized" } }
class InitializeParameter extends MemoryAccessOpcode, TInitializeParameter { override final string toString() { result = "InitializeParameter" } } class InitializeParameter extends MemoryAccessOpcode, TInitializeParameter { override final string toString() { result = "InitializeParameter" } }
class InitializeThis extends Opcode, TInitializeThis { override final string toString() { result = "InitializeThis" } } class InitializeThis extends Opcode, TInitializeThis { override final string toString() { result = "InitializeThis" } }
class EnterFunction extends Opcode, TEnterFunction { override final string toString() { result = "EnterFunction" } } class EnterFunction extends Opcode, TEnterFunction { override final string toString() { result = "EnterFunction" } }
class ExitFunction extends Opcode, TExitFunction { override final string toString() { result = "ExitFunction" } } class ExitFunction extends Opcode, TExitFunction { override final string toString() { result = "ExitFunction" } }
class ReturnValue extends ReturnOpcode, MemoryAccessOpcode, TReturnValue { override final string toString() { result = "ReturnValue" } } class ReturnValue extends ReturnOpcode, MemoryAccessOpcode, TReturnValue { override final string toString() { result = "ReturnValue" } }
class ReturnVoid extends ReturnOpcode, TReturnVoid { override final string toString() { result = "ReturnVoid" } } class ReturnVoid extends ReturnOpcode, TReturnVoid { override final string toString() { result = "ReturnVoid" } }
class CopyValue extends CopyOpcode, TCopyValue { override final string toString() { result = "CopyValue" } } class CopyValue extends CopyOpcode, TCopyValue { override final string toString() { result = "CopyValue" } }
class Load extends CopyOpcode, MemoryAccessOpcode, TLoad { override final string toString() { result = "Load" } } class Load extends CopyOpcode, MemoryAccessOpcode, TLoad { override final string toString() { result = "Load" } }
class Store extends CopyOpcode, MemoryAccessOpcode, TStore { override final string toString() { result = "Store" } } class Store extends CopyOpcode, MemoryAccessOpcode, TStore { override final string toString() { result = "Store" } }
class Add extends BinaryOpcode, TAdd { override final string toString() { result = "Add" } } class Add extends BinaryOpcode, TAdd { override final string toString() { result = "Add" } }
class Sub extends BinaryOpcode, TSub { override final string toString() { result = "Sub" } } class Sub extends BinaryOpcode, TSub { override final string toString() { result = "Sub" } }
class Mul extends BinaryOpcode, TMul { override final string toString() { result = "Mul" } } class Mul extends BinaryOpcode, TMul { override final string toString() { result = "Mul" } }
class Div extends BinaryOpcode, TDiv { override final string toString() { result = "Div" } } class Div extends BinaryOpcode, TDiv { override final string toString() { result = "Div" } }
class Rem extends BinaryOpcode, TRem { override final string toString() { result = "Rem" } } class Rem extends BinaryOpcode, TRem { override final string toString() { result = "Rem" } }
class Negate extends UnaryOpcode, TNegate { override final string toString() { result = "Negate" } } class Negate extends UnaryOpcode, TNegate { override final string toString() { result = "Negate" } }
class ShiftLeft extends BinaryOpcode, TShiftLeft { override final string toString() { result = "ShiftLeft" } } class ShiftLeft extends BinaryOpcode, TShiftLeft { override final string toString() { result = "ShiftLeft" } }
class ShiftRight extends BinaryOpcode, TShiftRight { override final string toString() { result = "ShiftRight" } } class ShiftRight extends BinaryOpcode, TShiftRight { override final string toString() { result = "ShiftRight" } }
class BitAnd extends BinaryOpcode, TBitAnd { override final string toString() { result = "BitAnd" } } class BitAnd extends BinaryOpcode, TBitAnd { override final string toString() { result = "BitAnd" } }
class BitOr extends BinaryOpcode, TBitOr { override final string toString() { result = "BitOr" } } class BitOr extends BinaryOpcode, TBitOr { override final string toString() { result = "BitOr" } }
class BitXor extends BinaryOpcode, TBitXor { override final string toString() { result = "BitXor" } } class BitXor extends BinaryOpcode, TBitXor { override final string toString() { result = "BitXor" } }
class BitComplement extends UnaryOpcode, TBitComplement { override final string toString() { result = "BitComplement" } } class BitComplement extends UnaryOpcode, TBitComplement { override final string toString() { result = "BitComplement" } }
class LogicalNot extends UnaryOpcode, TLogicalNot { override final string toString() { result = "LogicalNot" } } class LogicalNot extends UnaryOpcode, TLogicalNot { override final string toString() { result = "LogicalNot" } }
class CompareEQ extends CompareOpcode, TCompareEQ { override final string toString() { result = "CompareEQ" } } class CompareEQ extends CompareOpcode, TCompareEQ { override final string toString() { result = "CompareEQ" } }
class CompareNE extends CompareOpcode, TCompareNE { override final string toString() { result = "CompareNE" } } class CompareNE extends CompareOpcode, TCompareNE { override final string toString() { result = "CompareNE" } }
class CompareLT extends CompareOpcode, TCompareLT { override final string toString() { result = "CompareLT" } } class CompareLT extends CompareOpcode, TCompareLT { override final string toString() { result = "CompareLT" } }
class CompareGT extends CompareOpcode, TCompareGT { override final string toString() { result = "CompareGT" } } class CompareGT extends CompareOpcode, TCompareGT { override final string toString() { result = "CompareGT" } }
class CompareLE extends CompareOpcode, TCompareLE { override final string toString() { result = "CompareLE" } } class CompareLE extends CompareOpcode, TCompareLE { override final string toString() { result = "CompareLE" } }
class CompareGE extends CompareOpcode, TCompareGE { override final string toString() { result = "CompareGE" } } class CompareGE extends CompareOpcode, TCompareGE { override final string toString() { result = "CompareGE" } }
class PointerAdd extends PointerOffsetOpcode, TPointerAdd { override final string toString() { result = "PointerAdd" } } class PointerAdd extends PointerOffsetOpcode, TPointerAdd { override final string toString() { result = "PointerAdd" } }
class PointerSub extends PointerOffsetOpcode, TPointerSub { override final string toString() { result = "PointerSub" } } class PointerSub extends PointerOffsetOpcode, TPointerSub { override final string toString() { result = "PointerSub" } }
class PointerDiff extends PointerArithmeticOpcode, TPointerDiff { override final string toString() { result = "PointerDiff" } } class PointerDiff extends PointerArithmeticOpcode, TPointerDiff { override final string toString() { result = "PointerDiff" } }
class Convert extends UnaryOpcode, TConvert { override final string toString() { result = "Convert" } } class Convert extends UnaryOpcode, TConvert { override final string toString() { result = "Convert" } }
class ConvertToBase extends UnaryOpcode, TConvertToBase { override final string toString() { result = "ConvertToBase" } } class ConvertToBase extends UnaryOpcode, TConvertToBase { override final string toString() { result = "ConvertToBase" } }
class ConvertToVirtualBase extends UnaryOpcode, TConvertToVirtualBase { override final string toString() { result = "ConvertToVirtualBase" } } class ConvertToVirtualBase extends UnaryOpcode, TConvertToVirtualBase { override final string toString() { result = "ConvertToVirtualBase" } }
class ConvertToDerived extends UnaryOpcode, TConvertToDerived { override final string toString() { result = "ConvertToDerived" } } class ConvertToDerived extends UnaryOpcode, TConvertToDerived { override final string toString() { result = "ConvertToDerived" } }
class CheckedConvertOrNull extends UnaryOpcode, TCheckedConvertOrNull { override final string toString() { result = "CheckedConvertOrNull" } } class CheckedConvertOrNull extends UnaryOpcode, TCheckedConvertOrNull { override final string toString() { result = "CheckedConvertOrNull" } }
class CheckedConvertOrThrow extends UnaryOpcode, TCheckedConvertOrThrow { override final string toString() { result = "CheckedConvertOrThrow" } } class CheckedConvertOrThrow extends UnaryOpcode, TCheckedConvertOrThrow { override final string toString() { result = "CheckedConvertOrThrow" } }
class DynamicCastToVoid extends UnaryOpcode, TDynamicCastToVoid { override final string toString() { result = "DynamicCastToVoid" } } class DynamicCastToVoid extends UnaryOpcode, TDynamicCastToVoid { override final string toString() { result = "DynamicCastToVoid" } }
class VariableAddress extends Opcode, TVariableAddress { override final string toString() { result = "VariableAddress" } } class VariableAddress extends Opcode, TVariableAddress { override final string toString() { result = "VariableAddress" } }
class FieldAddress extends UnaryOpcode, TFieldAddress { override final string toString() { result = "FieldAddress" } } class FieldAddress extends UnaryOpcode, TFieldAddress { override final string toString() { result = "FieldAddress" } }
class FunctionAddress extends Opcode, TFunctionAddress { override final string toString() { result = "FunctionAddress" } } class FunctionAddress extends Opcode, TFunctionAddress { override final string toString() { result = "FunctionAddress" } }
class Constant extends Opcode, TConstant { override final string toString() { result = "Constant" } } class Constant extends Opcode, TConstant { override final string toString() { result = "Constant" } }
class StringConstant extends Opcode, TStringConstant { override final string toString() { result = "StringConstant" } } class StringConstant extends Opcode, TStringConstant { override final string toString() { result = "StringConstant" } }
class ConditionalBranch extends OpcodeWithCondition, TConditionalBranch { override final string toString() { result = "ConditionalBranch" } } class ConditionalBranch extends OpcodeWithCondition, TConditionalBranch { override final string toString() { result = "ConditionalBranch" } }
class Switch extends OpcodeWithCondition, TSwitch { override final string toString() { result = "Switch" } } class Switch extends OpcodeWithCondition, TSwitch { override final string toString() { result = "Switch" } }
class Invoke extends Opcode, TInvoke { override final string toString() { result = "Invoke" } } class Invoke extends Opcode, TInvoke { override final string toString() { result = "Invoke" } }
class CatchByType extends CatchOpcode, TCatchByType { override final string toString() { result = "CatchByType" } } class CatchByType extends CatchOpcode, TCatchByType { override final string toString() { result = "CatchByType" } }
class CatchAny extends CatchOpcode, TCatchAny { override final string toString() { result = "CatchAny" } } class CatchAny extends CatchOpcode, TCatchAny { override final string toString() { result = "CatchAny" } }
class ThrowValue extends ThrowOpcode, MemoryAccessOpcode, TThrowValue { override final string toString() { result = "ThrowValue" } } class ThrowValue extends ThrowOpcode, MemoryAccessOpcode, TThrowValue { override final string toString() { result = "ThrowValue" } }
class ReThrow extends ThrowOpcode, TReThrow { override final string toString() { result = "ReThrow" } } class ReThrow extends ThrowOpcode, TReThrow { override final string toString() { result = "ReThrow" } }
class Unwind extends Opcode, TUnwind { override final string toString() { result = "Unwind" } } class Unwind extends Opcode, TUnwind { override final string toString() { result = "Unwind" } }
class UnmodeledDefinition extends Opcode, TUnmodeledDefinition { override final string toString() { result = "UnmodeledDefinition" } } class UnmodeledDefinition extends Opcode, TUnmodeledDefinition { override final string toString() { result = "UnmodeledDefinition" } }
class UnmodeledUse extends Opcode, TUnmodeledUse { override final string toString() { result = "UnmodeledUse" } } class UnmodeledUse extends Opcode, TUnmodeledUse { override final string toString() { result = "UnmodeledUse" } }
class Phi extends Opcode, TPhi { override final string toString() { result = "Phi" } } class Phi extends Opcode, TPhi { override final string toString() { result = "Phi" } }
class VarArgsStart extends BuiltInOpcode, TVarArgsStart { override final string toString() { result = "VarArgsStart" } } class VarArgsStart extends BuiltInOpcode, TVarArgsStart { override final string toString() { result = "VarArgsStart" } }
class VarArgsEnd extends BuiltInOpcode, TVarArgsEnd { override final string toString() { result = "VarArgsEnd" } } class VarArgsEnd extends BuiltInOpcode, TVarArgsEnd { override final string toString() { result = "VarArgsEnd" } }
class VarArg extends BuiltInOpcode, TVarArg { override final string toString() { result = "VarArg" } } class VarArg extends BuiltInOpcode, TVarArg { override final string toString() { result = "VarArg" } }
class VarArgCopy extends BuiltInOpcode, TVarArgCopy { override final string toString() { result = "VarArgCopy" } } class VarArgCopy extends BuiltInOpcode, TVarArgCopy { override final string toString() { result = "VarArgCopy" } }
} }

View File

@@ -1,12 +1,12 @@
import cpp import cpp
newtype TTempVariableTag = newtype TTempVariableTag =
ConditionValueTempVar() or ConditionValueTempVar() or
ReturnValueTempVar() or ReturnValueTempVar() or
ThrowTempVar() ThrowTempVar()
string getTempVariableTagId(TTempVariableTag tag) { string getTempVariableTagId(TTempVariableTag tag) {
tag = ConditionValueTempVar() and result = "CondVal" or tag = ConditionValueTempVar() and result = "CondVal" or
tag = ReturnValueTempVar() and result = "Ret" or tag = ReturnValueTempVar() and result = "Ret" or
tag = ThrowTempVar() and result = "Throw" tag = ThrowTempVar() and result = "Throw"
} }

View File

@@ -1,263 +1,263 @@
import cpp import cpp
private import InstructionTag private import InstructionTag
private import Opcode private import Opcode
private import TranslatedElement private import TranslatedElement
private import TranslatedExpr private import TranslatedExpr
abstract class ConditionContext extends TranslatedElement { abstract class ConditionContext extends TranslatedElement {
abstract Instruction getChildTrueSuccessor(TranslatedCondition child); abstract Instruction getChildTrueSuccessor(TranslatedCondition child);
abstract Instruction getChildFalseSuccessor(TranslatedCondition child); abstract Instruction getChildFalseSuccessor(TranslatedCondition child);
} }
TranslatedCondition getTranslatedCondition(Expr expr) { TranslatedCondition getTranslatedCondition(Expr expr) {
result.getExpr() = expr result.getExpr() = expr
} }
abstract class TranslatedCondition extends TranslatedElement { abstract class TranslatedCondition extends TranslatedElement {
Expr expr; Expr expr;
override final string toString() { override final string toString() {
result = expr.toString() result = expr.toString()
} }
override final Locatable getAST() { override final Locatable getAST() {
result = expr result = expr
} }
final ConditionContext getConditionContext() { final ConditionContext getConditionContext() {
result = getParent() result = getParent()
} }
final Expr getExpr() { final Expr getExpr() {
result = expr result = expr
} }
override final Function getFunction() { override final Function getFunction() {
result = expr.getEnclosingFunction() result = expr.getEnclosingFunction()
} }
final Type getResultType() { final Type getResultType() {
result = expr.getType().getUnspecifiedType() result = expr.getType().getUnspecifiedType()
} }
} }
abstract class TranslatedFlexibleCondition extends TranslatedCondition, abstract class TranslatedFlexibleCondition extends TranslatedCondition,
ConditionContext, TTranslatedFlexibleCondition { ConditionContext, TTranslatedFlexibleCondition {
TranslatedFlexibleCondition() { TranslatedFlexibleCondition() {
this = TTranslatedFlexibleCondition(expr) this = TTranslatedFlexibleCondition(expr)
} }
override final TranslatedElement getChild(int id) { override final TranslatedElement getChild(int id) {
id = 0 and result = getOperand() id = 0 and result = getOperand()
} }
override final Instruction getFirstInstruction() { override final Instruction getFirstInstruction() {
result = getOperand().getFirstInstruction() result = getOperand().getFirstInstruction()
} }
override final predicate hasInstruction(Opcode opcode, InstructionTag tag, override final predicate hasInstruction(Opcode opcode, InstructionTag tag,
Type resultType, boolean isGLValue) { Type resultType, boolean isGLValue) {
none() none()
} }
override final Instruction getInstructionSuccessor(InstructionTag tag, override final Instruction getInstructionSuccessor(InstructionTag tag,
EdgeKind kind) { EdgeKind kind) {
none() none()
} }
override final Instruction getChildSuccessor(TranslatedElement child) { override final Instruction getChildSuccessor(TranslatedElement child) {
none() none()
} }
abstract TranslatedCondition getOperand(); abstract TranslatedCondition getOperand();
} }
class TranslatedParenthesisCondition extends TranslatedFlexibleCondition { class TranslatedParenthesisCondition extends TranslatedFlexibleCondition {
ParenthesisExpr paren; ParenthesisExpr paren;
TranslatedParenthesisCondition() { TranslatedParenthesisCondition() {
paren = expr paren = expr
} }
final override Instruction getChildTrueSuccessor(TranslatedCondition child) { final override Instruction getChildTrueSuccessor(TranslatedCondition child) {
child = getOperand() and child = getOperand() and
result = getConditionContext().getChildTrueSuccessor(this) result = getConditionContext().getChildTrueSuccessor(this)
} }
final override Instruction getChildFalseSuccessor(TranslatedCondition child) { final override Instruction getChildFalseSuccessor(TranslatedCondition child) {
child = getOperand() and child = getOperand() and
result = getConditionContext().getChildFalseSuccessor(this) result = getConditionContext().getChildFalseSuccessor(this)
} }
final override TranslatedCondition getOperand() { final override TranslatedCondition getOperand() {
result = getTranslatedCondition(paren.getExpr()) result = getTranslatedCondition(paren.getExpr())
} }
} }
class TranslatedNotCondition extends TranslatedFlexibleCondition { class TranslatedNotCondition extends TranslatedFlexibleCondition {
NotExpr notExpr; NotExpr notExpr;
TranslatedNotCondition() { TranslatedNotCondition() {
notExpr = expr notExpr = expr
} }
override Instruction getChildTrueSuccessor(TranslatedCondition child) { override Instruction getChildTrueSuccessor(TranslatedCondition child) {
child = getOperand() and child = getOperand() and
result = getConditionContext().getChildFalseSuccessor(this) result = getConditionContext().getChildFalseSuccessor(this)
} }
override Instruction getChildFalseSuccessor(TranslatedCondition child) { override Instruction getChildFalseSuccessor(TranslatedCondition child) {
child = getOperand() and child = getOperand() and
result = getConditionContext().getChildTrueSuccessor(this) result = getConditionContext().getChildTrueSuccessor(this)
} }
override TranslatedCondition getOperand() { override TranslatedCondition getOperand() {
result = getTranslatedCondition(notExpr.getOperand().getFullyConverted()) result = getTranslatedCondition(notExpr.getOperand().getFullyConverted())
} }
} }
abstract class TranslatedNativeCondition extends TranslatedCondition, abstract class TranslatedNativeCondition extends TranslatedCondition,
TTranslatedNativeCondition { TTranslatedNativeCondition {
TranslatedNativeCondition() { TranslatedNativeCondition() {
this = TTranslatedNativeCondition(expr) this = TTranslatedNativeCondition(expr)
} }
override final Instruction getChildSuccessor(TranslatedElement child) { override final Instruction getChildSuccessor(TranslatedElement child) {
none() none()
} }
} }
abstract class TranslatedBinaryLogicalOperation extends abstract class TranslatedBinaryLogicalOperation extends
TranslatedNativeCondition, ConditionContext { TranslatedNativeCondition, ConditionContext {
BinaryLogicalOperation op; BinaryLogicalOperation op;
TranslatedBinaryLogicalOperation() { TranslatedBinaryLogicalOperation() {
op = expr op = expr
} }
override final TranslatedElement getChild(int id) { override final TranslatedElement getChild(int id) {
id = 0 and result = getLeftOperand() or id = 0 and result = getLeftOperand() or
id = 1 and result = getRightOperand() id = 1 and result = getRightOperand()
} }
override final Instruction getFirstInstruction() { override final Instruction getFirstInstruction() {
result = getLeftOperand().getFirstInstruction() result = getLeftOperand().getFirstInstruction()
} }
override final predicate hasInstruction(Opcode opcode, InstructionTag tag, override final predicate hasInstruction(Opcode opcode, InstructionTag tag,
Type resultType, boolean isGLValue) { Type resultType, boolean isGLValue) {
none() none()
} }
override final Instruction getInstructionSuccessor(InstructionTag tag, override final Instruction getInstructionSuccessor(InstructionTag tag,
EdgeKind kind) { EdgeKind kind) {
none() none()
} }
final TranslatedCondition getLeftOperand() { final TranslatedCondition getLeftOperand() {
result = getTranslatedCondition(op.getLeftOperand().getFullyConverted()) result = getTranslatedCondition(op.getLeftOperand().getFullyConverted())
} }
final TranslatedCondition getRightOperand() { final TranslatedCondition getRightOperand() {
result = getTranslatedCondition(op.getRightOperand().getFullyConverted()) result = getTranslatedCondition(op.getRightOperand().getFullyConverted())
} }
} }
class TranslatedLogicalAndExpr extends TranslatedBinaryLogicalOperation { class TranslatedLogicalAndExpr extends TranslatedBinaryLogicalOperation {
TranslatedLogicalAndExpr() { TranslatedLogicalAndExpr() {
op instanceof LogicalAndExpr op instanceof LogicalAndExpr
} }
override Instruction getChildTrueSuccessor(TranslatedCondition child) { override Instruction getChildTrueSuccessor(TranslatedCondition child) {
( (
child = getLeftOperand() and child = getLeftOperand() and
result = getRightOperand().getFirstInstruction() result = getRightOperand().getFirstInstruction()
) or ) or
( (
child = getRightOperand() and child = getRightOperand() and
result = getConditionContext().getChildTrueSuccessor(this) result = getConditionContext().getChildTrueSuccessor(this)
) )
} }
override Instruction getChildFalseSuccessor(TranslatedCondition child) { override Instruction getChildFalseSuccessor(TranslatedCondition child) {
(child = getLeftOperand() or child = getRightOperand()) and (child = getLeftOperand() or child = getRightOperand()) and
result = getConditionContext().getChildFalseSuccessor(this) result = getConditionContext().getChildFalseSuccessor(this)
} }
} }
class TranslatedLogicalOrExpr extends TranslatedBinaryLogicalOperation { class TranslatedLogicalOrExpr extends TranslatedBinaryLogicalOperation {
TranslatedLogicalOrExpr() { TranslatedLogicalOrExpr() {
op instanceof LogicalOrExpr op instanceof LogicalOrExpr
} }
override Instruction getChildTrueSuccessor(TranslatedCondition child) { override Instruction getChildTrueSuccessor(TranslatedCondition child) {
(child = getLeftOperand() or child = getRightOperand()) and (child = getLeftOperand() or child = getRightOperand()) and
result = getConditionContext().getChildTrueSuccessor(this) result = getConditionContext().getChildTrueSuccessor(this)
} }
override Instruction getChildFalseSuccessor(TranslatedCondition child) { override Instruction getChildFalseSuccessor(TranslatedCondition child) {
( (
child = getLeftOperand() and child = getLeftOperand() and
result = getRightOperand().getFirstInstruction() result = getRightOperand().getFirstInstruction()
) or ) or
( (
child = getRightOperand() and child = getRightOperand() and
result = getConditionContext().getChildFalseSuccessor(this) result = getConditionContext().getChildFalseSuccessor(this)
) )
} }
} }
class TranslatedValueCondition extends TranslatedCondition, class TranslatedValueCondition extends TranslatedCondition,
TTranslatedValueCondition { TTranslatedValueCondition {
TranslatedValueCondition() { TranslatedValueCondition() {
this = TTranslatedValueCondition(expr) this = TTranslatedValueCondition(expr)
} }
override TranslatedElement getChild(int id) { override TranslatedElement getChild(int id) {
id = 0 and result = getValueExpr() id = 0 and result = getValueExpr()
} }
override Instruction getFirstInstruction() { override Instruction getFirstInstruction() {
result = getValueExpr().getFirstInstruction() result = getValueExpr().getFirstInstruction()
} }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, override predicate hasInstruction(Opcode opcode, InstructionTag tag,
Type resultType, boolean isGLValue) { Type resultType, boolean isGLValue) {
tag = ValueConditionConditionalBranchTag() and tag = ValueConditionConditionalBranchTag() and
opcode instanceof Opcode::ConditionalBranch and opcode instanceof Opcode::ConditionalBranch and
resultType instanceof VoidType and resultType instanceof VoidType and
isGLValue = false isGLValue = false
} }
override Instruction getChildSuccessor(TranslatedElement child) { override Instruction getChildSuccessor(TranslatedElement child) {
child = getValueExpr() and child = getValueExpr() and
result = getInstruction(ValueConditionConditionalBranchTag()) result = getInstruction(ValueConditionConditionalBranchTag())
} }
override Instruction getInstructionSuccessor(InstructionTag tag, override Instruction getInstructionSuccessor(InstructionTag tag,
EdgeKind kind) { EdgeKind kind) {
tag = ValueConditionConditionalBranchTag() and tag = ValueConditionConditionalBranchTag() and
( (
( (
kind instanceof TrueEdge and kind instanceof TrueEdge and
result = getConditionContext().getChildTrueSuccessor(this) result = getConditionContext().getChildTrueSuccessor(this)
) or ) or
( (
kind instanceof FalseEdge and kind instanceof FalseEdge and
result = getConditionContext().getChildFalseSuccessor(this) result = getConditionContext().getChildFalseSuccessor(this)
) )
) )
} }
override Instruction getInstructionOperand(InstructionTag tag, override Instruction getInstructionOperand(InstructionTag tag,
OperandTag operandTag) { OperandTag operandTag) {
tag = ValueConditionConditionalBranchTag() and tag = ValueConditionConditionalBranchTag() and
operandTag instanceof ConditionOperand and operandTag instanceof ConditionOperand and
result = getValueExpr().getResult() result = getValueExpr().getResult()
} }
private TranslatedExpr getValueExpr() { private TranslatedExpr getValueExpr() {
result = getTranslatedExpr(expr) result = getTranslatedExpr(expr)
} }
} }

View File

@@ -1,226 +1,226 @@
import cpp import cpp
private import InstructionTag private import InstructionTag
private import Opcode private import Opcode
private import TranslatedElement private import TranslatedElement
private import TranslatedExpr private import TranslatedExpr
private import TranslatedInitialization private import TranslatedInitialization
/** /**
* Gets the `TranslatedDeclarationEntry` that represents the declaration * Gets the `TranslatedDeclarationEntry` that represents the declaration
* `entry`. * `entry`.
*/ */
TranslatedDeclarationEntry getTranslatedDeclarationEntry( TranslatedDeclarationEntry getTranslatedDeclarationEntry(
DeclarationEntry entry) { DeclarationEntry entry) {
result.getAST() = entry result.getAST() = entry
} }
/** /**
* Represents the IR translation of a declaration within the body of a function. * Represents the IR translation of a declaration within the body of a function.
* Most often, this is the declaration of an automatic local variable, although * Most often, this is the declaration of an automatic local variable, although
* it can also be the declaration of a static local variable, an extern * it can also be the declaration of a static local variable, an extern
* variable, or an extern function. * variable, or an extern function.
*/ */
abstract class TranslatedDeclarationEntry extends TranslatedElement, abstract class TranslatedDeclarationEntry extends TranslatedElement,
TTranslatedDeclarationEntry { TTranslatedDeclarationEntry {
DeclarationEntry entry; DeclarationEntry entry;
TranslatedDeclarationEntry() { TranslatedDeclarationEntry() {
this = TTranslatedDeclarationEntry(entry) this = TTranslatedDeclarationEntry(entry)
} }
override final Function getFunction() { override final Function getFunction() {
exists(DeclStmt stmt | exists(DeclStmt stmt |
stmt.getADeclarationEntry() = entry and stmt.getADeclarationEntry() = entry and
result = stmt.getEnclosingFunction() result = stmt.getEnclosingFunction()
) )
} }
override final string toString() { override final string toString() {
result = entry.toString() result = entry.toString()
} }
override final Locatable getAST() { override final Locatable getAST() {
result = entry result = entry
} }
} }
/** /**
* Represents the IR translation of a declaration within the body of a function, * Represents the IR translation of a declaration within the body of a function,
* for declarations other than local variables. Since these have no semantic * for declarations other than local variables. Since these have no semantic
* effect, they are translated as `NoOp`. * effect, they are translated as `NoOp`.
*/ */
class TranslatedNonVariableDeclaration extends class TranslatedNonVariableDeclaration extends
TranslatedDeclarationEntry { TranslatedDeclarationEntry {
TranslatedNonVariableDeclaration() { TranslatedNonVariableDeclaration() {
not entry.getDeclaration() instanceof LocalVariable not entry.getDeclaration() instanceof LocalVariable
} }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, override predicate hasInstruction(Opcode opcode, InstructionTag tag,
Type resultType, boolean isGLValue) { Type resultType, boolean isGLValue) {
opcode instanceof Opcode::NoOp and opcode instanceof Opcode::NoOp and
tag = OnlyInstructionTag() and tag = OnlyInstructionTag() and
resultType instanceof VoidType and resultType instanceof VoidType and
isGLValue = false isGLValue = false
} }
override Instruction getFirstInstruction() { override Instruction getFirstInstruction() {
result = getInstruction(OnlyInstructionTag()) result = getInstruction(OnlyInstructionTag())
} }
override TranslatedElement getChild(int id) { override TranslatedElement getChild(int id) {
none() none()
} }
override Instruction getInstructionSuccessor(InstructionTag tag, override Instruction getInstructionSuccessor(InstructionTag tag,
EdgeKind kind) { EdgeKind kind) {
tag = OnlyInstructionTag() and tag = OnlyInstructionTag() and
result = getParent().getChildSuccessor(this) and result = getParent().getChildSuccessor(this) and
kind instanceof GotoEdge kind instanceof GotoEdge
} }
override Instruction getChildSuccessor(TranslatedElement child) { override Instruction getChildSuccessor(TranslatedElement child) {
none() none()
} }
} }
/** /**
* Represents the IR translation of the declaration of a local variable, * Represents the IR translation of the declaration of a local variable,
* including its initialization, if any. * including its initialization, if any.
*/ */
abstract class TranslatedVariableDeclaration extends abstract class TranslatedVariableDeclaration extends
TranslatedDeclarationEntry { TranslatedDeclarationEntry {
LocalVariable var; LocalVariable var;
TranslatedVariableDeclaration() { TranslatedVariableDeclaration() {
entry.getDeclaration() = var entry.getDeclaration() = var
} }
} }
/** /**
* Represents the IR translation of a local variable with no initializer. The * Represents the IR translation of a local variable with no initializer. The
* generated IR stores into the variable using an `Uninitialized` instruction, * generated IR stores into the variable using an `Uninitialized` instruction,
* rather than a `Store`. * rather than a `Store`.
*/ */
class TranslatedUninitializedVariable extends class TranslatedUninitializedVariable extends
TranslatedVariableDeclaration { TranslatedVariableDeclaration {
TranslatedUninitializedVariable() { TranslatedUninitializedVariable() {
not exists(Initializer init | not exists(Initializer init |
init.getDeclaration() = var init.getDeclaration() = var
) )
} }
override TranslatedElement getChild(int id) { override TranslatedElement getChild(int id) {
none() none()
} }
override Instruction getFirstInstruction() { override Instruction getFirstInstruction() {
result = getInstruction(InitializerVariableAddressTag()) result = getInstruction(InitializerVariableAddressTag())
} }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, override predicate hasInstruction(Opcode opcode, InstructionTag tag,
Type resultType, boolean isGLValue) { Type resultType, boolean isGLValue) {
( (
tag = InitializerVariableAddressTag() and tag = InitializerVariableAddressTag() and
opcode instanceof Opcode::VariableAddress and opcode instanceof Opcode::VariableAddress and
resultType = var.getType().getUnspecifiedType() and resultType = var.getType().getUnspecifiedType() and
isGLValue = true isGLValue = true
) or ) or
( (
tag = InitializerStoreTag() and tag = InitializerStoreTag() and
opcode instanceof Opcode::Uninitialized and opcode instanceof Opcode::Uninitialized and
resultType = var.getType().getUnspecifiedType() and resultType = var.getType().getUnspecifiedType() and
isGLValue = false isGLValue = false
) )
} }
override Instruction getInstructionSuccessor(InstructionTag tag, override Instruction getInstructionSuccessor(InstructionTag tag,
EdgeKind kind) { EdgeKind kind) {
kind instanceof GotoEdge and kind instanceof GotoEdge and
( (
( (
tag = InitializerVariableAddressTag() and tag = InitializerVariableAddressTag() and
result = getInstruction(InitializerStoreTag()) result = getInstruction(InitializerStoreTag())
) or ) or
( (
tag = InitializerStoreTag() and tag = InitializerStoreTag() and
result = getParent().getChildSuccessor(this) result = getParent().getChildSuccessor(this)
) )
) )
} }
override Instruction getChildSuccessor(TranslatedElement child) { override Instruction getChildSuccessor(TranslatedElement child) {
none() none()
} }
override Instruction getInstructionOperand(InstructionTag tag, override Instruction getInstructionOperand(InstructionTag tag,
OperandTag operandTag) { OperandTag operandTag) {
tag = InitializerStoreTag() and tag = InitializerStoreTag() and
( (
( (
operandTag instanceof LoadStoreAddressOperand and operandTag instanceof LoadStoreAddressOperand and
result = getInstruction(InitializerVariableAddressTag()) result = getInstruction(InitializerVariableAddressTag())
) )
) )
} }
override IRVariable getInstructionVariable(InstructionTag tag) { override IRVariable getInstructionVariable(InstructionTag tag) {
tag = InitializerVariableAddressTag() and tag = InitializerVariableAddressTag() and
result = getIRUserVariable(var.getFunction(), var) result = getIRUserVariable(var.getFunction(), var)
} }
} }
/** /**
* Represents the IR translation of a local variable with an initializer. * Represents the IR translation of a local variable with an initializer.
*/ */
class TranslatedInitializedVariable extends class TranslatedInitializedVariable extends
TranslatedVariableDeclaration, InitializationContext { TranslatedVariableDeclaration, InitializationContext {
Initializer init; Initializer init;
TranslatedInitializedVariable() { TranslatedInitializedVariable() {
init.getDeclaration() = var init.getDeclaration() = var
} }
override TranslatedElement getChild(int id) { override TranslatedElement getChild(int id) {
id = 0 and result = getInitialization() id = 0 and result = getInitialization()
} }
override Instruction getFirstInstruction() { override Instruction getFirstInstruction() {
result = getInstruction(InitializerVariableAddressTag()) result = getInstruction(InitializerVariableAddressTag())
} }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, override predicate hasInstruction(Opcode opcode, InstructionTag tag,
Type resultType, boolean isGLValue) { Type resultType, boolean isGLValue) {
tag = InitializerVariableAddressTag() and tag = InitializerVariableAddressTag() and
opcode instanceof Opcode::VariableAddress and opcode instanceof Opcode::VariableAddress and
resultType = var.getType().getUnspecifiedType() and resultType = var.getType().getUnspecifiedType() and
isGLValue = true isGLValue = true
} }
override Instruction getInstructionSuccessor(InstructionTag tag, override Instruction getInstructionSuccessor(InstructionTag tag,
EdgeKind kind) { EdgeKind kind) {
tag = InitializerVariableAddressTag() and tag = InitializerVariableAddressTag() and
result = getInitialization().getFirstInstruction() and result = getInitialization().getFirstInstruction() and
kind instanceof GotoEdge kind instanceof GotoEdge
} }
override Instruction getChildSuccessor(TranslatedElement child) { override Instruction getChildSuccessor(TranslatedElement child) {
child = getInitialization() and result = getParent().getChildSuccessor(this) child = getInitialization() and result = getParent().getChildSuccessor(this)
} }
override IRVariable getInstructionVariable(InstructionTag tag) { override IRVariable getInstructionVariable(InstructionTag tag) {
tag = InitializerVariableAddressTag() and tag = InitializerVariableAddressTag() and
result = getIRUserVariable(var.getFunction(), var) result = getIRUserVariable(var.getFunction(), var)
} }
override Instruction getTargetAddress() { override Instruction getTargetAddress() {
result = getInstruction(InitializerVariableAddressTag()) result = getInstruction(InitializerVariableAddressTag())
} }
override Type getTargetType() { override Type getTargetType() {
result = var.getType().getUnspecifiedType() result = var.getType().getUnspecifiedType()
} }
private TranslatedInitialization getInitialization() { private TranslatedInitialization getInitialization() {
result = getTranslatedInitialization(init.getExpr().getFullyConverted()) result = getTranslatedInitialization(init.getExpr().getFullyConverted())
} }
} }

View File

@@ -50,7 +50,7 @@ abstract class TranslatedExpr extends TranslatedElement {
* Gets the type of the result produced by this expression. * Gets the type of the result produced by this expression.
*/ */
final Type getResultType() { final Type getResultType() {
result = expr.getType().getUnspecifiedType() result = expr.getType().getUnspecifiedType()
} }
override final Locatable getAST() { override final Locatable getAST() {
@@ -303,7 +303,7 @@ class TranslatedLoad extends TranslatedExpr, TTranslatedLoad {
} }
override string toString() { override string toString() {
result = "Load of " + expr.toString() result = "Load of " + expr.toString()
} }
override Instruction getFirstInstruction() { override Instruction getFirstInstruction() {
@@ -1945,7 +1945,7 @@ abstract class TranslatedAllocationSize extends TranslatedExpr,
} }
override final predicate producesExprResult() { override final predicate producesExprResult() {
none() none()
} }
override final Instruction getResult() { override final Instruction getResult() {
@@ -2144,7 +2144,7 @@ class TranslatedAllocatorCall extends TTranslatedAllocatorCall,
} }
override final predicate producesExprResult() { override final predicate producesExprResult() {
none() none()
} }
override Function getInstructionFunction(InstructionTag tag) { override Function getInstructionFunction(InstructionTag tag) {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
private import implementations.Inet private import implementations.Inet
private import implementations.Memcpy private import implementations.Memcpy
private import implementations.Printf private import implementations.Printf
private import implementations.Pure private import implementations.Pure
private import implementations.Strcat private import implementations.Strcat
private import implementations.Strcpy private import implementations.Strcpy
private import implementations.Strftime private import implementations.Strftime

View File

@@ -1 +1 @@
import internal.aliased_ssa.IRImpl import internal.aliased_ssa.IRImpl

View File

@@ -1,8 +1,8 @@
/** /**
* @name Print Aliased SSA IR * @name Print Aliased SSA IR
* @description Outputs a representation of the Aliased SSA IR graph * @description Outputs a representation of the Aliased SSA IR graph
* @id cpp/print-aliased-ssa-ir * @id cpp/print-aliased-ssa-ir
* @kind graph * @kind graph
*/ */
import PrintAliasedSSAIR import PrintAliasedSSAIR

View File

@@ -1 +1 @@
import internal.aliased_ssa.PrintIRImpl import internal.aliased_ssa.PrintIRImpl

View File

@@ -1,8 +1,8 @@
/** /**
* @name Print SSA IR * @name Print SSA IR
* @description Outputs a representation of the SSA IR graph * @description Outputs a representation of the SSA IR graph
* @id cpp/print-ssa-ir * @id cpp/print-ssa-ir
* @kind graph * @kind graph
*/ */
import PrintSSAIR import PrintSSAIR

View File

@@ -1 +1 @@
import internal.ssa.PrintIRImpl import internal.ssa.PrintIRImpl

View File

@@ -1 +1 @@
import internal.ssa.IRImpl import internal.ssa.IRImpl

View File

@@ -1,111 +1,111 @@
import cpp import cpp
class IntValue = int; class IntValue = int;
/** /**
* Returns the value of the maximum representable integer. * Returns the value of the maximum representable integer.
*/ */
int maxValue() { int maxValue() {
result = 2147483647 result = 2147483647
} }
/** /**
* Returns the value of the minimum representable integer. * Returns the value of the minimum representable integer.
*/ */
int minValue() { int minValue() {
result = -2147483647 result = -2147483647
} }
/** /**
* Returns a value representing an unknown integer. * Returns a value representing an unknown integer.
*/ */
IntValue unknown() { IntValue unknown() {
result = -2147483648 result = -2147483648
} }
/** /**
* Holds if `n` has a known value. * Holds if `n` has a known value.
*/ */
bindingset[n] bindingset[n]
predicate hasValue(IntValue n) { predicate hasValue(IntValue n) {
n != unknown() n != unknown()
} }
/** /**
* Holds if the value `f` is within the range of representable integers. * Holds if the value `f` is within the range of representable integers.
*/ */
pragma[inline] pragma[inline]
bindingset[f] bindingset[f]
private predicate isRepresentable(float f) { private predicate isRepresentable(float f) {
(f >= minValue()) and (f <= maxValue()) (f >= minValue()) and (f <= maxValue())
} }
/** /**
* Gets the value of `n`. Holds only if `n` has a known value. * Gets the value of `n`. Holds only if `n` has a known value.
*/ */
bindingset[n] bindingset[n]
int getValue(IntValue n) { int getValue(IntValue n) {
hasValue(n) and result = n hasValue(n) and result = n
} }
/** /**
* Returns `a + b`. If either input is unknown, or if the addition overflows, * Returns `a + b`. If either input is unknown, or if the addition overflows,
* the result is unknown. * the result is unknown.
*/ */
bindingset[a, b] bindingset[a, b]
IntValue add(IntValue a, IntValue b) { IntValue add(IntValue a, IntValue b) {
if hasValue(a) and hasValue(b) and isRepresentable((float)a + (float)b) then if hasValue(a) and hasValue(b) and isRepresentable((float)a + (float)b) then
result = a + b result = a + b
else else
result = unknown() result = unknown()
} }
/** /**
* Returns `a - b`. If either input is unknown, or if the subtraction overflows, * Returns `a - b`. If either input is unknown, or if the subtraction overflows,
* the result is unknown. * the result is unknown.
*/ */
bindingset[a, b] bindingset[a, b]
IntValue sub(IntValue a, IntValue b) { IntValue sub(IntValue a, IntValue b) {
if hasValue(a) and hasValue(b) and isRepresentable((float)a - (float)b) then if hasValue(a) and hasValue(b) and isRepresentable((float)a - (float)b) then
result = a - b result = a - b
else else
result = unknown() result = unknown()
} }
/** /**
* Returns `a * b`. If the multiplication overflows, the result is unknown. If * Returns `a * b`. If the multiplication overflows, the result is unknown. If
* either input is unknown and the other input is non-zero, the result is * either input is unknown and the other input is non-zero, the result is
* unknown. * unknown.
*/ */
bindingset[a, b] bindingset[a, b]
IntValue mul(IntValue a, IntValue b) { IntValue mul(IntValue a, IntValue b) {
if (a = 0) or (b = 0) then if (a = 0) or (b = 0) then
result = 0 result = 0
else if hasValue(a) and hasValue(b) and isRepresentable((float)a * (float)b) then else if hasValue(a) and hasValue(b) and isRepresentable((float)a * (float)b) then
result = a * b result = a * b
else else
result = unknown() result = unknown()
} }
/** /**
* Returns `a / b`. If either input is unknown, or if `b` is zero, the result is * Returns `a / b`. If either input is unknown, or if `b` is zero, the result is
* unknown. * unknown.
*/ */
bindingset[a, b] bindingset[a, b]
IntValue div(IntValue a, IntValue b) { IntValue div(IntValue a, IntValue b) {
// Normally, integer division has to worry about overflow for INT_MIN/-1. // Normally, integer division has to worry about overflow for INT_MIN/-1.
// However, since we use INT_MIN to represent an unknown value anyway, we only // However, since we use INT_MIN to represent an unknown value anyway, we only
// have to worry about division by zero. // have to worry about division by zero.
if hasValue(a) and hasValue(b) and (b != 0) then if hasValue(a) and hasValue(b) and (b != 0) then
result = a / b result = a / b
else else
result = unknown() result = unknown()
} }
/** /**
* Return `-a`. If `a` is unknown, the result is unknown. * Return `-a`. If `a` is unknown, the result is unknown.
*/ */
bindingset[a] bindingset[a]
IntValue neg(IntValue a) { IntValue neg(IntValue a) {
result = -a // -INT_MIN = INT_MIN, so this preserves unknown result = -a // -INT_MIN = INT_MIN, so this preserves unknown
} }

View File

@@ -1,28 +1,28 @@
import cpp import cpp
private newtype TOverlap = private newtype TOverlap =
TMayPartiallyOverlap() or TMayPartiallyOverlap() or
TMustTotallyOverlap() or TMustTotallyOverlap() or
TMustExactlyOverlap() TMustExactlyOverlap()
abstract class Overlap extends TOverlap { abstract class Overlap extends TOverlap {
abstract string toString(); abstract string toString();
} }
class MayPartiallyOverlap extends Overlap, TMayPartiallyOverlap { class MayPartiallyOverlap extends Overlap, TMayPartiallyOverlap {
override final string toString() { override final string toString() {
result = "MayPartiallyOverlap" result = "MayPartiallyOverlap"
} }
} }
class MustTotallyOverlap extends Overlap, TMustTotallyOverlap { class MustTotallyOverlap extends Overlap, TMustTotallyOverlap {
override final string toString() { override final string toString() {
result = "MustTotallyOverlap" result = "MustTotallyOverlap"
} }
} }
class MustExactlyOverlap extends Overlap, TMustExactlyOverlap { class MustExactlyOverlap extends Overlap, TMustExactlyOverlap {
override final string toString() { override final string toString() {
result = "MustExactlyOverlap" result = "MustExactlyOverlap"
} }
} }

View File

@@ -1,214 +1,214 @@
private import AliasAnalysisInternal private import AliasAnalysisInternal
import cpp import cpp
private import IR private import IR
private import semmle.code.cpp.ssa.internal.IntegerConstant as Ints private import semmle.code.cpp.ssa.internal.IntegerConstant as Ints
private class IntValue = Ints::IntValue; private class IntValue = Ints::IntValue;
/** /**
* Converts the bit count in `bits` to a byte count and a bit count in the form * Converts the bit count in `bits` to a byte count and a bit count in the form
* bytes:bits. * bytes:bits.
*/ */
bindingset[bits] bindingset[bits]
string bitsToBytesAndBits(int bits) { string bitsToBytesAndBits(int bits) {
result = (bits / 8).toString() + ":" + (bits % 8).toString() result = (bits / 8).toString() + ":" + (bits % 8).toString()
} }
/** /**
* Gets a printable string for a bit offset with possibly unknown value. * Gets a printable string for a bit offset with possibly unknown value.
*/ */
bindingset[bitOffset] bindingset[bitOffset]
string getBitOffsetString(IntValue bitOffset) { string getBitOffsetString(IntValue bitOffset) {
if Ints::hasValue(bitOffset) then if Ints::hasValue(bitOffset) then
if bitOffset >= 0 then if bitOffset >= 0 then
result = "+" + bitsToBytesAndBits(bitOffset) result = "+" + bitsToBytesAndBits(bitOffset)
else else
result = "-" + bitsToBytesAndBits(Ints::neg(bitOffset)) result = "-" + bitsToBytesAndBits(Ints::neg(bitOffset))
else else
result = "+?" result = "+?"
} }
/** /**
* Gets the offset of field `field` in bits. * Gets the offset of field `field` in bits.
*/ */
private IntValue getFieldBitOffset(Field field) { private IntValue getFieldBitOffset(Field field) {
if (field instanceof BitField) then ( if (field instanceof BitField) then (
result = Ints::add(Ints::mul(field.getByteOffset(), 8), result = Ints::add(Ints::mul(field.getByteOffset(), 8),
field.(BitField).getBitOffset()) field.(BitField).getBitOffset())
) )
else ( else (
result = Ints::mul(field.getByteOffset(), 8) result = Ints::mul(field.getByteOffset(), 8)
) )
} }
/** /**
* Holds if the operand `tag` of instruction `instr` is used in a way that does * Holds if the operand `tag` of instruction `instr` is used in a way that does
* not result in any address held in that operand from escaping beyond the * not result in any address held in that operand from escaping beyond the
* instruction. * instruction.
*/ */
predicate operandIsConsumedWithoutEscaping(Instruction instr, OperandTag tag) { predicate operandIsConsumedWithoutEscaping(Instruction instr, OperandTag tag) {
exists(instr.getOperand(tag)) and exists(instr.getOperand(tag)) and
( (
// The source/destination address of a Load/Store does not escape (but the // The source/destination address of a Load/Store does not escape (but the
// loaded/stored value could). // loaded/stored value could).
tag instanceof LoadStoreAddressOperand or tag instanceof LoadStoreAddressOperand or
// Neither operand of a Compare escapes. // Neither operand of a Compare escapes.
instr instanceof CompareInstruction or instr instanceof CompareInstruction or
// Neither operand of a PointerDiff escapes. // Neither operand of a PointerDiff escapes.
instr instanceof PointerDiffInstruction or instr instanceof PointerDiffInstruction or
// Converting an address to a `bool` does not escape the address. // Converting an address to a `bool` does not escape the address.
instr.(ConvertInstruction).getResultType() instanceof BoolType instr.(ConvertInstruction).getResultType() instanceof BoolType
) )
} }
/** /**
* If the result of instruction `instr` is an integer constant, returns the * If the result of instruction `instr` is an integer constant, returns the
* value of that constant. Otherwise, returns unknown. * value of that constant. Otherwise, returns unknown.
*/ */
IntValue getConstantValue(Instruction instr) { IntValue getConstantValue(Instruction instr) {
if instr instanceof IntegerConstantInstruction then if instr instanceof IntegerConstantInstruction then
result = instr.(IntegerConstantInstruction).getValue().toInt() result = instr.(IntegerConstantInstruction).getValue().toInt()
else else
result = Ints::unknown() result = Ints::unknown()
} }
/** /**
* Computes the offset, in bits, by which the result of `instr` differs from the * Computes the offset, in bits, by which the result of `instr` differs from the
* pointer argument to `instr`, if that offset is a constant. Otherwise, returns * pointer argument to `instr`, if that offset is a constant. Otherwise, returns
* unknown. * unknown.
*/ */
IntValue getPointerBitOffset(PointerOffsetInstruction instr) { IntValue getPointerBitOffset(PointerOffsetInstruction instr) {
exists(IntValue bitOffset | exists(IntValue bitOffset |
( (
bitOffset = Ints::mul(Ints::mul(getConstantValue(instr.getRightOperand()), bitOffset = Ints::mul(Ints::mul(getConstantValue(instr.getRightOperand()),
instr.getElementSize()), 8) instr.getElementSize()), 8)
) and ) and
( (
instr instanceof PointerAddInstruction and result = bitOffset or instr instanceof PointerAddInstruction and result = bitOffset or
instr instanceof PointerSubInstruction and result = Ints::neg(bitOffset) instr instanceof PointerSubInstruction and result = Ints::neg(bitOffset)
) )
) )
} }
/** /**
* Holds if any address held in operand `tag` of instruction `instr` is * Holds if any address held in operand `tag` of instruction `instr` is
* propagated to the result of `instr`, offset by the number of bits in * propagated to the result of `instr`, offset by the number of bits in
* `bitOffset`. If the address is propagated, but the offset is not known to be * `bitOffset`. If the address is propagated, but the offset is not known to be
* a constant, then `bitOffset` is unknown. * a constant, then `bitOffset` is unknown.
*/ */
predicate operandIsPropagated(Instruction instr, OperandTag tag, predicate operandIsPropagated(Instruction instr, OperandTag tag,
IntValue bitOffset) { IntValue bitOffset) {
exists(instr.getOperand(tag)) and exists(instr.getOperand(tag)) and
( (
// Converting to a non-virtual base class adds the offset of the base class. // Converting to a non-virtual base class adds the offset of the base class.
exists(ConvertToBaseInstruction convert | exists(ConvertToBaseInstruction convert |
convert = instr and convert = instr and
bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8) bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8)
) or ) or
// Converting to a derived class subtracts the offset of the base class. // Converting to a derived class subtracts the offset of the base class.
exists(ConvertToDerivedInstruction convert | exists(ConvertToDerivedInstruction convert |
convert = instr and convert = instr and
bitOffset = Ints::neg(Ints::mul(convert.getDerivation().getByteOffset(), 8)) bitOffset = Ints::neg(Ints::mul(convert.getDerivation().getByteOffset(), 8))
) or ) or
// Converting to a virtual base class adds an unknown offset. // Converting to a virtual base class adds an unknown offset.
( (
instr instanceof ConvertToVirtualBaseInstruction and instr instanceof ConvertToVirtualBaseInstruction and
bitOffset = Ints::unknown() bitOffset = Ints::unknown()
) or ) or
// Conversion to another pointer type propagates the source address. // Conversion to another pointer type propagates the source address.
exists(ConvertInstruction convert, Type resultType | exists(ConvertInstruction convert, Type resultType |
convert = instr and convert = instr and
resultType = convert.getResultType() and resultType = convert.getResultType() and
( (
resultType instanceof PointerType or resultType instanceof PointerType or
resultType instanceof Class //REVIEW: Remove when all glvalues are pointers resultType instanceof Class //REVIEW: Remove when all glvalues are pointers
) and ) and
bitOffset = 0 bitOffset = 0
) or ) or
// Adding an integer to or subtracting an integer from a pointer propagates // Adding an integer to or subtracting an integer from a pointer propagates
// the address with an offset. // the address with an offset.
bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction)) or bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction)) or
// Computing a field address from a pointer propagates the address plus the // Computing a field address from a pointer propagates the address plus the
// offset of the field. // offset of the field.
bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) or bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) or
// A copy propagates the source value. // A copy propagates the source value.
tag instanceof CopySourceOperand and bitOffset = 0 tag instanceof CopySourceOperand and bitOffset = 0
) )
} }
/** /**
* Holds if any address held in operand number `tag` of instruction `instr` * Holds if any address held in operand number `tag` of instruction `instr`
* escapes outside the domain of the analysis. * escapes outside the domain of the analysis.
*/ */
predicate operandEscapes(Instruction instr, OperandTag tag) { predicate operandEscapes(Instruction instr, OperandTag tag) {
exists(instr.getOperand(tag)) and exists(instr.getOperand(tag)) and
// Conservatively assume that the address escapes unless one of the following // Conservatively assume that the address escapes unless one of the following
// holds: // holds:
not ( not (
// The operand is used in a way that does not escape the instruction // The operand is used in a way that does not escape the instruction
operandIsConsumedWithoutEscaping(instr, tag) or operandIsConsumedWithoutEscaping(instr, tag) or
// The address is propagated to the result of the instruction, but that // The address is propagated to the result of the instruction, but that
// result does not itself escape. // result does not itself escape.
operandIsPropagated(instr, tag, _) and not resultEscapes(instr) operandIsPropagated(instr, tag, _) and not resultEscapes(instr)
) )
} }
/** /**
* Holds if any address held in the result of instruction `instr` escapes * Holds if any address held in the result of instruction `instr` escapes
* outside the domain of the analysis. * outside the domain of the analysis.
*/ */
predicate resultEscapes(Instruction instr) { predicate resultEscapes(Instruction instr) {
// The result escapes if it has at least one use that escapes. // The result escapes if it has at least one use that escapes.
exists(Instruction useInstr, OperandTag useOperandTag | exists(Instruction useInstr, OperandTag useOperandTag |
useInstr.getOperand(useOperandTag) = instr and useInstr.getOperand(useOperandTag) = instr and
operandEscapes(useInstr, useOperandTag) operandEscapes(useInstr, useOperandTag)
) )
} }
/** /**
* Holds if the address of the specified local variable or parameter escapes the * Holds if the address of the specified local variable or parameter escapes the
* domain of the analysis. * domain of the analysis.
*/ */
private predicate automaticVariableAddressEscapes(IRAutomaticVariable var) { private predicate automaticVariableAddressEscapes(IRAutomaticVariable var) {
exists(FunctionIR funcIR | exists(FunctionIR funcIR |
funcIR = var.getFunctionIR() and funcIR = var.getFunctionIR() and
// The variable's address escapes if the result of any // The variable's address escapes if the result of any
// VariableAddressInstruction that computes the variable's address escapes. // VariableAddressInstruction that computes the variable's address escapes.
exists(VariableAddressInstruction instr | exists(VariableAddressInstruction instr |
instr.getFunctionIR() = funcIR and instr.getFunctionIR() = funcIR and
instr.getVariable() = var and instr.getVariable() = var and
resultEscapes(instr) resultEscapes(instr)
) )
) )
} }
/** /**
* Holds if the address of the specified variable escapes the domain of the * Holds if the address of the specified variable escapes the domain of the
* analysis. * analysis.
*/ */
predicate variableAddressEscapes(IRVariable var) { predicate variableAddressEscapes(IRVariable var) {
automaticVariableAddressEscapes(var.(IRAutomaticVariable)) or automaticVariableAddressEscapes(var.(IRAutomaticVariable)) or
// All variables with static storage duration have their address escape. // All variables with static storage duration have their address escape.
not var instanceof IRAutomaticVariable not var instanceof IRAutomaticVariable
} }
/** /**
* Holds if the result of instruction `instr` points within variable `var`, at * Holds if the result of instruction `instr` points within variable `var`, at
* bit offset `bitOffset` within the variable. If the result points within * bit offset `bitOffset` within the variable. If the result points within
* `var`, but at an unknown or non-constant offset, then `bitOffset` is unknown. * `var`, but at an unknown or non-constant offset, then `bitOffset` is unknown.
*/ */
predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) { predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) {
( (
// The address of a variable points to that variable, at offset 0. // The address of a variable points to that variable, at offset 0.
instr.(VariableAddressInstruction).getVariable() = var and instr.(VariableAddressInstruction).getVariable() = var and
bitOffset = 0 bitOffset = 0
) or ) or
exists(OperandTag operandTag, IntValue originalBitOffset, exists(OperandTag operandTag, IntValue originalBitOffset,
IntValue propagatedBitOffset | IntValue propagatedBitOffset |
// If an operand is propagated, then the result points to the same variable, // If an operand is propagated, then the result points to the same variable,
// offset by the bit offset from the propagation. // offset by the bit offset from the propagation.
resultPointsTo(instr.getOperand(operandTag), var, originalBitOffset) and resultPointsTo(instr.getOperand(operandTag), var, originalBitOffset) and
operandIsPropagated(instr, operandTag, propagatedBitOffset) and operandIsPropagated(instr, operandTag, propagatedBitOffset) and
bitOffset = Ints::add(originalBitOffset, propagatedBitOffset) bitOffset = Ints::add(originalBitOffset, propagatedBitOffset)
) )
} }

View File

@@ -1 +1 @@
import semmle.code.cpp.ssa.SSAIR as IR import semmle.code.cpp.ssa.SSAIR as IR

View File

@@ -1,97 +1,97 @@
private import IRInternal private import IRInternal
import Instruction import Instruction
import cpp import cpp
private newtype TFunctionIR = private newtype TFunctionIR =
MkFunctionIR(Function func) { MkFunctionIR(Function func) {
Construction::functionHasIR(func) Construction::functionHasIR(func)
} }
/** /**
* Represents the IR for a function. * Represents the IR for a function.
*/ */
class FunctionIR extends TFunctionIR { class FunctionIR extends TFunctionIR {
Function func; Function func;
FunctionIR() { FunctionIR() {
this = MkFunctionIR(func) this = MkFunctionIR(func)
} }
final string toString() { final string toString() {
result = "IR: " + func.toString() result = "IR: " + func.toString()
} }
/** /**
* Gets the function whose IR is represented. * Gets the function whose IR is represented.
*/ */
final Function getFunction() { final Function getFunction() {
result = func result = func
} }
/** /**
* Gets the location of the function. * Gets the location of the function.
*/ */
final Location getLocation() { final Location getLocation() {
result = func.getLocation() result = func.getLocation()
} }
/** /**
* Gets the entry point for this function. * Gets the entry point for this function.
*/ */
pragma[noinline] pragma[noinline]
final EnterFunctionInstruction getEnterFunctionInstruction() { final EnterFunctionInstruction getEnterFunctionInstruction() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
/** /**
* Gets the exit point for this function. * Gets the exit point for this function.
*/ */
pragma[noinline] pragma[noinline]
final ExitFunctionInstruction getExitFunctionInstruction() { final ExitFunctionInstruction getExitFunctionInstruction() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
pragma[noinline] pragma[noinline]
final UnmodeledDefinitionInstruction getUnmodeledDefinitionInstruction() { final UnmodeledDefinitionInstruction getUnmodeledDefinitionInstruction() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
/** /**
* Gets the single return instruction for this function. * Gets the single return instruction for this function.
*/ */
pragma[noinline] pragma[noinline]
final ReturnInstruction getReturnInstruction() { final ReturnInstruction getReturnInstruction() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
/** /**
* Gets the variable used to hold the return value of this function. If this * Gets the variable used to hold the return value of this function. If this
* function does not return a value, this predicate does not hold. * function does not return a value, this predicate does not hold.
*/ */
pragma[noinline] pragma[noinline]
final IRReturnVariable getReturnVariable() { final IRReturnVariable getReturnVariable() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
/** /**
* Gets the block containing the entry point of this function. * Gets the block containing the entry point of this function.
*/ */
pragma[noinline] pragma[noinline]
final IRBlock getEntryBlock() { final IRBlock getEntryBlock() {
result.getFirstInstruction() = getEnterFunctionInstruction() result.getFirstInstruction() = getEnterFunctionInstruction()
} }
/** /**
* Gets all instructions in this function. * Gets all instructions in this function.
*/ */
final Instruction getAnInstruction() { final Instruction getAnInstruction() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
/** /**
* Gets all blocks in this function. * Gets all blocks in this function.
*/ */
final IRBlock getABlock() { final IRBlock getABlock() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
} }

View File

@@ -1 +1 @@
import SSAConstruction as Construction import SSAConstruction as Construction

View File

@@ -1,3 +1,3 @@
private import IRImpl private import IRImpl
import InstructionSanity import InstructionSanity

View File

@@ -1,202 +1,202 @@
private import IRInternal private import IRInternal
import FunctionIR import FunctionIR
import cpp import cpp
import semmle.code.cpp.ir.TempVariableTag import semmle.code.cpp.ir.TempVariableTag
private import semmle.code.cpp.ir.internal.TempVariableTag private import semmle.code.cpp.ir.internal.TempVariableTag
private newtype TIRVariable = private newtype TIRVariable =
TIRAutomaticUserVariable(LocalScopeVariable var, FunctionIR funcIR) { TIRAutomaticUserVariable(LocalScopeVariable var, FunctionIR funcIR) {
exists(Function func | exists(Function func |
func = funcIR.getFunction() and func = funcIR.getFunction() and
( (
var.getFunction() = func or var.getFunction() = func or
var.(Parameter).getCatchBlock().getEnclosingFunction() = func var.(Parameter).getCatchBlock().getEnclosingFunction() = func
) )
) )
} or } or
TIRStaticUserVariable(Variable var, FunctionIR funcIR) { TIRStaticUserVariable(Variable var, FunctionIR funcIR) {
( (
var instanceof GlobalOrNamespaceVariable or var instanceof GlobalOrNamespaceVariable or
var instanceof MemberVariable and not var instanceof Field var instanceof MemberVariable and not var instanceof Field
) and ) and
exists(VariableAccess access | exists(VariableAccess access |
access.getTarget() = var and access.getTarget() = var and
access.getEnclosingFunction() = funcIR.getFunction() access.getEnclosingFunction() = funcIR.getFunction()
) )
} or } or
TIRTempVariable(FunctionIR funcIR, Locatable ast, TempVariableTag tag, TIRTempVariable(FunctionIR funcIR, Locatable ast, TempVariableTag tag,
Type type) { Type type) {
Construction::hasTempVariable(funcIR.getFunction(), ast, tag, type) Construction::hasTempVariable(funcIR.getFunction(), ast, tag, type)
} }
IRUserVariable getIRUserVariable(Function func, Variable var) { IRUserVariable getIRUserVariable(Function func, Variable var) {
result.getVariable() = var and result.getVariable() = var and
result.getFunction() = func result.getFunction() = func
} }
/** /**
* Represents a variable referenced by the IR for a function. The variable may * Represents a variable referenced by the IR for a function. The variable may
* be a user-declared variable (`IRUserVariable`) or a temporary variable * be a user-declared variable (`IRUserVariable`) or a temporary variable
* generated by the AST-to-IR translation (`IRTempVariable`). * generated by the AST-to-IR translation (`IRTempVariable`).
*/ */
abstract class IRVariable extends TIRVariable { abstract class IRVariable extends TIRVariable {
FunctionIR funcIR; FunctionIR funcIR;
abstract string toString(); abstract string toString();
/** /**
* Gets the type of the variable. * Gets the type of the variable.
*/ */
abstract Type getType(); abstract Type getType();
/** /**
* Gets the AST node that declared this variable, or that introduced this * Gets the AST node that declared this variable, or that introduced this
* variable as part of the AST-to-IR translation. * variable as part of the AST-to-IR translation.
*/ */
abstract Locatable getAST(); abstract Locatable getAST();
/** /**
* Gets an identifier string for the variable. This identifier is unique * Gets an identifier string for the variable. This identifier is unique
* within the function. * within the function.
*/ */
abstract string getUniqueId(); abstract string getUniqueId();
/** /**
* Gets the source location of this variable. * Gets the source location of this variable.
*/ */
final Location getLocation() { final Location getLocation() {
result = getAST().getLocation() result = getAST().getLocation()
} }
/** /**
* Gets the IR for the function that references this variable. * Gets the IR for the function that references this variable.
*/ */
final FunctionIR getFunctionIR() { final FunctionIR getFunctionIR() {
result = funcIR result = funcIR
} }
/** /**
* Gets the function that references this variable. * Gets the function that references this variable.
*/ */
final Function getFunction() { final Function getFunction() {
result = funcIR.getFunction() result = funcIR.getFunction()
} }
} }
/** /**
* Represents a user-declared variable referenced by the IR for a function. * Represents a user-declared variable referenced by the IR for a function.
*/ */
abstract class IRUserVariable extends IRVariable { abstract class IRUserVariable extends IRVariable {
Variable var; Variable var;
override final string toString() { override final string toString() {
result = var.toString() result = var.toString()
} }
override final Type getType() { override final Type getType() {
result = var.getType().getUnspecifiedType() result = var.getType().getUnspecifiedType()
} }
override final Locatable getAST() { override final Locatable getAST() {
result = var result = var
} }
override final string getUniqueId() { override final string getUniqueId() {
result = var.toString() + " " + var.getLocation().toString() result = var.toString() + " " + var.getLocation().toString()
} }
/** /**
* Gets the original user-declared variable. * Gets the original user-declared variable.
*/ */
final Variable getVariable() { final Variable getVariable() {
result = var result = var
} }
} }
/** /**
* Represents a variable (user-declared or temporary) that is allocated on the * Represents a variable (user-declared or temporary) that is allocated on the
* stack. This includes all parameters, non-static local variables, and * stack. This includes all parameters, non-static local variables, and
* temporary variables. * temporary variables.
*/ */
abstract class IRAutomaticVariable extends IRVariable { abstract class IRAutomaticVariable extends IRVariable {
} }
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable, class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable,
TIRAutomaticUserVariable { TIRAutomaticUserVariable {
LocalScopeVariable localVar; LocalScopeVariable localVar;
IRAutomaticUserVariable() { IRAutomaticUserVariable() {
this = TIRAutomaticUserVariable(localVar, funcIR) and this = TIRAutomaticUserVariable(localVar, funcIR) and
var = localVar var = localVar
} }
final LocalScopeVariable getLocalVariable() { final LocalScopeVariable getLocalVariable() {
result = localVar result = localVar
} }
} }
class IRStaticUserVariable extends IRUserVariable, TIRStaticUserVariable { class IRStaticUserVariable extends IRUserVariable, TIRStaticUserVariable {
IRStaticUserVariable() { IRStaticUserVariable() {
this = TIRStaticUserVariable(var, funcIR) this = TIRStaticUserVariable(var, funcIR)
} }
} }
IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) { IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) {
result.getAST() = ast and result.getAST() = ast and
result.getTag() = tag result.getTag() = tag
} }
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
Locatable ast; Locatable ast;
TempVariableTag tag; TempVariableTag tag;
Type type; Type type;
IRTempVariable() { IRTempVariable() {
this = TIRTempVariable(funcIR, ast, tag, type) this = TIRTempVariable(funcIR, ast, tag, type)
} }
override final Type getType() { override final Type getType() {
result = type result = type
} }
override final Locatable getAST() { override final Locatable getAST() {
result = ast result = ast
} }
override final string getUniqueId() { override final string getUniqueId() {
result = "Temp: " + Construction::getTempVariableUniqueId(this) result = "Temp: " + Construction::getTempVariableUniqueId(this)
} }
final TempVariableTag getTag() { final TempVariableTag getTag() {
result = tag result = tag
} }
override string toString() { override string toString() {
result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" +
ast.getLocation().getStartColumn().toString() ast.getLocation().getStartColumn().toString()
} }
string getBaseString() { string getBaseString() {
result = "#temp" result = "#temp"
} }
} }
class IRReturnVariable extends IRTempVariable { class IRReturnVariable extends IRTempVariable {
IRReturnVariable() { IRReturnVariable() {
tag = ReturnValueTempVar() tag = ReturnValueTempVar()
} }
override final string toString() { override final string toString() {
result = "#return" result = "#return"
} }
} }
class IRThrowVariable extends IRTempVariable { class IRThrowVariable extends IRTempVariable {
IRThrowVariable() { IRThrowVariable() {
tag = ThrowTempVar() tag = ThrowTempVar()
} }
override string getBaseString() { override string getBaseString() {
result = "#throw" result = "#throw"
} }
} }

View File

@@ -1,424 +1,424 @@
import SSAConstructionInternal import SSAConstructionInternal
import cpp import cpp
private import semmle.code.cpp.ir.internal.Opcode private import semmle.code.cpp.ir.internal.Opcode
import NewIR import NewIR
import Cached import Cached
cached private module Cached { cached private module Cached {
private OldIR::OperandTag getOldOperandTag(OperandTag newTag) { private OldIR::OperandTag getOldOperandTag(OperandTag newTag) {
newTag instanceof LoadStoreAddressOperand and result instanceof OldIR::LoadStoreAddressOperand or newTag instanceof LoadStoreAddressOperand and result instanceof OldIR::LoadStoreAddressOperand or
newTag instanceof CopySourceOperand and result instanceof OldIR::CopySourceOperand or newTag instanceof CopySourceOperand and result instanceof OldIR::CopySourceOperand or
newTag instanceof UnaryOperand and result instanceof OldIR::UnaryOperand or newTag instanceof UnaryOperand and result instanceof OldIR::UnaryOperand or
newTag instanceof LeftOperand and result instanceof OldIR::LeftOperand or newTag instanceof LeftOperand and result instanceof OldIR::LeftOperand or
newTag instanceof RightOperand and result instanceof OldIR::RightOperand or newTag instanceof RightOperand and result instanceof OldIR::RightOperand or
newTag instanceof ReturnValueOperand and result instanceof OldIR::ReturnValueOperand or newTag instanceof ReturnValueOperand and result instanceof OldIR::ReturnValueOperand or
newTag instanceof ExceptionOperand and result instanceof OldIR::ExceptionOperand or newTag instanceof ExceptionOperand and result instanceof OldIR::ExceptionOperand or
newTag instanceof ConditionOperand and result instanceof OldIR::ConditionOperand or newTag instanceof ConditionOperand and result instanceof OldIR::ConditionOperand or
newTag instanceof UnmodeledUseOperand and result instanceof OldIR::UnmodeledUseOperand or newTag instanceof UnmodeledUseOperand and result instanceof OldIR::UnmodeledUseOperand or
newTag instanceof CallTargetOperand and result instanceof OldIR::CallTargetOperand or newTag instanceof CallTargetOperand and result instanceof OldIR::CallTargetOperand or
newTag instanceof ThisArgumentOperand and result instanceof OldIR::ThisArgumentOperand or newTag instanceof ThisArgumentOperand and result instanceof OldIR::ThisArgumentOperand or
exists(PositionalArgumentOperand newArg | exists(PositionalArgumentOperand newArg |
newArg = newTag and newArg = newTag and
result.(OldIR::PositionalArgumentOperand).getArgIndex() = newArg.getArgIndex() result.(OldIR::PositionalArgumentOperand).getArgIndex() = newArg.getArgIndex()
) )
} }
private IRBlock getNewBlock(OldIR::IRBlock oldBlock) { private IRBlock getNewBlock(OldIR::IRBlock oldBlock) {
result.getFirstInstruction() = getNewInstruction(oldBlock.getFirstInstruction()) result.getFirstInstruction() = getNewInstruction(oldBlock.getFirstInstruction())
} }
cached newtype TInstructionTag = cached newtype TInstructionTag =
WrappedInstructionTag(OldIR::Instruction oldInstruction) or WrappedInstructionTag(OldIR::Instruction oldInstruction) or
PhiTag(Alias::VirtualVariable vvar, OldIR::IRBlock block) { PhiTag(Alias::VirtualVariable vvar, OldIR::IRBlock block) {
hasPhiNode(vvar, block) hasPhiNode(vvar, block)
} }
cached class InstructionTagType extends TInstructionTag { cached class InstructionTagType extends TInstructionTag {
cached final string toString() { cached final string toString() {
result = "Tag" result = "Tag"
} }
} }
cached predicate functionHasIR(Function func) { cached predicate functionHasIR(Function func) {
exists(OldIR::FunctionIR funcIR | exists(OldIR::FunctionIR funcIR |
funcIR.getFunction() = func funcIR.getFunction() = func
) )
} }
cached int getMaxCallArgIndex() { cached int getMaxCallArgIndex() {
result = max(int argIndex | result = max(int argIndex |
exists(OldIR::PositionalArgumentOperand oldOperand | exists(OldIR::PositionalArgumentOperand oldOperand |
argIndex = oldOperand.getArgIndex() argIndex = oldOperand.getArgIndex()
) )
) )
} }
cached OldIR::Instruction getOldInstruction(Instruction instr) { cached OldIR::Instruction getOldInstruction(Instruction instr) {
instr.getTag() = WrappedInstructionTag(result) instr.getTag() = WrappedInstructionTag(result)
} }
private Instruction getNewInstruction(OldIR::Instruction instr) { private Instruction getNewInstruction(OldIR::Instruction instr) {
getOldInstruction(result) = instr getOldInstruction(result) = instr
} }
private PhiInstruction getPhiInstruction(Function func, OldIR::IRBlock oldBlock, private PhiInstruction getPhiInstruction(Function func, OldIR::IRBlock oldBlock,
Alias::VirtualVariable vvar) { Alias::VirtualVariable vvar) {
result.getFunction() = func and result.getFunction() = func and
result.getAST() = oldBlock.getFirstInstruction().getAST() and result.getAST() = oldBlock.getFirstInstruction().getAST() and
result.getTag() = PhiTag(vvar, oldBlock) result.getTag() = PhiTag(vvar, oldBlock)
} }
private IRVariable getNewIRVariable(OldIR::IRVariable var) { private IRVariable getNewIRVariable(OldIR::IRVariable var) {
result.getFunction() = var.getFunction() and result.getFunction() = var.getFunction() and
( (
exists(OldIR::IRUserVariable userVar, IRUserVariable newUserVar | exists(OldIR::IRUserVariable userVar, IRUserVariable newUserVar |
userVar = var and userVar = var and
newUserVar.getVariable() = userVar.getVariable() and newUserVar.getVariable() = userVar.getVariable() and
result = newUserVar result = newUserVar
) or ) or
exists(OldIR::IRTempVariable tempVar, IRTempVariable newTempVar | exists(OldIR::IRTempVariable tempVar, IRTempVariable newTempVar |
tempVar = var and tempVar = var and
newTempVar.getAST() = tempVar.getAST() and newTempVar.getAST() = tempVar.getAST() and
newTempVar.getTag() = tempVar.getTag() and newTempVar.getTag() = tempVar.getTag() and
result = newTempVar result = newTempVar
) )
) )
} }
cached newtype TInstruction = cached newtype TInstruction =
MkInstruction(FunctionIR funcIR, Opcode opcode, Locatable ast, MkInstruction(FunctionIR funcIR, Opcode opcode, Locatable ast,
InstructionTag tag, Type resultType, boolean isGLValue) { InstructionTag tag, Type resultType, boolean isGLValue) {
hasInstruction(funcIR.getFunction(), opcode, ast, tag, hasInstruction(funcIR.getFunction(), opcode, ast, tag,
resultType, isGLValue) resultType, isGLValue)
} }
private predicate hasInstruction(Function func, Opcode opcode, Locatable ast, private predicate hasInstruction(Function func, Opcode opcode, Locatable ast,
InstructionTag tag, Type resultType, boolean isGLValue) { InstructionTag tag, Type resultType, boolean isGLValue) {
exists(OldIR::Instruction instr | exists(OldIR::Instruction instr |
instr.getFunction() = func and instr.getFunction() = func and
instr.getOpcode() = opcode and instr.getOpcode() = opcode and
instr.getAST() = ast and instr.getAST() = ast and
WrappedInstructionTag(instr) = tag and WrappedInstructionTag(instr) = tag and
instr.getResultType() = resultType and instr.getResultType() = resultType and
if instr.isGLValue() then if instr.isGLValue() then
isGLValue = true isGLValue = true
else else
isGLValue = false isGLValue = false
) or ) or
exists(OldIR::IRBlock block, Alias::VirtualVariable vvar | exists(OldIR::IRBlock block, Alias::VirtualVariable vvar |
hasPhiNode(vvar, block) and hasPhiNode(vvar, block) and
block.getFunction() = func and block.getFunction() = func and
opcode instanceof Opcode::Phi and opcode instanceof Opcode::Phi and
ast = block.getFirstInstruction().getAST() and ast = block.getFirstInstruction().getAST() and
tag = PhiTag(vvar, block) and tag = PhiTag(vvar, block) and
resultType = vvar.getType() and resultType = vvar.getType() and
isGLValue = false isGLValue = false
) )
} }
cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag,
Type type) { Type type) {
exists(OldIR::IRTempVariable var | exists(OldIR::IRTempVariable var |
var.getFunction() = func and var.getFunction() = func and
var.getAST() = ast and var.getAST() = ast and
var.getTag() = tag and var.getTag() = tag and
var.getType() = type var.getType() = type
) )
} }
cached predicate hasModeledMemoryResult(Instruction instruction) { cached predicate hasModeledMemoryResult(Instruction instruction) {
exists(Alias::getResultMemoryAccess(getOldInstruction(instruction))) or exists(Alias::getResultMemoryAccess(getOldInstruction(instruction))) or
instruction instanceof PhiInstruction // Phis always have modeled results instruction instanceof PhiInstruction // Phis always have modeled results
} }
cached Instruction getInstructionOperand(Instruction instruction, OperandTag tag) { cached Instruction getInstructionOperand(Instruction instruction, OperandTag tag) {
exists(OldIR::Instruction oldUse, OldIR::OperandTag oldTag | exists(OldIR::Instruction oldUse, OldIR::OperandTag oldTag |
oldUse = getOldInstruction(instruction) and oldUse = getOldInstruction(instruction) and
oldTag = getOldOperandTag(tag) and oldTag = getOldOperandTag(tag) and
if oldUse.isMemoryOperand(oldTag) then ( if oldUse.isMemoryOperand(oldTag) then (
( (
if exists(Alias::getOperandMemoryAccess(oldUse, oldTag)) then ( if exists(Alias::getOperandMemoryAccess(oldUse, oldTag)) then (
exists(OldIR::IRBlock useBlock, int useRank, Alias::VirtualVariable vvar, exists(OldIR::IRBlock useBlock, int useRank, Alias::VirtualVariable vvar,
OldIR::IRBlock defBlock, int defRank, int defIndex | OldIR::IRBlock defBlock, int defRank, int defIndex |
vvar = Alias::getOperandMemoryAccess(oldUse, oldTag).getVirtualVariable() and vvar = Alias::getOperandMemoryAccess(oldUse, oldTag).getVirtualVariable() and
hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and
hasUseAtRank(vvar, useBlock, useRank, oldUse) and hasUseAtRank(vvar, useBlock, useRank, oldUse) and
definitionReachesUse(vvar, defBlock, defRank, useBlock, useRank) and definitionReachesUse(vvar, defBlock, defRank, useBlock, useRank) and
if defIndex >= 0 then if defIndex >= 0 then
result = getNewInstruction(defBlock.getInstruction(defIndex)) result = getNewInstruction(defBlock.getInstruction(defIndex))
else else
result = getPhiInstruction(instruction.getFunction(), defBlock, vvar) result = getPhiInstruction(instruction.getFunction(), defBlock, vvar)
) )
) )
else ( else (
result = instruction.getFunctionIR().getUnmodeledDefinitionInstruction() result = instruction.getFunctionIR().getUnmodeledDefinitionInstruction()
) )
) or ) or
// Connect any definitions that are not being modeled in SSA to the // Connect any definitions that are not being modeled in SSA to the
// `UnmodeledUse` instruction. // `UnmodeledUse` instruction.
exists(OldIR::Instruction oldDefinition | exists(OldIR::Instruction oldDefinition |
instruction instanceof UnmodeledUseInstruction and instruction instanceof UnmodeledUseInstruction and
tag instanceof UnmodeledUseOperand and tag instanceof UnmodeledUseOperand and
oldDefinition = oldUse.getOperand(oldTag) and oldDefinition = oldUse.getOperand(oldTag) and
not exists(Alias::getResultMemoryAccess(oldDefinition)) and not exists(Alias::getResultMemoryAccess(oldDefinition)) and
result = getNewInstruction(oldDefinition) result = getNewInstruction(oldDefinition)
) )
) )
else else
result = getNewInstruction(oldUse.getOperand(oldTag)) result = getNewInstruction(oldUse.getOperand(oldTag))
) or ) or
result = getPhiInstructionOperand(instruction.(PhiInstruction), tag.(PhiOperand)) result = getPhiInstructionOperand(instruction.(PhiInstruction), tag.(PhiOperand))
} }
cached Instruction getPhiInstructionOperand(PhiInstruction instr, PhiOperand tag) { cached Instruction getPhiInstructionOperand(PhiInstruction instr, PhiOperand tag) {
exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock, exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock,
OldIR::IRBlock defBlock, int defRank, int defIndex, OldIR::IRBlock predBlock | OldIR::IRBlock defBlock, int defRank, int defIndex, OldIR::IRBlock predBlock |
hasPhiNode(vvar, phiBlock) and hasPhiNode(vvar, phiBlock) and
predBlock = phiBlock.getAPredecessor() and predBlock = phiBlock.getAPredecessor() and
instr.getTag() = PhiTag(vvar, phiBlock) and instr.getTag() = PhiTag(vvar, phiBlock) and
tag.getPredecessorBlock() = getNewBlock(predBlock) and tag.getPredecessorBlock() = getNewBlock(predBlock) and
hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and
definitionReachesEndOfBlock(vvar, defBlock, defRank, predBlock) and definitionReachesEndOfBlock(vvar, defBlock, defRank, predBlock) and
if defIndex >= 0 then if defIndex >= 0 then
result = getNewInstruction(defBlock.getInstruction(defIndex)) result = getNewInstruction(defBlock.getInstruction(defIndex))
else else
result = getPhiInstruction(instr.getFunction(), defBlock, vvar) result = getPhiInstruction(instr.getFunction(), defBlock, vvar)
) )
} }
cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) { cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) {
exists(OldIR::IRBlock oldBlock | exists(OldIR::IRBlock oldBlock |
instr.getTag() = PhiTag(_, oldBlock) and instr.getTag() = PhiTag(_, oldBlock) and
result = getNewInstruction(oldBlock.getFirstInstruction()) result = getNewInstruction(oldBlock.getFirstInstruction())
) )
} }
cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) { cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
result = getNewInstruction(getOldInstruction(instruction).getSuccessor(kind)) result = getNewInstruction(getOldInstruction(instruction).getSuccessor(kind))
} }
cached IRVariable getInstructionVariable(Instruction instruction) { cached IRVariable getInstructionVariable(Instruction instruction) {
result = getNewIRVariable(getOldInstruction(instruction).(OldIR::VariableInstruction).getVariable()) result = getNewIRVariable(getOldInstruction(instruction).(OldIR::VariableInstruction).getVariable())
} }
cached Field getInstructionField(Instruction instruction) { cached Field getInstructionField(Instruction instruction) {
result = getOldInstruction(instruction).(OldIR::FieldInstruction).getField() result = getOldInstruction(instruction).(OldIR::FieldInstruction).getField()
} }
cached Function getInstructionFunction(Instruction instruction) { cached Function getInstructionFunction(Instruction instruction) {
result = getOldInstruction(instruction).(OldIR::FunctionInstruction).getFunctionSymbol() result = getOldInstruction(instruction).(OldIR::FunctionInstruction).getFunctionSymbol()
} }
cached string getInstructionConstantValue(Instruction instruction) { cached string getInstructionConstantValue(Instruction instruction) {
result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue() result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue()
} }
cached StringLiteral getInstructionStringLiteral(Instruction instruction) { cached StringLiteral getInstructionStringLiteral(Instruction instruction) {
result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue() result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue()
} }
cached Type getInstructionExceptionType(Instruction instruction) { cached Type getInstructionExceptionType(Instruction instruction) {
result = getOldInstruction(instruction).(OldIR::CatchByTypeInstruction).getExceptionType() result = getOldInstruction(instruction).(OldIR::CatchByTypeInstruction).getExceptionType()
} }
cached int getInstructionElementSize(Instruction instruction) { cached int getInstructionElementSize(Instruction instruction) {
result = getOldInstruction(instruction).(OldIR::PointerArithmeticInstruction).getElementSize() result = getOldInstruction(instruction).(OldIR::PointerArithmeticInstruction).getElementSize()
} }
cached int getInstructionResultSize(Instruction instruction) { cached int getInstructionResultSize(Instruction instruction) {
// Only return a result for instructions that needed an explicit result size. // Only return a result for instructions that needed an explicit result size.
instruction.getResultType() instanceof UnknownType and instruction.getResultType() instanceof UnknownType and
result = getOldInstruction(instruction).getResultSize() result = getOldInstruction(instruction).getResultSize()
} }
cached predicate getInstructionInheritance(Instruction instruction, Class baseClass, cached predicate getInstructionInheritance(Instruction instruction, Class baseClass,
Class derivedClass) { Class derivedClass) {
exists(OldIR::InheritanceConversionInstruction oldInstr | exists(OldIR::InheritanceConversionInstruction oldInstr |
oldInstr = getOldInstruction(instruction) and oldInstr = getOldInstruction(instruction) and
baseClass = oldInstr.getBaseClass() and baseClass = oldInstr.getBaseClass() and
derivedClass = oldInstr.getDerivedClass() derivedClass = oldInstr.getDerivedClass()
) )
} }
private predicate ssa_variableUpdate(Alias::VirtualVariable vvar, private predicate ssa_variableUpdate(Alias::VirtualVariable vvar,
OldIR::Instruction instr, OldIR::IRBlock block, int index) { OldIR::Instruction instr, OldIR::IRBlock block, int index) {
block.getInstruction(index) = instr and block.getInstruction(index) = instr and
Alias::getResultMemoryAccess(instr).getVirtualVariable() = vvar Alias::getResultMemoryAccess(instr).getVirtualVariable() = vvar
} }
private predicate hasDefinition(Alias::VirtualVariable vvar, OldIR::IRBlock block, int index) { private predicate hasDefinition(Alias::VirtualVariable vvar, OldIR::IRBlock block, int index) {
( (
hasPhiNode(vvar, block) and hasPhiNode(vvar, block) and
index = -1 index = -1
) or ) or
exists(Alias::MemoryAccess access, OldIR::Instruction def | exists(Alias::MemoryAccess access, OldIR::Instruction def |
access = Alias::getResultMemoryAccess(def) and access = Alias::getResultMemoryAccess(def) and
block.getInstruction(index) = def and block.getInstruction(index) = def and
vvar = access.getVirtualVariable() vvar = access.getVirtualVariable()
) )
} }
private predicate defUseRank(Alias::VirtualVariable vvar, OldIR::IRBlock block, int rankIndex, int index) { private predicate defUseRank(Alias::VirtualVariable vvar, OldIR::IRBlock block, int rankIndex, int index) {
index = rank[rankIndex](int j | hasDefinition(vvar, block, j) or hasUse(vvar, _, block, j)) index = rank[rankIndex](int j | hasDefinition(vvar, block, j) or hasUse(vvar, _, block, j))
} }
private predicate hasUse(Alias::VirtualVariable vvar, private predicate hasUse(Alias::VirtualVariable vvar,
OldIR::Instruction use, OldIR::IRBlock block, int index) { OldIR::Instruction use, OldIR::IRBlock block, int index) {
exists(Alias::MemoryAccess access | exists(Alias::MemoryAccess access |
access = Alias::getOperandMemoryAccess(use, _) and access = Alias::getOperandMemoryAccess(use, _) and
block.getInstruction(index) = use and block.getInstruction(index) = use and
vvar = access.getVirtualVariable() vvar = access.getVirtualVariable()
) )
} }
private predicate variableLiveOnEntryToBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) { private predicate variableLiveOnEntryToBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) {
exists (int index | hasUse(vvar, _, block, index) | exists (int index | hasUse(vvar, _, block, index) |
not exists (int j | ssa_variableUpdate(vvar, _, block, j) | j < index) not exists (int j | ssa_variableUpdate(vvar, _, block, j) | j < index)
) or ) or
(variableLiveOnExitFromBlock(vvar, block) and not ssa_variableUpdate(vvar, _, block, _)) (variableLiveOnExitFromBlock(vvar, block) and not ssa_variableUpdate(vvar, _, block, _))
} }
pragma[noinline] pragma[noinline]
private predicate variableLiveOnExitFromBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) { private predicate variableLiveOnExitFromBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) {
variableLiveOnEntryToBlock(vvar, block.getASuccessor()) variableLiveOnEntryToBlock(vvar, block.getASuccessor())
} }
/** /**
* Gets the rank index of a hyphothetical use one instruction past the end of * Gets the rank index of a hyphothetical use one instruction past the end of
* the block. This index can be used to determine if a definition reaches the * the block. This index can be used to determine if a definition reaches the
* end of the block, even if the definition is the last instruction in the * end of the block, even if the definition is the last instruction in the
* block. * block.
*/ */
private int exitRank(Alias::VirtualVariable vvar, OldIR::IRBlock block) { private int exitRank(Alias::VirtualVariable vvar, OldIR::IRBlock block) {
result = max(int rankIndex | defUseRank(vvar, block, rankIndex, _)) + 1 result = max(int rankIndex | defUseRank(vvar, block, rankIndex, _)) + 1
} }
private predicate hasDefinitionAtRank(Alias::VirtualVariable vvar, private predicate hasDefinitionAtRank(Alias::VirtualVariable vvar,
OldIR::IRBlock block, int rankIndex, int instructionIndex) { OldIR::IRBlock block, int rankIndex, int instructionIndex) {
hasDefinition(vvar, block, instructionIndex) and hasDefinition(vvar, block, instructionIndex) and
defUseRank(vvar, block, rankIndex, instructionIndex) defUseRank(vvar, block, rankIndex, instructionIndex)
} }
private predicate hasUseAtRank(Alias::VirtualVariable vvar, OldIR::IRBlock block, private predicate hasUseAtRank(Alias::VirtualVariable vvar, OldIR::IRBlock block,
int rankIndex, OldIR::Instruction use) { int rankIndex, OldIR::Instruction use) {
exists(int index | exists(int index |
hasUse(vvar, use, block, index) and hasUse(vvar, use, block, index) and
defUseRank(vvar, block, rankIndex, index) defUseRank(vvar, block, rankIndex, index)
) )
} }
/** /**
* Holds if the definition of `vvar` at `(block, defRank)` reaches the rank * Holds if the definition of `vvar` at `(block, defRank)` reaches the rank
* index `reachesRank` in block `block`. * index `reachesRank` in block `block`.
*/ */
private predicate definitionReachesRank(Alias::VirtualVariable vvar, private predicate definitionReachesRank(Alias::VirtualVariable vvar,
OldIR::IRBlock block, int defRank, int reachesRank) { OldIR::IRBlock block, int defRank, int reachesRank) {
hasDefinitionAtRank(vvar, block, defRank, _) and hasDefinitionAtRank(vvar, block, defRank, _) and
reachesRank <= exitRank(vvar, block) and // Without this, the predicate would be infinite. reachesRank <= exitRank(vvar, block) and // Without this, the predicate would be infinite.
( (
// The def always reaches the next use, even if there is also a def on the // The def always reaches the next use, even if there is also a def on the
// use instruction. // use instruction.
reachesRank = defRank + 1 or reachesRank = defRank + 1 or
( (
// If the def reached the previous rank, it also reaches the current rank, // If the def reached the previous rank, it also reaches the current rank,
// unless there was another def at the previous rank. // unless there was another def at the previous rank.
definitionReachesRank(vvar, block, defRank, reachesRank - 1) and definitionReachesRank(vvar, block, defRank, reachesRank - 1) and
not hasDefinitionAtRank(vvar, block, reachesRank - 1, _) not hasDefinitionAtRank(vvar, block, reachesRank - 1, _)
) )
) )
} }
/** /**
* Holds if the definition of `vvar` at `(defBlock, defRank)` reaches the end of * Holds if the definition of `vvar` at `(defBlock, defRank)` reaches the end of
* block `block`. * block `block`.
*/ */
private predicate definitionReachesEndOfBlock(Alias::VirtualVariable vvar, private predicate definitionReachesEndOfBlock(Alias::VirtualVariable vvar,
OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock block) { OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock block) {
hasDefinitionAtRank(vvar, defBlock, defRank, _) and hasDefinitionAtRank(vvar, defBlock, defRank, _) and
( (
( (
// If we're looking at the def's own block, just see if it reaches the exit // If we're looking at the def's own block, just see if it reaches the exit
// rank of the block. // rank of the block.
block = defBlock and block = defBlock and
variableLiveOnExitFromBlock(vvar, defBlock) and variableLiveOnExitFromBlock(vvar, defBlock) and
definitionReachesRank(vvar, defBlock, defRank, exitRank(vvar, defBlock)) definitionReachesRank(vvar, defBlock, defRank, exitRank(vvar, defBlock))
) or ) or
exists(OldIR::IRBlock idom | exists(OldIR::IRBlock idom |
definitionReachesEndOfBlock(vvar, defBlock, defRank, idom) and definitionReachesEndOfBlock(vvar, defBlock, defRank, idom) and
noDefinitionsSinceIDominator(vvar, idom, block) noDefinitionsSinceIDominator(vvar, idom, block)
) )
) )
} }
pragma[noinline] pragma[noinline]
private predicate noDefinitionsSinceIDominator(Alias::VirtualVariable vvar, private predicate noDefinitionsSinceIDominator(Alias::VirtualVariable vvar,
OldIR::IRBlock idom, OldIR::IRBlock block) { OldIR::IRBlock idom, OldIR::IRBlock block) {
idom.immediatelyDominates(block) and // It is sufficient to traverse the dominator graph, cf. discussion above. idom.immediatelyDominates(block) and // It is sufficient to traverse the dominator graph, cf. discussion above.
variableLiveOnExitFromBlock(vvar, block) and variableLiveOnExitFromBlock(vvar, block) and
not hasDefinition(vvar, block, _) not hasDefinition(vvar, block, _)
} }
private predicate definitionReachesUseWithinBlock( private predicate definitionReachesUseWithinBlock(
Alias::VirtualVariable vvar, OldIR::IRBlock defBlock, int defRank, Alias::VirtualVariable vvar, OldIR::IRBlock defBlock, int defRank,
OldIR::IRBlock useBlock, int useRank) { OldIR::IRBlock useBlock, int useRank) {
defBlock = useBlock and defBlock = useBlock and
hasDefinitionAtRank(vvar, defBlock, defRank, _) and hasDefinitionAtRank(vvar, defBlock, defRank, _) and
hasUseAtRank(vvar, useBlock, useRank, _) and hasUseAtRank(vvar, useBlock, useRank, _) and
definitionReachesRank(vvar, defBlock, defRank, useRank) definitionReachesRank(vvar, defBlock, defRank, useRank)
} }
private predicate definitionReachesUse(Alias::VirtualVariable vvar, private predicate definitionReachesUse(Alias::VirtualVariable vvar,
OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock useBlock, int useRank) { OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock useBlock, int useRank) {
hasUseAtRank(vvar, useBlock, useRank, _) and hasUseAtRank(vvar, useBlock, useRank, _) and
( (
definitionReachesUseWithinBlock(vvar, defBlock, defRank, useBlock, definitionReachesUseWithinBlock(vvar, defBlock, defRank, useBlock,
useRank) or useRank) or
( (
definitionReachesEndOfBlock(vvar, defBlock, defRank, definitionReachesEndOfBlock(vvar, defBlock, defRank,
useBlock.getAPredecessor()) and useBlock.getAPredecessor()) and
not definitionReachesUseWithinBlock(vvar, useBlock, _, useBlock, useRank) not definitionReachesUseWithinBlock(vvar, useBlock, _, useBlock, useRank)
) )
) )
} }
private predicate hasFrontierPhiNode(Alias::VirtualVariable vvar, private predicate hasFrontierPhiNode(Alias::VirtualVariable vvar,
OldIR::IRBlock phiBlock) { OldIR::IRBlock phiBlock) {
exists(OldIR::IRBlock defBlock | exists(OldIR::IRBlock defBlock |
phiBlock = defBlock.dominanceFrontier() and phiBlock = defBlock.dominanceFrontier() and
hasDefinition(vvar, defBlock, _) and hasDefinition(vvar, defBlock, _) and
/* We can also eliminate those nodes where the variable is not live on any incoming edge */ /* We can also eliminate those nodes where the variable is not live on any incoming edge */
variableLiveOnEntryToBlock(vvar, phiBlock) variableLiveOnEntryToBlock(vvar, phiBlock)
) )
} }
private predicate hasPhiNode(Alias::VirtualVariable vvar, private predicate hasPhiNode(Alias::VirtualVariable vvar,
OldIR::IRBlock phiBlock) { OldIR::IRBlock phiBlock) {
hasFrontierPhiNode(vvar, phiBlock) hasFrontierPhiNode(vvar, phiBlock)
//or ssa_sanitized_custom_phi_node(vvar, block) //or ssa_sanitized_custom_phi_node(vvar, block)
} }
} }
import CachedForDebugging import CachedForDebugging
cached private module CachedForDebugging { cached private module CachedForDebugging {
cached string getTempVariableUniqueId(IRTempVariable var) { cached string getTempVariableUniqueId(IRTempVariable var) {
result = getOldTempVariable(var).getUniqueId() result = getOldTempVariable(var).getUniqueId()
} }
cached string getInstructionUniqueId(Instruction instr) { cached string getInstructionUniqueId(Instruction instr) {
exists(OldIR::Instruction oldInstr | exists(OldIR::Instruction oldInstr |
oldInstr = getOldInstruction(instr) and oldInstr = getOldInstruction(instr) and
result = "NonSSA: " + oldInstr.getUniqueId() result = "NonSSA: " + oldInstr.getUniqueId()
) or ) or
exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock | exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock |
instr.getTag() = PhiTag(vvar, phiBlock) and instr.getTag() = PhiTag(vvar, phiBlock) and
result = "Phi Block(" + phiBlock.getUniqueId() + "): " + vvar.getUniqueId() result = "Phi Block(" + phiBlock.getUniqueId() + "): " + vvar.getUniqueId()
) )
} }
private OldIR::IRTempVariable getOldTempVariable(IRTempVariable var) { private OldIR::IRTempVariable getOldTempVariable(IRTempVariable var) {
result.getFunction() = var.getFunction() and result.getFunction() = var.getFunction() and
result.getAST() = var.getAST() and result.getAST() = var.getAST() and
result.getTag() = var.getTag() result.getTag() = var.getTag()
} }
} }

View File

@@ -1,3 +1,3 @@
import semmle.code.cpp.ssa.SSAIR as OldIR import semmle.code.cpp.ssa.SSAIR as OldIR
import semmle.code.cpp.ssa.AliasedSSAIR as NewIR import semmle.code.cpp.ssa.AliasedSSAIR as NewIR
import SimpleSSA as Alias import SimpleSSA as Alias

View File

@@ -1,83 +1,83 @@
import SimpleSSAInternal import SimpleSSAInternal
import cpp import cpp
import Alias import Alias
import IR import IR
import semmle.code.cpp.ssa.internal.Overlap import semmle.code.cpp.ssa.internal.Overlap
private newtype TVirtualVariable = private newtype TVirtualVariable =
MkVirtualVariable(IRVariable var) { MkVirtualVariable(IRVariable var) {
not variableAddressEscapes(var) not variableAddressEscapes(var)
} }
private VirtualVariable getVirtualVariable(IRVariable var) { private VirtualVariable getVirtualVariable(IRVariable var) {
result.getIRVariable() = var result.getIRVariable() = var
} }
class VirtualVariable extends TVirtualVariable { class VirtualVariable extends TVirtualVariable {
IRVariable var; IRVariable var;
VirtualVariable() { VirtualVariable() {
this = MkVirtualVariable(var) this = MkVirtualVariable(var)
} }
final string toString() { final string toString() {
result = var.toString() result = var.toString()
} }
final IRVariable getIRVariable() { final IRVariable getIRVariable() {
result = var result = var
} }
// REVIEW: This should just be on MemoryAccess // REVIEW: This should just be on MemoryAccess
final Type getType() { final Type getType() {
result = var.getType() result = var.getType()
} }
final string getUniqueId() { final string getUniqueId() {
result = var.getUniqueId() result = var.getUniqueId()
} }
} }
private newtype TMemoryAccess = private newtype TMemoryAccess =
MkMemoryAccess(VirtualVariable vvar) MkMemoryAccess(VirtualVariable vvar)
private MemoryAccess getMemoryAccess(IRVariable var) { private MemoryAccess getMemoryAccess(IRVariable var) {
result.getVirtualVariable() = getVirtualVariable(var) result.getVirtualVariable() = getVirtualVariable(var)
} }
class MemoryAccess extends TMemoryAccess { class MemoryAccess extends TMemoryAccess {
VirtualVariable vvar; VirtualVariable vvar;
MemoryAccess() { MemoryAccess() {
this = MkMemoryAccess(vvar) this = MkMemoryAccess(vvar)
} }
string toString() { string toString() {
result = vvar.toString() result = vvar.toString()
} }
VirtualVariable getVirtualVariable() { VirtualVariable getVirtualVariable() {
result = vvar result = vvar
} }
} }
Overlap getOverlap(MemoryAccess def, MemoryAccess use) { Overlap getOverlap(MemoryAccess def, MemoryAccess use) {
def.getVirtualVariable() = use.getVirtualVariable() and def.getVirtualVariable() = use.getVirtualVariable() and
result instanceof MustExactlyOverlap result instanceof MustExactlyOverlap
} }
MemoryAccess getResultMemoryAccess(Instruction instr) { MemoryAccess getResultMemoryAccess(Instruction instr) {
exists(IRVariable var | exists(IRVariable var |
instr.getResultMemoryAccess() instanceof IndirectMemoryAccess and instr.getResultMemoryAccess() instanceof IndirectMemoryAccess and
resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and
result = getMemoryAccess(var) result = getMemoryAccess(var)
) )
} }
MemoryAccess getOperandMemoryAccess(Instruction instr, OperandTag tag) { MemoryAccess getOperandMemoryAccess(Instruction instr, OperandTag tag) {
exists(IRVariable var | exists(IRVariable var |
instr.getOperandMemoryAccess(tag) instanceof IndirectMemoryAccess and instr.getOperandMemoryAccess(tag) instanceof IndirectMemoryAccess and
resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and
result = getMemoryAccess(var) result = getMemoryAccess(var)
) )
} }

View File

@@ -1,3 +1,3 @@
import AliasAnalysis as Alias import AliasAnalysis as Alias
import semmle.code.cpp.ssa.SSAIR as IR import semmle.code.cpp.ssa.SSAIR as IR

View File

@@ -1,214 +1,214 @@
private import AliasAnalysisInternal private import AliasAnalysisInternal
import cpp import cpp
private import IR private import IR
private import semmle.code.cpp.ssa.internal.IntegerConstant as Ints private import semmle.code.cpp.ssa.internal.IntegerConstant as Ints
private class IntValue = Ints::IntValue; private class IntValue = Ints::IntValue;
/** /**
* Converts the bit count in `bits` to a byte count and a bit count in the form * Converts the bit count in `bits` to a byte count and a bit count in the form
* bytes:bits. * bytes:bits.
*/ */
bindingset[bits] bindingset[bits]
string bitsToBytesAndBits(int bits) { string bitsToBytesAndBits(int bits) {
result = (bits / 8).toString() + ":" + (bits % 8).toString() result = (bits / 8).toString() + ":" + (bits % 8).toString()
} }
/** /**
* Gets a printable string for a bit offset with possibly unknown value. * Gets a printable string for a bit offset with possibly unknown value.
*/ */
bindingset[bitOffset] bindingset[bitOffset]
string getBitOffsetString(IntValue bitOffset) { string getBitOffsetString(IntValue bitOffset) {
if Ints::hasValue(bitOffset) then if Ints::hasValue(bitOffset) then
if bitOffset >= 0 then if bitOffset >= 0 then
result = "+" + bitsToBytesAndBits(bitOffset) result = "+" + bitsToBytesAndBits(bitOffset)
else else
result = "-" + bitsToBytesAndBits(Ints::neg(bitOffset)) result = "-" + bitsToBytesAndBits(Ints::neg(bitOffset))
else else
result = "+?" result = "+?"
} }
/** /**
* Gets the offset of field `field` in bits. * Gets the offset of field `field` in bits.
*/ */
private IntValue getFieldBitOffset(Field field) { private IntValue getFieldBitOffset(Field field) {
if (field instanceof BitField) then ( if (field instanceof BitField) then (
result = Ints::add(Ints::mul(field.getByteOffset(), 8), result = Ints::add(Ints::mul(field.getByteOffset(), 8),
field.(BitField).getBitOffset()) field.(BitField).getBitOffset())
) )
else ( else (
result = Ints::mul(field.getByteOffset(), 8) result = Ints::mul(field.getByteOffset(), 8)
) )
} }
/** /**
* Holds if the operand `tag` of instruction `instr` is used in a way that does * Holds if the operand `tag` of instruction `instr` is used in a way that does
* not result in any address held in that operand from escaping beyond the * not result in any address held in that operand from escaping beyond the
* instruction. * instruction.
*/ */
predicate operandIsConsumedWithoutEscaping(Instruction instr, OperandTag tag) { predicate operandIsConsumedWithoutEscaping(Instruction instr, OperandTag tag) {
exists(instr.getOperand(tag)) and exists(instr.getOperand(tag)) and
( (
// The source/destination address of a Load/Store does not escape (but the // The source/destination address of a Load/Store does not escape (but the
// loaded/stored value could). // loaded/stored value could).
tag instanceof LoadStoreAddressOperand or tag instanceof LoadStoreAddressOperand or
// Neither operand of a Compare escapes. // Neither operand of a Compare escapes.
instr instanceof CompareInstruction or instr instanceof CompareInstruction or
// Neither operand of a PointerDiff escapes. // Neither operand of a PointerDiff escapes.
instr instanceof PointerDiffInstruction or instr instanceof PointerDiffInstruction or
// Converting an address to a `bool` does not escape the address. // Converting an address to a `bool` does not escape the address.
instr.(ConvertInstruction).getResultType() instanceof BoolType instr.(ConvertInstruction).getResultType() instanceof BoolType
) )
} }
/** /**
* If the result of instruction `instr` is an integer constant, returns the * If the result of instruction `instr` is an integer constant, returns the
* value of that constant. Otherwise, returns unknown. * value of that constant. Otherwise, returns unknown.
*/ */
IntValue getConstantValue(Instruction instr) { IntValue getConstantValue(Instruction instr) {
if instr instanceof IntegerConstantInstruction then if instr instanceof IntegerConstantInstruction then
result = instr.(IntegerConstantInstruction).getValue().toInt() result = instr.(IntegerConstantInstruction).getValue().toInt()
else else
result = Ints::unknown() result = Ints::unknown()
} }
/** /**
* Computes the offset, in bits, by which the result of `instr` differs from the * Computes the offset, in bits, by which the result of `instr` differs from the
* pointer argument to `instr`, if that offset is a constant. Otherwise, returns * pointer argument to `instr`, if that offset is a constant. Otherwise, returns
* unknown. * unknown.
*/ */
IntValue getPointerBitOffset(PointerOffsetInstruction instr) { IntValue getPointerBitOffset(PointerOffsetInstruction instr) {
exists(IntValue bitOffset | exists(IntValue bitOffset |
( (
bitOffset = Ints::mul(Ints::mul(getConstantValue(instr.getRightOperand()), bitOffset = Ints::mul(Ints::mul(getConstantValue(instr.getRightOperand()),
instr.getElementSize()), 8) instr.getElementSize()), 8)
) and ) and
( (
instr instanceof PointerAddInstruction and result = bitOffset or instr instanceof PointerAddInstruction and result = bitOffset or
instr instanceof PointerSubInstruction and result = Ints::neg(bitOffset) instr instanceof PointerSubInstruction and result = Ints::neg(bitOffset)
) )
) )
} }
/** /**
* Holds if any address held in operand `tag` of instruction `instr` is * Holds if any address held in operand `tag` of instruction `instr` is
* propagated to the result of `instr`, offset by the number of bits in * propagated to the result of `instr`, offset by the number of bits in
* `bitOffset`. If the address is propagated, but the offset is not known to be * `bitOffset`. If the address is propagated, but the offset is not known to be
* a constant, then `bitOffset` is unknown. * a constant, then `bitOffset` is unknown.
*/ */
predicate operandIsPropagated(Instruction instr, OperandTag tag, predicate operandIsPropagated(Instruction instr, OperandTag tag,
IntValue bitOffset) { IntValue bitOffset) {
exists(instr.getOperand(tag)) and exists(instr.getOperand(tag)) and
( (
// Converting to a non-virtual base class adds the offset of the base class. // Converting to a non-virtual base class adds the offset of the base class.
exists(ConvertToBaseInstruction convert | exists(ConvertToBaseInstruction convert |
convert = instr and convert = instr and
bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8) bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8)
) or ) or
// Converting to a derived class subtracts the offset of the base class. // Converting to a derived class subtracts the offset of the base class.
exists(ConvertToDerivedInstruction convert | exists(ConvertToDerivedInstruction convert |
convert = instr and convert = instr and
bitOffset = Ints::neg(Ints::mul(convert.getDerivation().getByteOffset(), 8)) bitOffset = Ints::neg(Ints::mul(convert.getDerivation().getByteOffset(), 8))
) or ) or
// Converting to a virtual base class adds an unknown offset. // Converting to a virtual base class adds an unknown offset.
( (
instr instanceof ConvertToVirtualBaseInstruction and instr instanceof ConvertToVirtualBaseInstruction and
bitOffset = Ints::unknown() bitOffset = Ints::unknown()
) or ) or
// Conversion to another pointer type propagates the source address. // Conversion to another pointer type propagates the source address.
exists(ConvertInstruction convert, Type resultType | exists(ConvertInstruction convert, Type resultType |
convert = instr and convert = instr and
resultType = convert.getResultType() and resultType = convert.getResultType() and
( (
resultType instanceof PointerType or resultType instanceof PointerType or
resultType instanceof Class //REVIEW: Remove when all glvalues are pointers resultType instanceof Class //REVIEW: Remove when all glvalues are pointers
) and ) and
bitOffset = 0 bitOffset = 0
) or ) or
// Adding an integer to or subtracting an integer from a pointer propagates // Adding an integer to or subtracting an integer from a pointer propagates
// the address with an offset. // the address with an offset.
bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction)) or bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction)) or
// Computing a field address from a pointer propagates the address plus the // Computing a field address from a pointer propagates the address plus the
// offset of the field. // offset of the field.
bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) or bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) or
// A copy propagates the source value. // A copy propagates the source value.
tag instanceof CopySourceOperand and bitOffset = 0 tag instanceof CopySourceOperand and bitOffset = 0
) )
} }
/** /**
* Holds if any address held in operand number `tag` of instruction `instr` * Holds if any address held in operand number `tag` of instruction `instr`
* escapes outside the domain of the analysis. * escapes outside the domain of the analysis.
*/ */
predicate operandEscapes(Instruction instr, OperandTag tag) { predicate operandEscapes(Instruction instr, OperandTag tag) {
exists(instr.getOperand(tag)) and exists(instr.getOperand(tag)) and
// Conservatively assume that the address escapes unless one of the following // Conservatively assume that the address escapes unless one of the following
// holds: // holds:
not ( not (
// The operand is used in a way that does not escape the instruction // The operand is used in a way that does not escape the instruction
operandIsConsumedWithoutEscaping(instr, tag) or operandIsConsumedWithoutEscaping(instr, tag) or
// The address is propagated to the result of the instruction, but that // The address is propagated to the result of the instruction, but that
// result does not itself escape. // result does not itself escape.
operandIsPropagated(instr, tag, _) and not resultEscapes(instr) operandIsPropagated(instr, tag, _) and not resultEscapes(instr)
) )
} }
/** /**
* Holds if any address held in the result of instruction `instr` escapes * Holds if any address held in the result of instruction `instr` escapes
* outside the domain of the analysis. * outside the domain of the analysis.
*/ */
predicate resultEscapes(Instruction instr) { predicate resultEscapes(Instruction instr) {
// The result escapes if it has at least one use that escapes. // The result escapes if it has at least one use that escapes.
exists(Instruction useInstr, OperandTag useOperandTag | exists(Instruction useInstr, OperandTag useOperandTag |
useInstr.getOperand(useOperandTag) = instr and useInstr.getOperand(useOperandTag) = instr and
operandEscapes(useInstr, useOperandTag) operandEscapes(useInstr, useOperandTag)
) )
} }
/** /**
* Holds if the address of the specified local variable or parameter escapes the * Holds if the address of the specified local variable or parameter escapes the
* domain of the analysis. * domain of the analysis.
*/ */
private predicate automaticVariableAddressEscapes(IRAutomaticVariable var) { private predicate automaticVariableAddressEscapes(IRAutomaticVariable var) {
exists(FunctionIR funcIR | exists(FunctionIR funcIR |
funcIR = var.getFunctionIR() and funcIR = var.getFunctionIR() and
// The variable's address escapes if the result of any // The variable's address escapes if the result of any
// VariableAddressInstruction that computes the variable's address escapes. // VariableAddressInstruction that computes the variable's address escapes.
exists(VariableAddressInstruction instr | exists(VariableAddressInstruction instr |
instr.getFunctionIR() = funcIR and instr.getFunctionIR() = funcIR and
instr.getVariable() = var and instr.getVariable() = var and
resultEscapes(instr) resultEscapes(instr)
) )
) )
} }
/** /**
* Holds if the address of the specified variable escapes the domain of the * Holds if the address of the specified variable escapes the domain of the
* analysis. * analysis.
*/ */
predicate variableAddressEscapes(IRVariable var) { predicate variableAddressEscapes(IRVariable var) {
automaticVariableAddressEscapes(var.(IRAutomaticVariable)) or automaticVariableAddressEscapes(var.(IRAutomaticVariable)) or
// All variables with static storage duration have their address escape. // All variables with static storage duration have their address escape.
not var instanceof IRAutomaticVariable not var instanceof IRAutomaticVariable
} }
/** /**
* Holds if the result of instruction `instr` points within variable `var`, at * Holds if the result of instruction `instr` points within variable `var`, at
* bit offset `bitOffset` within the variable. If the result points within * bit offset `bitOffset` within the variable. If the result points within
* `var`, but at an unknown or non-constant offset, then `bitOffset` is unknown. * `var`, but at an unknown or non-constant offset, then `bitOffset` is unknown.
*/ */
predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) { predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) {
( (
// The address of a variable points to that variable, at offset 0. // The address of a variable points to that variable, at offset 0.
instr.(VariableAddressInstruction).getVariable() = var and instr.(VariableAddressInstruction).getVariable() = var and
bitOffset = 0 bitOffset = 0
) or ) or
exists(OperandTag operandTag, IntValue originalBitOffset, exists(OperandTag operandTag, IntValue originalBitOffset,
IntValue propagatedBitOffset | IntValue propagatedBitOffset |
// If an operand is propagated, then the result points to the same variable, // If an operand is propagated, then the result points to the same variable,
// offset by the bit offset from the propagation. // offset by the bit offset from the propagation.
resultPointsTo(instr.getOperand(operandTag), var, originalBitOffset) and resultPointsTo(instr.getOperand(operandTag), var, originalBitOffset) and
operandIsPropagated(instr, operandTag, propagatedBitOffset) and operandIsPropagated(instr, operandTag, propagatedBitOffset) and
bitOffset = Ints::add(originalBitOffset, propagatedBitOffset) bitOffset = Ints::add(originalBitOffset, propagatedBitOffset)
) )
} }

View File

@@ -1 +1 @@
import semmle.code.cpp.ir.IR as IR import semmle.code.cpp.ir.IR as IR

View File

@@ -1,97 +1,97 @@
private import IRInternal private import IRInternal
import Instruction import Instruction
import cpp import cpp
private newtype TFunctionIR = private newtype TFunctionIR =
MkFunctionIR(Function func) { MkFunctionIR(Function func) {
Construction::functionHasIR(func) Construction::functionHasIR(func)
} }
/** /**
* Represents the IR for a function. * Represents the IR for a function.
*/ */
class FunctionIR extends TFunctionIR { class FunctionIR extends TFunctionIR {
Function func; Function func;
FunctionIR() { FunctionIR() {
this = MkFunctionIR(func) this = MkFunctionIR(func)
} }
final string toString() { final string toString() {
result = "IR: " + func.toString() result = "IR: " + func.toString()
} }
/** /**
* Gets the function whose IR is represented. * Gets the function whose IR is represented.
*/ */
final Function getFunction() { final Function getFunction() {
result = func result = func
} }
/** /**
* Gets the location of the function. * Gets the location of the function.
*/ */
final Location getLocation() { final Location getLocation() {
result = func.getLocation() result = func.getLocation()
} }
/** /**
* Gets the entry point for this function. * Gets the entry point for this function.
*/ */
pragma[noinline] pragma[noinline]
final EnterFunctionInstruction getEnterFunctionInstruction() { final EnterFunctionInstruction getEnterFunctionInstruction() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
/** /**
* Gets the exit point for this function. * Gets the exit point for this function.
*/ */
pragma[noinline] pragma[noinline]
final ExitFunctionInstruction getExitFunctionInstruction() { final ExitFunctionInstruction getExitFunctionInstruction() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
pragma[noinline] pragma[noinline]
final UnmodeledDefinitionInstruction getUnmodeledDefinitionInstruction() { final UnmodeledDefinitionInstruction getUnmodeledDefinitionInstruction() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
/** /**
* Gets the single return instruction for this function. * Gets the single return instruction for this function.
*/ */
pragma[noinline] pragma[noinline]
final ReturnInstruction getReturnInstruction() { final ReturnInstruction getReturnInstruction() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
/** /**
* Gets the variable used to hold the return value of this function. If this * Gets the variable used to hold the return value of this function. If this
* function does not return a value, this predicate does not hold. * function does not return a value, this predicate does not hold.
*/ */
pragma[noinline] pragma[noinline]
final IRReturnVariable getReturnVariable() { final IRReturnVariable getReturnVariable() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
/** /**
* Gets the block containing the entry point of this function. * Gets the block containing the entry point of this function.
*/ */
pragma[noinline] pragma[noinline]
final IRBlock getEntryBlock() { final IRBlock getEntryBlock() {
result.getFirstInstruction() = getEnterFunctionInstruction() result.getFirstInstruction() = getEnterFunctionInstruction()
} }
/** /**
* Gets all instructions in this function. * Gets all instructions in this function.
*/ */
final Instruction getAnInstruction() { final Instruction getAnInstruction() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
/** /**
* Gets all blocks in this function. * Gets all blocks in this function.
*/ */
final IRBlock getABlock() { final IRBlock getABlock() {
result.getFunctionIR() = this result.getFunctionIR() = this
} }
} }

View File

@@ -1 +1 @@
import SSAConstruction as Construction import SSAConstruction as Construction

View File

@@ -1,3 +1,3 @@
private import IRImpl private import IRImpl
import InstructionSanity import InstructionSanity

View File

@@ -1,202 +1,202 @@
private import IRInternal private import IRInternal
import FunctionIR import FunctionIR
import cpp import cpp
import semmle.code.cpp.ir.TempVariableTag import semmle.code.cpp.ir.TempVariableTag
private import semmle.code.cpp.ir.internal.TempVariableTag private import semmle.code.cpp.ir.internal.TempVariableTag
private newtype TIRVariable = private newtype TIRVariable =
TIRAutomaticUserVariable(LocalScopeVariable var, FunctionIR funcIR) { TIRAutomaticUserVariable(LocalScopeVariable var, FunctionIR funcIR) {
exists(Function func | exists(Function func |
func = funcIR.getFunction() and func = funcIR.getFunction() and
( (
var.getFunction() = func or var.getFunction() = func or
var.(Parameter).getCatchBlock().getEnclosingFunction() = func var.(Parameter).getCatchBlock().getEnclosingFunction() = func
) )
) )
} or } or
TIRStaticUserVariable(Variable var, FunctionIR funcIR) { TIRStaticUserVariable(Variable var, FunctionIR funcIR) {
( (
var instanceof GlobalOrNamespaceVariable or var instanceof GlobalOrNamespaceVariable or
var instanceof MemberVariable and not var instanceof Field var instanceof MemberVariable and not var instanceof Field
) and ) and
exists(VariableAccess access | exists(VariableAccess access |
access.getTarget() = var and access.getTarget() = var and
access.getEnclosingFunction() = funcIR.getFunction() access.getEnclosingFunction() = funcIR.getFunction()
) )
} or } or
TIRTempVariable(FunctionIR funcIR, Locatable ast, TempVariableTag tag, TIRTempVariable(FunctionIR funcIR, Locatable ast, TempVariableTag tag,
Type type) { Type type) {
Construction::hasTempVariable(funcIR.getFunction(), ast, tag, type) Construction::hasTempVariable(funcIR.getFunction(), ast, tag, type)
} }
IRUserVariable getIRUserVariable(Function func, Variable var) { IRUserVariable getIRUserVariable(Function func, Variable var) {
result.getVariable() = var and result.getVariable() = var and
result.getFunction() = func result.getFunction() = func
} }
/** /**
* Represents a variable referenced by the IR for a function. The variable may * Represents a variable referenced by the IR for a function. The variable may
* be a user-declared variable (`IRUserVariable`) or a temporary variable * be a user-declared variable (`IRUserVariable`) or a temporary variable
* generated by the AST-to-IR translation (`IRTempVariable`). * generated by the AST-to-IR translation (`IRTempVariable`).
*/ */
abstract class IRVariable extends TIRVariable { abstract class IRVariable extends TIRVariable {
FunctionIR funcIR; FunctionIR funcIR;
abstract string toString(); abstract string toString();
/** /**
* Gets the type of the variable. * Gets the type of the variable.
*/ */
abstract Type getType(); abstract Type getType();
/** /**
* Gets the AST node that declared this variable, or that introduced this * Gets the AST node that declared this variable, or that introduced this
* variable as part of the AST-to-IR translation. * variable as part of the AST-to-IR translation.
*/ */
abstract Locatable getAST(); abstract Locatable getAST();
/** /**
* Gets an identifier string for the variable. This identifier is unique * Gets an identifier string for the variable. This identifier is unique
* within the function. * within the function.
*/ */
abstract string getUniqueId(); abstract string getUniqueId();
/** /**
* Gets the source location of this variable. * Gets the source location of this variable.
*/ */
final Location getLocation() { final Location getLocation() {
result = getAST().getLocation() result = getAST().getLocation()
} }
/** /**
* Gets the IR for the function that references this variable. * Gets the IR for the function that references this variable.
*/ */
final FunctionIR getFunctionIR() { final FunctionIR getFunctionIR() {
result = funcIR result = funcIR
} }
/** /**
* Gets the function that references this variable. * Gets the function that references this variable.
*/ */
final Function getFunction() { final Function getFunction() {
result = funcIR.getFunction() result = funcIR.getFunction()
} }
} }
/** /**
* Represents a user-declared variable referenced by the IR for a function. * Represents a user-declared variable referenced by the IR for a function.
*/ */
abstract class IRUserVariable extends IRVariable { abstract class IRUserVariable extends IRVariable {
Variable var; Variable var;
override final string toString() { override final string toString() {
result = var.toString() result = var.toString()
} }
override final Type getType() { override final Type getType() {
result = var.getType().getUnspecifiedType() result = var.getType().getUnspecifiedType()
} }
override final Locatable getAST() { override final Locatable getAST() {
result = var result = var
} }
override final string getUniqueId() { override final string getUniqueId() {
result = var.toString() + " " + var.getLocation().toString() result = var.toString() + " " + var.getLocation().toString()
} }
/** /**
* Gets the original user-declared variable. * Gets the original user-declared variable.
*/ */
final Variable getVariable() { final Variable getVariable() {
result = var result = var
} }
} }
/** /**
* Represents a variable (user-declared or temporary) that is allocated on the * Represents a variable (user-declared or temporary) that is allocated on the
* stack. This includes all parameters, non-static local variables, and * stack. This includes all parameters, non-static local variables, and
* temporary variables. * temporary variables.
*/ */
abstract class IRAutomaticVariable extends IRVariable { abstract class IRAutomaticVariable extends IRVariable {
} }
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable, class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable,
TIRAutomaticUserVariable { TIRAutomaticUserVariable {
LocalScopeVariable localVar; LocalScopeVariable localVar;
IRAutomaticUserVariable() { IRAutomaticUserVariable() {
this = TIRAutomaticUserVariable(localVar, funcIR) and this = TIRAutomaticUserVariable(localVar, funcIR) and
var = localVar var = localVar
} }
final LocalScopeVariable getLocalVariable() { final LocalScopeVariable getLocalVariable() {
result = localVar result = localVar
} }
} }
class IRStaticUserVariable extends IRUserVariable, TIRStaticUserVariable { class IRStaticUserVariable extends IRUserVariable, TIRStaticUserVariable {
IRStaticUserVariable() { IRStaticUserVariable() {
this = TIRStaticUserVariable(var, funcIR) this = TIRStaticUserVariable(var, funcIR)
} }
} }
IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) { IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) {
result.getAST() = ast and result.getAST() = ast and
result.getTag() = tag result.getTag() = tag
} }
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
Locatable ast; Locatable ast;
TempVariableTag tag; TempVariableTag tag;
Type type; Type type;
IRTempVariable() { IRTempVariable() {
this = TIRTempVariable(funcIR, ast, tag, type) this = TIRTempVariable(funcIR, ast, tag, type)
} }
override final Type getType() { override final Type getType() {
result = type result = type
} }
override final Locatable getAST() { override final Locatable getAST() {
result = ast result = ast
} }
override final string getUniqueId() { override final string getUniqueId() {
result = "Temp: " + Construction::getTempVariableUniqueId(this) result = "Temp: " + Construction::getTempVariableUniqueId(this)
} }
final TempVariableTag getTag() { final TempVariableTag getTag() {
result = tag result = tag
} }
override string toString() { override string toString() {
result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" +
ast.getLocation().getStartColumn().toString() ast.getLocation().getStartColumn().toString()
} }
string getBaseString() { string getBaseString() {
result = "#temp" result = "#temp"
} }
} }
class IRReturnVariable extends IRTempVariable { class IRReturnVariable extends IRTempVariable {
IRReturnVariable() { IRReturnVariable() {
tag = ReturnValueTempVar() tag = ReturnValueTempVar()
} }
override final string toString() { override final string toString() {
result = "#return" result = "#return"
} }
} }
class IRThrowVariable extends IRTempVariable { class IRThrowVariable extends IRTempVariable {
IRThrowVariable() { IRThrowVariable() {
tag = ThrowTempVar() tag = ThrowTempVar()
} }
override string getBaseString() { override string getBaseString() {
result = "#throw" result = "#throw"
} }
} }

View File

@@ -1,424 +1,424 @@
import SSAConstructionInternal import SSAConstructionInternal
import cpp import cpp
private import semmle.code.cpp.ir.internal.Opcode private import semmle.code.cpp.ir.internal.Opcode
import NewIR import NewIR
import Cached import Cached
cached private module Cached { cached private module Cached {
private OldIR::OperandTag getOldOperandTag(OperandTag newTag) { private OldIR::OperandTag getOldOperandTag(OperandTag newTag) {
newTag instanceof LoadStoreAddressOperand and result instanceof OldIR::LoadStoreAddressOperand or newTag instanceof LoadStoreAddressOperand and result instanceof OldIR::LoadStoreAddressOperand or
newTag instanceof CopySourceOperand and result instanceof OldIR::CopySourceOperand or newTag instanceof CopySourceOperand and result instanceof OldIR::CopySourceOperand or
newTag instanceof UnaryOperand and result instanceof OldIR::UnaryOperand or newTag instanceof UnaryOperand and result instanceof OldIR::UnaryOperand or
newTag instanceof LeftOperand and result instanceof OldIR::LeftOperand or newTag instanceof LeftOperand and result instanceof OldIR::LeftOperand or
newTag instanceof RightOperand and result instanceof OldIR::RightOperand or newTag instanceof RightOperand and result instanceof OldIR::RightOperand or
newTag instanceof ReturnValueOperand and result instanceof OldIR::ReturnValueOperand or newTag instanceof ReturnValueOperand and result instanceof OldIR::ReturnValueOperand or
newTag instanceof ExceptionOperand and result instanceof OldIR::ExceptionOperand or newTag instanceof ExceptionOperand and result instanceof OldIR::ExceptionOperand or
newTag instanceof ConditionOperand and result instanceof OldIR::ConditionOperand or newTag instanceof ConditionOperand and result instanceof OldIR::ConditionOperand or
newTag instanceof UnmodeledUseOperand and result instanceof OldIR::UnmodeledUseOperand or newTag instanceof UnmodeledUseOperand and result instanceof OldIR::UnmodeledUseOperand or
newTag instanceof CallTargetOperand and result instanceof OldIR::CallTargetOperand or newTag instanceof CallTargetOperand and result instanceof OldIR::CallTargetOperand or
newTag instanceof ThisArgumentOperand and result instanceof OldIR::ThisArgumentOperand or newTag instanceof ThisArgumentOperand and result instanceof OldIR::ThisArgumentOperand or
exists(PositionalArgumentOperand newArg | exists(PositionalArgumentOperand newArg |
newArg = newTag and newArg = newTag and
result.(OldIR::PositionalArgumentOperand).getArgIndex() = newArg.getArgIndex() result.(OldIR::PositionalArgumentOperand).getArgIndex() = newArg.getArgIndex()
) )
} }
private IRBlock getNewBlock(OldIR::IRBlock oldBlock) { private IRBlock getNewBlock(OldIR::IRBlock oldBlock) {
result.getFirstInstruction() = getNewInstruction(oldBlock.getFirstInstruction()) result.getFirstInstruction() = getNewInstruction(oldBlock.getFirstInstruction())
} }
cached newtype TInstructionTag = cached newtype TInstructionTag =
WrappedInstructionTag(OldIR::Instruction oldInstruction) or WrappedInstructionTag(OldIR::Instruction oldInstruction) or
PhiTag(Alias::VirtualVariable vvar, OldIR::IRBlock block) { PhiTag(Alias::VirtualVariable vvar, OldIR::IRBlock block) {
hasPhiNode(vvar, block) hasPhiNode(vvar, block)
} }
cached class InstructionTagType extends TInstructionTag { cached class InstructionTagType extends TInstructionTag {
cached final string toString() { cached final string toString() {
result = "Tag" result = "Tag"
} }
} }
cached predicate functionHasIR(Function func) { cached predicate functionHasIR(Function func) {
exists(OldIR::FunctionIR funcIR | exists(OldIR::FunctionIR funcIR |
funcIR.getFunction() = func funcIR.getFunction() = func
) )
} }
cached int getMaxCallArgIndex() { cached int getMaxCallArgIndex() {
result = max(int argIndex | result = max(int argIndex |
exists(OldIR::PositionalArgumentOperand oldOperand | exists(OldIR::PositionalArgumentOperand oldOperand |
argIndex = oldOperand.getArgIndex() argIndex = oldOperand.getArgIndex()
) )
) )
} }
cached OldIR::Instruction getOldInstruction(Instruction instr) { cached OldIR::Instruction getOldInstruction(Instruction instr) {
instr.getTag() = WrappedInstructionTag(result) instr.getTag() = WrappedInstructionTag(result)
} }
private Instruction getNewInstruction(OldIR::Instruction instr) { private Instruction getNewInstruction(OldIR::Instruction instr) {
getOldInstruction(result) = instr getOldInstruction(result) = instr
} }
private PhiInstruction getPhiInstruction(Function func, OldIR::IRBlock oldBlock, private PhiInstruction getPhiInstruction(Function func, OldIR::IRBlock oldBlock,
Alias::VirtualVariable vvar) { Alias::VirtualVariable vvar) {
result.getFunction() = func and result.getFunction() = func and
result.getAST() = oldBlock.getFirstInstruction().getAST() and result.getAST() = oldBlock.getFirstInstruction().getAST() and
result.getTag() = PhiTag(vvar, oldBlock) result.getTag() = PhiTag(vvar, oldBlock)
} }
private IRVariable getNewIRVariable(OldIR::IRVariable var) { private IRVariable getNewIRVariable(OldIR::IRVariable var) {
result.getFunction() = var.getFunction() and result.getFunction() = var.getFunction() and
( (
exists(OldIR::IRUserVariable userVar, IRUserVariable newUserVar | exists(OldIR::IRUserVariable userVar, IRUserVariable newUserVar |
userVar = var and userVar = var and
newUserVar.getVariable() = userVar.getVariable() and newUserVar.getVariable() = userVar.getVariable() and
result = newUserVar result = newUserVar
) or ) or
exists(OldIR::IRTempVariable tempVar, IRTempVariable newTempVar | exists(OldIR::IRTempVariable tempVar, IRTempVariable newTempVar |
tempVar = var and tempVar = var and
newTempVar.getAST() = tempVar.getAST() and newTempVar.getAST() = tempVar.getAST() and
newTempVar.getTag() = tempVar.getTag() and newTempVar.getTag() = tempVar.getTag() and
result = newTempVar result = newTempVar
) )
) )
} }
cached newtype TInstruction = cached newtype TInstruction =
MkInstruction(FunctionIR funcIR, Opcode opcode, Locatable ast, MkInstruction(FunctionIR funcIR, Opcode opcode, Locatable ast,
InstructionTag tag, Type resultType, boolean isGLValue) { InstructionTag tag, Type resultType, boolean isGLValue) {
hasInstruction(funcIR.getFunction(), opcode, ast, tag, hasInstruction(funcIR.getFunction(), opcode, ast, tag,
resultType, isGLValue) resultType, isGLValue)
} }
private predicate hasInstruction(Function func, Opcode opcode, Locatable ast, private predicate hasInstruction(Function func, Opcode opcode, Locatable ast,
InstructionTag tag, Type resultType, boolean isGLValue) { InstructionTag tag, Type resultType, boolean isGLValue) {
exists(OldIR::Instruction instr | exists(OldIR::Instruction instr |
instr.getFunction() = func and instr.getFunction() = func and
instr.getOpcode() = opcode and instr.getOpcode() = opcode and
instr.getAST() = ast and instr.getAST() = ast and
WrappedInstructionTag(instr) = tag and WrappedInstructionTag(instr) = tag and
instr.getResultType() = resultType and instr.getResultType() = resultType and
if instr.isGLValue() then if instr.isGLValue() then
isGLValue = true isGLValue = true
else else
isGLValue = false isGLValue = false
) or ) or
exists(OldIR::IRBlock block, Alias::VirtualVariable vvar | exists(OldIR::IRBlock block, Alias::VirtualVariable vvar |
hasPhiNode(vvar, block) and hasPhiNode(vvar, block) and
block.getFunction() = func and block.getFunction() = func and
opcode instanceof Opcode::Phi and opcode instanceof Opcode::Phi and
ast = block.getFirstInstruction().getAST() and ast = block.getFirstInstruction().getAST() and
tag = PhiTag(vvar, block) and tag = PhiTag(vvar, block) and
resultType = vvar.getType() and resultType = vvar.getType() and
isGLValue = false isGLValue = false
) )
} }
cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag,
Type type) { Type type) {
exists(OldIR::IRTempVariable var | exists(OldIR::IRTempVariable var |
var.getFunction() = func and var.getFunction() = func and
var.getAST() = ast and var.getAST() = ast and
var.getTag() = tag and var.getTag() = tag and
var.getType() = type var.getType() = type
) )
} }
cached predicate hasModeledMemoryResult(Instruction instruction) { cached predicate hasModeledMemoryResult(Instruction instruction) {
exists(Alias::getResultMemoryAccess(getOldInstruction(instruction))) or exists(Alias::getResultMemoryAccess(getOldInstruction(instruction))) or
instruction instanceof PhiInstruction // Phis always have modeled results instruction instanceof PhiInstruction // Phis always have modeled results
} }
cached Instruction getInstructionOperand(Instruction instruction, OperandTag tag) { cached Instruction getInstructionOperand(Instruction instruction, OperandTag tag) {
exists(OldIR::Instruction oldUse, OldIR::OperandTag oldTag | exists(OldIR::Instruction oldUse, OldIR::OperandTag oldTag |
oldUse = getOldInstruction(instruction) and oldUse = getOldInstruction(instruction) and
oldTag = getOldOperandTag(tag) and oldTag = getOldOperandTag(tag) and
if oldUse.isMemoryOperand(oldTag) then ( if oldUse.isMemoryOperand(oldTag) then (
( (
if exists(Alias::getOperandMemoryAccess(oldUse, oldTag)) then ( if exists(Alias::getOperandMemoryAccess(oldUse, oldTag)) then (
exists(OldIR::IRBlock useBlock, int useRank, Alias::VirtualVariable vvar, exists(OldIR::IRBlock useBlock, int useRank, Alias::VirtualVariable vvar,
OldIR::IRBlock defBlock, int defRank, int defIndex | OldIR::IRBlock defBlock, int defRank, int defIndex |
vvar = Alias::getOperandMemoryAccess(oldUse, oldTag).getVirtualVariable() and vvar = Alias::getOperandMemoryAccess(oldUse, oldTag).getVirtualVariable() and
hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and
hasUseAtRank(vvar, useBlock, useRank, oldUse) and hasUseAtRank(vvar, useBlock, useRank, oldUse) and
definitionReachesUse(vvar, defBlock, defRank, useBlock, useRank) and definitionReachesUse(vvar, defBlock, defRank, useBlock, useRank) and
if defIndex >= 0 then if defIndex >= 0 then
result = getNewInstruction(defBlock.getInstruction(defIndex)) result = getNewInstruction(defBlock.getInstruction(defIndex))
else else
result = getPhiInstruction(instruction.getFunction(), defBlock, vvar) result = getPhiInstruction(instruction.getFunction(), defBlock, vvar)
) )
) )
else ( else (
result = instruction.getFunctionIR().getUnmodeledDefinitionInstruction() result = instruction.getFunctionIR().getUnmodeledDefinitionInstruction()
) )
) or ) or
// Connect any definitions that are not being modeled in SSA to the // Connect any definitions that are not being modeled in SSA to the
// `UnmodeledUse` instruction. // `UnmodeledUse` instruction.
exists(OldIR::Instruction oldDefinition | exists(OldIR::Instruction oldDefinition |
instruction instanceof UnmodeledUseInstruction and instruction instanceof UnmodeledUseInstruction and
tag instanceof UnmodeledUseOperand and tag instanceof UnmodeledUseOperand and
oldDefinition = oldUse.getOperand(oldTag) and oldDefinition = oldUse.getOperand(oldTag) and
not exists(Alias::getResultMemoryAccess(oldDefinition)) and not exists(Alias::getResultMemoryAccess(oldDefinition)) and
result = getNewInstruction(oldDefinition) result = getNewInstruction(oldDefinition)
) )
) )
else else
result = getNewInstruction(oldUse.getOperand(oldTag)) result = getNewInstruction(oldUse.getOperand(oldTag))
) or ) or
result = getPhiInstructionOperand(instruction.(PhiInstruction), tag.(PhiOperand)) result = getPhiInstructionOperand(instruction.(PhiInstruction), tag.(PhiOperand))
} }
cached Instruction getPhiInstructionOperand(PhiInstruction instr, PhiOperand tag) { cached Instruction getPhiInstructionOperand(PhiInstruction instr, PhiOperand tag) {
exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock, exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock,
OldIR::IRBlock defBlock, int defRank, int defIndex, OldIR::IRBlock predBlock | OldIR::IRBlock defBlock, int defRank, int defIndex, OldIR::IRBlock predBlock |
hasPhiNode(vvar, phiBlock) and hasPhiNode(vvar, phiBlock) and
predBlock = phiBlock.getAPredecessor() and predBlock = phiBlock.getAPredecessor() and
instr.getTag() = PhiTag(vvar, phiBlock) and instr.getTag() = PhiTag(vvar, phiBlock) and
tag.getPredecessorBlock() = getNewBlock(predBlock) and tag.getPredecessorBlock() = getNewBlock(predBlock) and
hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and
definitionReachesEndOfBlock(vvar, defBlock, defRank, predBlock) and definitionReachesEndOfBlock(vvar, defBlock, defRank, predBlock) and
if defIndex >= 0 then if defIndex >= 0 then
result = getNewInstruction(defBlock.getInstruction(defIndex)) result = getNewInstruction(defBlock.getInstruction(defIndex))
else else
result = getPhiInstruction(instr.getFunction(), defBlock, vvar) result = getPhiInstruction(instr.getFunction(), defBlock, vvar)
) )
} }
cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) { cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) {
exists(OldIR::IRBlock oldBlock | exists(OldIR::IRBlock oldBlock |
instr.getTag() = PhiTag(_, oldBlock) and instr.getTag() = PhiTag(_, oldBlock) and
result = getNewInstruction(oldBlock.getFirstInstruction()) result = getNewInstruction(oldBlock.getFirstInstruction())
) )
} }
cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) { cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
result = getNewInstruction(getOldInstruction(instruction).getSuccessor(kind)) result = getNewInstruction(getOldInstruction(instruction).getSuccessor(kind))
} }
cached IRVariable getInstructionVariable(Instruction instruction) { cached IRVariable getInstructionVariable(Instruction instruction) {
result = getNewIRVariable(getOldInstruction(instruction).(OldIR::VariableInstruction).getVariable()) result = getNewIRVariable(getOldInstruction(instruction).(OldIR::VariableInstruction).getVariable())
} }
cached Field getInstructionField(Instruction instruction) { cached Field getInstructionField(Instruction instruction) {
result = getOldInstruction(instruction).(OldIR::FieldInstruction).getField() result = getOldInstruction(instruction).(OldIR::FieldInstruction).getField()
} }
cached Function getInstructionFunction(Instruction instruction) { cached Function getInstructionFunction(Instruction instruction) {
result = getOldInstruction(instruction).(OldIR::FunctionInstruction).getFunctionSymbol() result = getOldInstruction(instruction).(OldIR::FunctionInstruction).getFunctionSymbol()
} }
cached string getInstructionConstantValue(Instruction instruction) { cached string getInstructionConstantValue(Instruction instruction) {
result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue() result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue()
} }
cached StringLiteral getInstructionStringLiteral(Instruction instruction) { cached StringLiteral getInstructionStringLiteral(Instruction instruction) {
result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue() result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue()
} }
cached Type getInstructionExceptionType(Instruction instruction) { cached Type getInstructionExceptionType(Instruction instruction) {
result = getOldInstruction(instruction).(OldIR::CatchByTypeInstruction).getExceptionType() result = getOldInstruction(instruction).(OldIR::CatchByTypeInstruction).getExceptionType()
} }
cached int getInstructionElementSize(Instruction instruction) { cached int getInstructionElementSize(Instruction instruction) {
result = getOldInstruction(instruction).(OldIR::PointerArithmeticInstruction).getElementSize() result = getOldInstruction(instruction).(OldIR::PointerArithmeticInstruction).getElementSize()
} }
cached int getInstructionResultSize(Instruction instruction) { cached int getInstructionResultSize(Instruction instruction) {
// Only return a result for instructions that needed an explicit result size. // Only return a result for instructions that needed an explicit result size.
instruction.getResultType() instanceof UnknownType and instruction.getResultType() instanceof UnknownType and
result = getOldInstruction(instruction).getResultSize() result = getOldInstruction(instruction).getResultSize()
} }
cached predicate getInstructionInheritance(Instruction instruction, Class baseClass, cached predicate getInstructionInheritance(Instruction instruction, Class baseClass,
Class derivedClass) { Class derivedClass) {
exists(OldIR::InheritanceConversionInstruction oldInstr | exists(OldIR::InheritanceConversionInstruction oldInstr |
oldInstr = getOldInstruction(instruction) and oldInstr = getOldInstruction(instruction) and
baseClass = oldInstr.getBaseClass() and baseClass = oldInstr.getBaseClass() and
derivedClass = oldInstr.getDerivedClass() derivedClass = oldInstr.getDerivedClass()
) )
} }
private predicate ssa_variableUpdate(Alias::VirtualVariable vvar, private predicate ssa_variableUpdate(Alias::VirtualVariable vvar,
OldIR::Instruction instr, OldIR::IRBlock block, int index) { OldIR::Instruction instr, OldIR::IRBlock block, int index) {
block.getInstruction(index) = instr and block.getInstruction(index) = instr and
Alias::getResultMemoryAccess(instr).getVirtualVariable() = vvar Alias::getResultMemoryAccess(instr).getVirtualVariable() = vvar
} }
private predicate hasDefinition(Alias::VirtualVariable vvar, OldIR::IRBlock block, int index) { private predicate hasDefinition(Alias::VirtualVariable vvar, OldIR::IRBlock block, int index) {
( (
hasPhiNode(vvar, block) and hasPhiNode(vvar, block) and
index = -1 index = -1
) or ) or
exists(Alias::MemoryAccess access, OldIR::Instruction def | exists(Alias::MemoryAccess access, OldIR::Instruction def |
access = Alias::getResultMemoryAccess(def) and access = Alias::getResultMemoryAccess(def) and
block.getInstruction(index) = def and block.getInstruction(index) = def and
vvar = access.getVirtualVariable() vvar = access.getVirtualVariable()
) )
} }
private predicate defUseRank(Alias::VirtualVariable vvar, OldIR::IRBlock block, int rankIndex, int index) { private predicate defUseRank(Alias::VirtualVariable vvar, OldIR::IRBlock block, int rankIndex, int index) {
index = rank[rankIndex](int j | hasDefinition(vvar, block, j) or hasUse(vvar, _, block, j)) index = rank[rankIndex](int j | hasDefinition(vvar, block, j) or hasUse(vvar, _, block, j))
} }
private predicate hasUse(Alias::VirtualVariable vvar, private predicate hasUse(Alias::VirtualVariable vvar,
OldIR::Instruction use, OldIR::IRBlock block, int index) { OldIR::Instruction use, OldIR::IRBlock block, int index) {
exists(Alias::MemoryAccess access | exists(Alias::MemoryAccess access |
access = Alias::getOperandMemoryAccess(use, _) and access = Alias::getOperandMemoryAccess(use, _) and
block.getInstruction(index) = use and block.getInstruction(index) = use and
vvar = access.getVirtualVariable() vvar = access.getVirtualVariable()
) )
} }
private predicate variableLiveOnEntryToBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) { private predicate variableLiveOnEntryToBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) {
exists (int index | hasUse(vvar, _, block, index) | exists (int index | hasUse(vvar, _, block, index) |
not exists (int j | ssa_variableUpdate(vvar, _, block, j) | j < index) not exists (int j | ssa_variableUpdate(vvar, _, block, j) | j < index)
) or ) or
(variableLiveOnExitFromBlock(vvar, block) and not ssa_variableUpdate(vvar, _, block, _)) (variableLiveOnExitFromBlock(vvar, block) and not ssa_variableUpdate(vvar, _, block, _))
} }
pragma[noinline] pragma[noinline]
private predicate variableLiveOnExitFromBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) { private predicate variableLiveOnExitFromBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) {
variableLiveOnEntryToBlock(vvar, block.getASuccessor()) variableLiveOnEntryToBlock(vvar, block.getASuccessor())
} }
/** /**
* Gets the rank index of a hyphothetical use one instruction past the end of * Gets the rank index of a hyphothetical use one instruction past the end of
* the block. This index can be used to determine if a definition reaches the * the block. This index can be used to determine if a definition reaches the
* end of the block, even if the definition is the last instruction in the * end of the block, even if the definition is the last instruction in the
* block. * block.
*/ */
private int exitRank(Alias::VirtualVariable vvar, OldIR::IRBlock block) { private int exitRank(Alias::VirtualVariable vvar, OldIR::IRBlock block) {
result = max(int rankIndex | defUseRank(vvar, block, rankIndex, _)) + 1 result = max(int rankIndex | defUseRank(vvar, block, rankIndex, _)) + 1
} }
private predicate hasDefinitionAtRank(Alias::VirtualVariable vvar, private predicate hasDefinitionAtRank(Alias::VirtualVariable vvar,
OldIR::IRBlock block, int rankIndex, int instructionIndex) { OldIR::IRBlock block, int rankIndex, int instructionIndex) {
hasDefinition(vvar, block, instructionIndex) and hasDefinition(vvar, block, instructionIndex) and
defUseRank(vvar, block, rankIndex, instructionIndex) defUseRank(vvar, block, rankIndex, instructionIndex)
} }
private predicate hasUseAtRank(Alias::VirtualVariable vvar, OldIR::IRBlock block, private predicate hasUseAtRank(Alias::VirtualVariable vvar, OldIR::IRBlock block,
int rankIndex, OldIR::Instruction use) { int rankIndex, OldIR::Instruction use) {
exists(int index | exists(int index |
hasUse(vvar, use, block, index) and hasUse(vvar, use, block, index) and
defUseRank(vvar, block, rankIndex, index) defUseRank(vvar, block, rankIndex, index)
) )
} }
/** /**
* Holds if the definition of `vvar` at `(block, defRank)` reaches the rank * Holds if the definition of `vvar` at `(block, defRank)` reaches the rank
* index `reachesRank` in block `block`. * index `reachesRank` in block `block`.
*/ */
private predicate definitionReachesRank(Alias::VirtualVariable vvar, private predicate definitionReachesRank(Alias::VirtualVariable vvar,
OldIR::IRBlock block, int defRank, int reachesRank) { OldIR::IRBlock block, int defRank, int reachesRank) {
hasDefinitionAtRank(vvar, block, defRank, _) and hasDefinitionAtRank(vvar, block, defRank, _) and
reachesRank <= exitRank(vvar, block) and // Without this, the predicate would be infinite. reachesRank <= exitRank(vvar, block) and // Without this, the predicate would be infinite.
( (
// The def always reaches the next use, even if there is also a def on the // The def always reaches the next use, even if there is also a def on the
// use instruction. // use instruction.
reachesRank = defRank + 1 or reachesRank = defRank + 1 or
( (
// If the def reached the previous rank, it also reaches the current rank, // If the def reached the previous rank, it also reaches the current rank,
// unless there was another def at the previous rank. // unless there was another def at the previous rank.
definitionReachesRank(vvar, block, defRank, reachesRank - 1) and definitionReachesRank(vvar, block, defRank, reachesRank - 1) and
not hasDefinitionAtRank(vvar, block, reachesRank - 1, _) not hasDefinitionAtRank(vvar, block, reachesRank - 1, _)
) )
) )
} }
/** /**
* Holds if the definition of `vvar` at `(defBlock, defRank)` reaches the end of * Holds if the definition of `vvar` at `(defBlock, defRank)` reaches the end of
* block `block`. * block `block`.
*/ */
private predicate definitionReachesEndOfBlock(Alias::VirtualVariable vvar, private predicate definitionReachesEndOfBlock(Alias::VirtualVariable vvar,
OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock block) { OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock block) {
hasDefinitionAtRank(vvar, defBlock, defRank, _) and hasDefinitionAtRank(vvar, defBlock, defRank, _) and
( (
( (
// If we're looking at the def's own block, just see if it reaches the exit // If we're looking at the def's own block, just see if it reaches the exit
// rank of the block. // rank of the block.
block = defBlock and block = defBlock and
variableLiveOnExitFromBlock(vvar, defBlock) and variableLiveOnExitFromBlock(vvar, defBlock) and
definitionReachesRank(vvar, defBlock, defRank, exitRank(vvar, defBlock)) definitionReachesRank(vvar, defBlock, defRank, exitRank(vvar, defBlock))
) or ) or
exists(OldIR::IRBlock idom | exists(OldIR::IRBlock idom |
definitionReachesEndOfBlock(vvar, defBlock, defRank, idom) and definitionReachesEndOfBlock(vvar, defBlock, defRank, idom) and
noDefinitionsSinceIDominator(vvar, idom, block) noDefinitionsSinceIDominator(vvar, idom, block)
) )
) )
} }
pragma[noinline] pragma[noinline]
private predicate noDefinitionsSinceIDominator(Alias::VirtualVariable vvar, private predicate noDefinitionsSinceIDominator(Alias::VirtualVariable vvar,
OldIR::IRBlock idom, OldIR::IRBlock block) { OldIR::IRBlock idom, OldIR::IRBlock block) {
idom.immediatelyDominates(block) and // It is sufficient to traverse the dominator graph, cf. discussion above. idom.immediatelyDominates(block) and // It is sufficient to traverse the dominator graph, cf. discussion above.
variableLiveOnExitFromBlock(vvar, block) and variableLiveOnExitFromBlock(vvar, block) and
not hasDefinition(vvar, block, _) not hasDefinition(vvar, block, _)
} }
private predicate definitionReachesUseWithinBlock( private predicate definitionReachesUseWithinBlock(
Alias::VirtualVariable vvar, OldIR::IRBlock defBlock, int defRank, Alias::VirtualVariable vvar, OldIR::IRBlock defBlock, int defRank,
OldIR::IRBlock useBlock, int useRank) { OldIR::IRBlock useBlock, int useRank) {
defBlock = useBlock and defBlock = useBlock and
hasDefinitionAtRank(vvar, defBlock, defRank, _) and hasDefinitionAtRank(vvar, defBlock, defRank, _) and
hasUseAtRank(vvar, useBlock, useRank, _) and hasUseAtRank(vvar, useBlock, useRank, _) and
definitionReachesRank(vvar, defBlock, defRank, useRank) definitionReachesRank(vvar, defBlock, defRank, useRank)
} }
private predicate definitionReachesUse(Alias::VirtualVariable vvar, private predicate definitionReachesUse(Alias::VirtualVariable vvar,
OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock useBlock, int useRank) { OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock useBlock, int useRank) {
hasUseAtRank(vvar, useBlock, useRank, _) and hasUseAtRank(vvar, useBlock, useRank, _) and
( (
definitionReachesUseWithinBlock(vvar, defBlock, defRank, useBlock, definitionReachesUseWithinBlock(vvar, defBlock, defRank, useBlock,
useRank) or useRank) or
( (
definitionReachesEndOfBlock(vvar, defBlock, defRank, definitionReachesEndOfBlock(vvar, defBlock, defRank,
useBlock.getAPredecessor()) and useBlock.getAPredecessor()) and
not definitionReachesUseWithinBlock(vvar, useBlock, _, useBlock, useRank) not definitionReachesUseWithinBlock(vvar, useBlock, _, useBlock, useRank)
) )
) )
} }
private predicate hasFrontierPhiNode(Alias::VirtualVariable vvar, private predicate hasFrontierPhiNode(Alias::VirtualVariable vvar,
OldIR::IRBlock phiBlock) { OldIR::IRBlock phiBlock) {
exists(OldIR::IRBlock defBlock | exists(OldIR::IRBlock defBlock |
phiBlock = defBlock.dominanceFrontier() and phiBlock = defBlock.dominanceFrontier() and
hasDefinition(vvar, defBlock, _) and hasDefinition(vvar, defBlock, _) and
/* We can also eliminate those nodes where the variable is not live on any incoming edge */ /* We can also eliminate those nodes where the variable is not live on any incoming edge */
variableLiveOnEntryToBlock(vvar, phiBlock) variableLiveOnEntryToBlock(vvar, phiBlock)
) )
} }
private predicate hasPhiNode(Alias::VirtualVariable vvar, private predicate hasPhiNode(Alias::VirtualVariable vvar,
OldIR::IRBlock phiBlock) { OldIR::IRBlock phiBlock) {
hasFrontierPhiNode(vvar, phiBlock) hasFrontierPhiNode(vvar, phiBlock)
//or ssa_sanitized_custom_phi_node(vvar, block) //or ssa_sanitized_custom_phi_node(vvar, block)
} }
} }
import CachedForDebugging import CachedForDebugging
cached private module CachedForDebugging { cached private module CachedForDebugging {
cached string getTempVariableUniqueId(IRTempVariable var) { cached string getTempVariableUniqueId(IRTempVariable var) {
result = getOldTempVariable(var).getUniqueId() result = getOldTempVariable(var).getUniqueId()
} }
cached string getInstructionUniqueId(Instruction instr) { cached string getInstructionUniqueId(Instruction instr) {
exists(OldIR::Instruction oldInstr | exists(OldIR::Instruction oldInstr |
oldInstr = getOldInstruction(instr) and oldInstr = getOldInstruction(instr) and
result = "NonSSA: " + oldInstr.getUniqueId() result = "NonSSA: " + oldInstr.getUniqueId()
) or ) or
exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock | exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock |
instr.getTag() = PhiTag(vvar, phiBlock) and instr.getTag() = PhiTag(vvar, phiBlock) and
result = "Phi Block(" + phiBlock.getUniqueId() + "): " + vvar.getUniqueId() result = "Phi Block(" + phiBlock.getUniqueId() + "): " + vvar.getUniqueId()
) )
} }
private OldIR::IRTempVariable getOldTempVariable(IRTempVariable var) { private OldIR::IRTempVariable getOldTempVariable(IRTempVariable var) {
result.getFunction() = var.getFunction() and result.getFunction() = var.getFunction() and
result.getAST() = var.getAST() and result.getAST() = var.getAST() and
result.getTag() = var.getTag() result.getTag() = var.getTag()
} }
} }

View File

@@ -1,3 +1,3 @@
import semmle.code.cpp.ir.IR as OldIR import semmle.code.cpp.ir.IR as OldIR
import semmle.code.cpp.ssa.SSAIR as NewIR import semmle.code.cpp.ssa.SSAIR as NewIR
import SimpleSSA as Alias import SimpleSSA as Alias

View File

@@ -1,83 +1,83 @@
import SimpleSSAInternal import SimpleSSAInternal
import cpp import cpp
import Alias import Alias
import IR import IR
import semmle.code.cpp.ssa.internal.Overlap import semmle.code.cpp.ssa.internal.Overlap
private newtype TVirtualVariable = private newtype TVirtualVariable =
MkVirtualVariable(IRVariable var) { MkVirtualVariable(IRVariable var) {
not variableAddressEscapes(var) not variableAddressEscapes(var)
} }
private VirtualVariable getVirtualVariable(IRVariable var) { private VirtualVariable getVirtualVariable(IRVariable var) {
result.getIRVariable() = var result.getIRVariable() = var
} }
class VirtualVariable extends TVirtualVariable { class VirtualVariable extends TVirtualVariable {
IRVariable var; IRVariable var;
VirtualVariable() { VirtualVariable() {
this = MkVirtualVariable(var) this = MkVirtualVariable(var)
} }
final string toString() { final string toString() {
result = var.toString() result = var.toString()
} }
final IRVariable getIRVariable() { final IRVariable getIRVariable() {
result = var result = var
} }
// REVIEW: This should just be on MemoryAccess // REVIEW: This should just be on MemoryAccess
final Type getType() { final Type getType() {
result = var.getType() result = var.getType()
} }
final string getUniqueId() { final string getUniqueId() {
result = var.getUniqueId() result = var.getUniqueId()
} }
} }
private newtype TMemoryAccess = private newtype TMemoryAccess =
MkMemoryAccess(VirtualVariable vvar) MkMemoryAccess(VirtualVariable vvar)
private MemoryAccess getMemoryAccess(IRVariable var) { private MemoryAccess getMemoryAccess(IRVariable var) {
result.getVirtualVariable() = getVirtualVariable(var) result.getVirtualVariable() = getVirtualVariable(var)
} }
class MemoryAccess extends TMemoryAccess { class MemoryAccess extends TMemoryAccess {
VirtualVariable vvar; VirtualVariable vvar;
MemoryAccess() { MemoryAccess() {
this = MkMemoryAccess(vvar) this = MkMemoryAccess(vvar)
} }
string toString() { string toString() {
result = vvar.toString() result = vvar.toString()
} }
VirtualVariable getVirtualVariable() { VirtualVariable getVirtualVariable() {
result = vvar result = vvar
} }
} }
Overlap getOverlap(MemoryAccess def, MemoryAccess use) { Overlap getOverlap(MemoryAccess def, MemoryAccess use) {
def.getVirtualVariable() = use.getVirtualVariable() and def.getVirtualVariable() = use.getVirtualVariable() and
result instanceof MustExactlyOverlap result instanceof MustExactlyOverlap
} }
MemoryAccess getResultMemoryAccess(Instruction instr) { MemoryAccess getResultMemoryAccess(Instruction instr) {
exists(IRVariable var | exists(IRVariable var |
instr.getResultMemoryAccess() instanceof IndirectMemoryAccess and instr.getResultMemoryAccess() instanceof IndirectMemoryAccess and
resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and
result = getMemoryAccess(var) result = getMemoryAccess(var)
) )
} }
MemoryAccess getOperandMemoryAccess(Instruction instr, OperandTag tag) { MemoryAccess getOperandMemoryAccess(Instruction instr, OperandTag tag) {
exists(IRVariable var | exists(IRVariable var |
instr.getOperandMemoryAccess(tag) instanceof IndirectMemoryAccess and instr.getOperandMemoryAccess(tag) instanceof IndirectMemoryAccess and
resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and
result = getMemoryAccess(var) result = getMemoryAccess(var)
) )
} }

View File

@@ -1,3 +1,3 @@
import AliasAnalysis as Alias import AliasAnalysis as Alias
import semmle.code.cpp.ir.IR as IR import semmle.code.cpp.ir.IR as IR

View File

@@ -1,49 +1,49 @@
import cpp import cpp
import semmle.code.cpp.ssa.internal.IntegerConstant as Ints import semmle.code.cpp.ssa.internal.IntegerConstant as Ints
bindingset[n] bindingset[n]
string resultString(int n) { string resultString(int n) {
if Ints::hasValue(n) then if Ints::hasValue(n) then
result = n.toString() result = n.toString()
else else
result = "unknown" result = "unknown"
} }
from string expr, int res from string expr, int res
where where
expr = "0 + 0" and res = Ints::add(0, 0) or expr = "0 + 0" and res = Ints::add(0, 0) or
expr = "0 + INT_MAX" and res = Ints::add(0, Ints::maxValue()) or expr = "0 + INT_MAX" and res = Ints::add(0, Ints::maxValue()) or
expr = "0 + -INT_MAX" and res = Ints::add(0, Ints::minValue()) or expr = "0 + -INT_MAX" and res = Ints::add(0, Ints::minValue()) or
expr = "1 + INT_MAX" and res = Ints::add(1, Ints::maxValue()) or expr = "1 + INT_MAX" and res = Ints::add(1, Ints::maxValue()) or
expr = "1 + -INT_MAX" and res = Ints::add(1, Ints::minValue()) or expr = "1 + -INT_MAX" and res = Ints::add(1, Ints::minValue()) or
expr = "unknown + unknown" and res = Ints::add(Ints::unknown(), Ints::unknown()) or expr = "unknown + unknown" and res = Ints::add(Ints::unknown(), Ints::unknown()) or
expr = "5 + unknown" and res = Ints::add(5, Ints::unknown()) or expr = "5 + unknown" and res = Ints::add(5, Ints::unknown()) or
expr = "unknown + 5" and res = Ints::add(Ints::unknown(), 5) or expr = "unknown + 5" and res = Ints::add(Ints::unknown(), 5) or
expr = "0 - INT_MAX" and res = Ints::sub(0, Ints::maxValue()) or expr = "0 - INT_MAX" and res = Ints::sub(0, Ints::maxValue()) or
expr = "0 - -INT_MAX" and res = Ints::sub(0, Ints::minValue()) or expr = "0 - -INT_MAX" and res = Ints::sub(0, Ints::minValue()) or
expr = "-1 - INT_MAX" and res = Ints::sub(-1, Ints::maxValue()) or expr = "-1 - INT_MAX" and res = Ints::sub(-1, Ints::maxValue()) or
expr = "-1 - -INT_MAX" and res = Ints::sub(-1, Ints::minValue()) or expr = "-1 - -INT_MAX" and res = Ints::sub(-1, Ints::minValue()) or
expr = "unknown - unknown" and res = Ints::sub(Ints::unknown(), Ints::unknown()) or expr = "unknown - unknown" and res = Ints::sub(Ints::unknown(), Ints::unknown()) or
expr = "5 - unknown" and res = Ints::sub(5, Ints::unknown()) or expr = "5 - unknown" and res = Ints::sub(5, Ints::unknown()) or
expr = "unknown - 5" and res = Ints::sub(Ints::unknown(), 5) or expr = "unknown - 5" and res = Ints::sub(Ints::unknown(), 5) or
expr = "0 * 0" and res = Ints::mul(0, 0) or expr = "0 * 0" and res = Ints::mul(0, 0) or
expr = "5 * 7" and res = Ints::mul(5, 7) or expr = "5 * 7" and res = Ints::mul(5, 7) or
expr = "0 * INT_MAX" and res = Ints::mul(0, Ints::maxValue()) or expr = "0 * INT_MAX" and res = Ints::mul(0, Ints::maxValue()) or
expr = "2 * INT_MAX" and res = Ints::mul(2, Ints::maxValue()) or expr = "2 * INT_MAX" and res = Ints::mul(2, Ints::maxValue()) or
expr = "-1 * -INT_MAX" and res = Ints::mul(-1, Ints::minValue()) or expr = "-1 * -INT_MAX" and res = Ints::mul(-1, Ints::minValue()) or
expr = "INT_MAX * INT_MAX" and res = Ints::mul(Ints::maxValue(), Ints::maxValue()) or expr = "INT_MAX * INT_MAX" and res = Ints::mul(Ints::maxValue(), Ints::maxValue()) or
expr = "0 * unknown" and res = Ints::mul(0, Ints::unknown()) or expr = "0 * unknown" and res = Ints::mul(0, Ints::unknown()) or
expr = "35 / 7" and res = Ints::div(35, 7) or expr = "35 / 7" and res = Ints::div(35, 7) or
expr = "35 / 8" and res = Ints::div(35, 8) or expr = "35 / 8" and res = Ints::div(35, 8) or
expr = "35 / -7" and res = Ints::div(35, -7) or expr = "35 / -7" and res = Ints::div(35, -7) or
expr = "35 / -8" and res = Ints::div(35, -8) or expr = "35 / -8" and res = Ints::div(35, -8) or
expr = "-35 / 7" and res = Ints::div(-35, 7) or expr = "-35 / 7" and res = Ints::div(-35, 7) or
expr = "-35 / 8" and res = Ints::div(-35, 8) or expr = "-35 / 8" and res = Ints::div(-35, 8) or
expr = "-35 / -7" and res = Ints::div(-35, -7) or expr = "-35 / -7" and res = Ints::div(-35, -7) or
expr = "-35 / -8" and res = Ints::div(-35, -8) or expr = "-35 / -8" and res = Ints::div(-35, -8) or
expr = "0 / -INT_MAX" and res = Ints::div(0, Ints::minValue()) or expr = "0 / -INT_MAX" and res = Ints::div(0, Ints::minValue()) or
expr = "INT_MAX / 0" and res = Ints::div(Ints::maxValue(), 0) or expr = "INT_MAX / 0" and res = Ints::div(Ints::maxValue(), 0) or
expr = "0 / unknown" and res = Ints::div(0, Ints::unknown()) or expr = "0 / unknown" and res = Ints::div(0, Ints::unknown()) or
expr = "unknown / 3" and res = Ints::div(Ints::unknown(), 3) or expr = "unknown / 3" and res = Ints::div(Ints::unknown(), 3) or
expr = "unknown / unknown" and res = Ints::div(Ints::unknown(), Ints::unknown()) expr = "unknown / unknown" and res = Ints::div(Ints::unknown(), Ints::unknown())
select expr, resultString(res) select expr, resultString(res)

View File

@@ -1,22 +1,22 @@
import default import default
import semmle.code.cpp.ssa.internal.ssa.AliasAnalysis import semmle.code.cpp.ssa.internal.ssa.AliasAnalysis
import semmle.code.cpp.ir.IR import semmle.code.cpp.ir.IR
predicate shouldEscape(IRAutomaticUserVariable var) { predicate shouldEscape(IRAutomaticUserVariable var) {
exists(string name | exists(string name |
name = var.getVariable().getName() and name = var.getVariable().getName() and
name.matches("no_%") and name.matches("no_%") and
not name.matches("no_ssa_%") not name.matches("no_ssa_%")
) )
} }
from IRAutomaticUserVariable var from IRAutomaticUserVariable var
where where
exists(FunctionIR funcIR | exists(FunctionIR funcIR |
funcIR = var.getFunctionIR() and funcIR = var.getFunctionIR() and
( (
(shouldEscape(var) and variableAddressEscapes(var)) or (shouldEscape(var) and variableAddressEscapes(var)) or
(not shouldEscape(var) and not variableAddressEscapes(var)) (not shouldEscape(var) and not variableAddressEscapes(var))
) )
) )
select var select var

View File

@@ -1,11 +1,11 @@
import default import default
import semmle.code.cpp.ssa.internal.ssa.AliasAnalysis import semmle.code.cpp.ssa.internal.ssa.AliasAnalysis
import semmle.code.cpp.ir.IR import semmle.code.cpp.ir.IR
from Instruction instr, string pointsTo from Instruction instr, string pointsTo
where where
exists(IRVariable var, int bitOffset | exists(IRVariable var, int bitOffset |
resultPointsTo(instr, var, bitOffset) and resultPointsTo(instr, var, bitOffset) and
pointsTo = var.toString() + getBitOffsetString(bitOffset) pointsTo = var.toString() + getBitOffsetString(bitOffset)
) )
select instr.getLocation().toString(), instr.getOperationString(), pointsTo select instr.getLocation().toString(), instr.getOperationString(), pointsTo

View File

@@ -1,21 +1,21 @@
import default import default
import semmle.code.cpp.ssa.internal.aliased_ssa.AliasAnalysis import semmle.code.cpp.ssa.internal.aliased_ssa.AliasAnalysis
import semmle.code.cpp.ssa.SSAIR import semmle.code.cpp.ssa.SSAIR
predicate shouldEscape(IRAutomaticUserVariable var) { predicate shouldEscape(IRAutomaticUserVariable var) {
exists(string name | exists(string name |
name = var.getVariable().getName() and name = var.getVariable().getName() and
name.matches("no_%") name.matches("no_%")
) )
} }
from IRAutomaticUserVariable var from IRAutomaticUserVariable var
where where
exists(FunctionIR funcIR | exists(FunctionIR funcIR |
funcIR = var.getFunctionIR() and funcIR = var.getFunctionIR() and
( (
(shouldEscape(var) and variableAddressEscapes(var)) or (shouldEscape(var) and variableAddressEscapes(var)) or
(not shouldEscape(var) and not variableAddressEscapes(var)) (not shouldEscape(var) and not variableAddressEscapes(var))
) )
) )
select var select var

View File

@@ -1,89 +1,89 @@
import default import default
query predicate newExprs(NewExpr expr, string type, string sig, int size, int alignment, string form) { query predicate newExprs(NewExpr expr, string type, string sig, int size, int alignment, string form) {
exists(Function allocator, Type allocatedType | exists(Function allocator, Type allocatedType |
expr.getAllocator() = allocator and expr.getAllocator() = allocator and
sig = allocator.getFullSignature() and sig = allocator.getFullSignature() and
allocatedType = expr.getAllocatedType() and allocatedType = expr.getAllocatedType() and
type = allocatedType.toString() and type = allocatedType.toString() and
size = allocatedType.getSize() and size = allocatedType.getSize() and
alignment = allocatedType.getAlignment() and alignment = allocatedType.getAlignment() and
if expr.hasAlignedAllocation() then form = "aligned" else form = "" if expr.hasAlignedAllocation() then form = "aligned" else form = ""
) )
} }
query predicate newArrayExprs(NewArrayExpr expr, string type, string sig, int size, int alignment, string form) { query predicate newArrayExprs(NewArrayExpr expr, string type, string sig, int size, int alignment, string form) {
exists(Function allocator, Type elementType | exists(Function allocator, Type elementType |
expr.getAllocator() = allocator and expr.getAllocator() = allocator and
sig = allocator.getFullSignature() and sig = allocator.getFullSignature() and
elementType = expr.getAllocatedElementType() and elementType = expr.getAllocatedElementType() and
type = elementType.toString() and type = elementType.toString() and
size = elementType.getSize() and size = elementType.getSize() and
alignment = elementType.getAlignment() and alignment = elementType.getAlignment() and
if expr.hasAlignedAllocation() then form = "aligned" else form = "" if expr.hasAlignedAllocation() then form = "aligned" else form = ""
) )
} }
query predicate newExprDeallocators(NewExpr expr, string type, string sig, int size, int alignment, string form) { query predicate newExprDeallocators(NewExpr expr, string type, string sig, int size, int alignment, string form) {
exists(Function deallocator, Type allocatedType | exists(Function deallocator, Type allocatedType |
expr.getDeallocator() = deallocator and expr.getDeallocator() = deallocator and
sig = deallocator.getFullSignature() and sig = deallocator.getFullSignature() and
allocatedType = expr.getAllocatedType() and allocatedType = expr.getAllocatedType() and
type = allocatedType.toString() and type = allocatedType.toString() and
size = allocatedType.getSize() and size = allocatedType.getSize() and
alignment = allocatedType.getAlignment() and alignment = allocatedType.getAlignment() and
exists(string sized, string aligned | exists(string sized, string aligned |
(if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and (if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and
(if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and (if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and
form = sized + " " + aligned form = sized + " " + aligned
) )
) )
} }
query predicate newArrayExprDeallocators(NewArrayExpr expr, string type, string sig, int size, int alignment, string form) { query predicate newArrayExprDeallocators(NewArrayExpr expr, string type, string sig, int size, int alignment, string form) {
exists(Function deallocator, Type elementType | exists(Function deallocator, Type elementType |
expr.getDeallocator() = deallocator and expr.getDeallocator() = deallocator and
sig = deallocator.getFullSignature() and sig = deallocator.getFullSignature() and
elementType = expr.getAllocatedElementType() and elementType = expr.getAllocatedElementType() and
type = elementType.toString() and type = elementType.toString() and
size = elementType.getSize() and size = elementType.getSize() and
alignment = elementType.getAlignment() and alignment = elementType.getAlignment() and
exists(string sized, string aligned | exists(string sized, string aligned |
(if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and (if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and
(if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and (if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and
form = sized + " " + aligned form = sized + " " + aligned
) )
) )
} }
query predicate deleteExprs(DeleteExpr expr, string type, string sig, int size, int alignment, string form) { query predicate deleteExprs(DeleteExpr expr, string type, string sig, int size, int alignment, string form) {
exists(Function deallocator, Type deletedType | exists(Function deallocator, Type deletedType |
expr.getDeallocator() = deallocator and expr.getDeallocator() = deallocator and
sig = deallocator.getFullSignature() and sig = deallocator.getFullSignature() and
deletedType = expr.getDeletedObjectType() and deletedType = expr.getDeletedObjectType() and
type = deletedType.toString() and type = deletedType.toString() and
size = deletedType.getSize() and size = deletedType.getSize() and
alignment = deletedType.getAlignment() and alignment = deletedType.getAlignment() and
exists(string sized, string aligned | exists(string sized, string aligned |
(if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and (if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and
(if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and (if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and
form = sized + " " + aligned form = sized + " " + aligned
) )
) )
} }
query predicate deleteArrayExprs(DeleteArrayExpr expr, string type, string sig, int size, int alignment, string form) { query predicate deleteArrayExprs(DeleteArrayExpr expr, string type, string sig, int size, int alignment, string form) {
exists(Function deallocator, Type elementType | exists(Function deallocator, Type elementType |
expr.getDeallocator() = deallocator and expr.getDeallocator() = deallocator and
sig = deallocator.getFullSignature() and sig = deallocator.getFullSignature() and
elementType = expr.getDeletedElementType() and elementType = expr.getDeletedElementType() and
type = elementType.toString() and type = elementType.toString() and
size = elementType.getSize() and size = elementType.getSize() and
alignment = elementType.getAlignment() and alignment = elementType.getAlignment() and
exists(string sized, string aligned | exists(string sized, string aligned |
(if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and (if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and
(if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and (if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and
form = sized + " " + aligned form = sized + " " + aligned
) )
) )
} }

View File

@@ -1,5 +1,5 @@
import cpp import cpp
import semmle.code.cpp.controlflow.Guards import semmle.code.cpp.controlflow.Guards
from GuardCondition guard from GuardCondition guard
select guard select guard

View File

@@ -1,15 +1,15 @@
import default import default
string getValueCategoryString(Expr expr) { string getValueCategoryString(Expr expr) {
if expr.isLValueCategory() then if expr.isLValueCategory() then
result = "lval" result = "lval"
else if expr.isXValueCategory() then else if expr.isXValueCategory() then
result = "xval" result = "xval"
else if expr.hasLValueToRValueConversion() then else if expr.hasLValueToRValueConversion() then
result = "prval(load)" result = "prval(load)"
else else
result = "prval" result = "prval"
} }
from Cast cast from Cast cast
select cast, cast.getSemanticConversionString(), getValueCategoryString(cast), cast.getType().toString(), cast.getExpr().getType().toString() select cast, cast.getSemanticConversionString(), getValueCategoryString(cast), cast.getType().toString(), cast.getExpr().getType().toString()

View File

@@ -1 +1 @@
semmle/code/cpp/ASTSanity.ql semmle/code/cpp/ASTSanity.ql

View File

@@ -1,5 +1,5 @@
import cpp import cpp
from Expr e, Variable v from Expr e, Variable v
where varbind(unresolveElement(e), unresolveElement(v)) where varbind(unresolveElement(e), unresolveElement(v))
select e, v select e, v

View File

@@ -1,7 +1,7 @@
/** /**
* @name InitializerAccesses * @name InitializerAccesses
*/ */
import cpp import cpp
from Initializer i, VariableAccess va from Initializer i, VariableAccess va
where i.getExpr().getAChild*() = va where i.getExpr().getAChild*() = va

View File

@@ -1,6 +1,6 @@
import cpp import cpp
//this query should find the baseType of CC* to be CC, not C. //this query should find the baseType of CC* to be CC, not C.
from DerivedType t, Type baseType from DerivedType t, Type baseType
where t.getBaseType() = baseType where t.getBaseType() = baseType
select t, baseType select t, baseType

View File

@@ -1,26 +1,26 @@
import cpp import cpp
from ComparisonOperation co, string s from ComparisonOperation co, string s
where where
( (
co instanceof EqualityOperation and s = "EqualityOperation" co instanceof EqualityOperation and s = "EqualityOperation"
) or ( ) or (
co instanceof EQExpr and s = "EQExpr" co instanceof EQExpr and s = "EQExpr"
) or ( ) or (
co instanceof NEExpr and s = "NEExpr" co instanceof NEExpr and s = "NEExpr"
) or ( ) or (
co instanceof RelationalOperation and s = "RelationalOperation" co instanceof RelationalOperation and s = "RelationalOperation"
) or ( ) or (
s = "getGreaterOperand() = " + co.(RelationalOperation).getGreaterOperand().toString() s = "getGreaterOperand() = " + co.(RelationalOperation).getGreaterOperand().toString()
) or ( ) or (
s = "getLesserOperand() = " + co.(RelationalOperation).getLesserOperand().toString() s = "getLesserOperand() = " + co.(RelationalOperation).getLesserOperand().toString()
) or ( ) or (
co instanceof GTExpr and s = "GTExpr" co instanceof GTExpr and s = "GTExpr"
) or ( ) or (
co instanceof LTExpr and s = "LTExpr" co instanceof LTExpr and s = "LTExpr"
) or ( ) or (
co instanceof GEExpr and s = "GEExpr" co instanceof GEExpr and s = "GEExpr"
) or ( ) or (
co instanceof LEExpr and s = "LEExpr" co instanceof LEExpr and s = "LEExpr"
) )
select co, s select co, s

View File

@@ -1,37 +1,37 @@
import cpp import cpp
predicate describe(UnaryOperation uo, string s) predicate describe(UnaryOperation uo, string s)
{ {
( (
uo instanceof UnaryArithmeticOperation and s = "UnaryArithmeticOperation" uo instanceof UnaryArithmeticOperation and s = "UnaryArithmeticOperation"
) or ( ) or (
uo instanceof UnaryMinusExpr and s = "UnaryMinusExpr" uo instanceof UnaryMinusExpr and s = "UnaryMinusExpr"
) or ( ) or (
uo instanceof UnaryPlusExpr and s = "UnaryPlusExpr" uo instanceof UnaryPlusExpr and s = "UnaryPlusExpr"
) or ( ) or (
uo instanceof ConjugationExpr and s = "ConjugationExpr" uo instanceof ConjugationExpr and s = "ConjugationExpr"
) or ( ) or (
uo instanceof CrementOperation and s = "CrementOperation" uo instanceof CrementOperation and s = "CrementOperation"
) or ( ) or (
uo instanceof IncrementOperation and s = "IncrementOperation" uo instanceof IncrementOperation and s = "IncrementOperation"
) or ( ) or (
uo instanceof DecrementOperation and s = "DecrementOperation" uo instanceof DecrementOperation and s = "DecrementOperation"
) or ( ) or (
uo instanceof PrefixCrementOperation and s = "PrefixCrementOperation" uo instanceof PrefixCrementOperation and s = "PrefixCrementOperation"
) or ( ) or (
uo instanceof PostfixCrementOperation and s = "PostfixCrementOperation" uo instanceof PostfixCrementOperation and s = "PostfixCrementOperation"
) or ( ) or (
uo instanceof AddressOfExpr and s = "AddressOfExpr" uo instanceof AddressOfExpr and s = "AddressOfExpr"
) or ( ) or (
s = "getAddressable() = " + uo.(AddressOfExpr).getAddressable().toString() s = "getAddressable() = " + uo.(AddressOfExpr).getAddressable().toString()
) or ( ) or (
uo instanceof PointerDereferenceExpr and s = "PointerDereferenceExpr" uo instanceof PointerDereferenceExpr and s = "PointerDereferenceExpr"
) or ( ) or (
uo instanceof UnaryLogicalOperation and s = "UnaryLogicalOperation" uo instanceof UnaryLogicalOperation and s = "UnaryLogicalOperation"
) or ( ) or (
uo instanceof NotExpr and s = "NotExpr" uo instanceof NotExpr and s = "NotExpr"
) )
} }
from UnaryOperation uo from UnaryOperation uo
select uo, uo.getOperator(), concat(string s | describe(uo, s) | s, ", ") select uo, uo.getOperator(), concat(string s | describe(uo, s) | s, ", ")

View File

@@ -1,5 +1,5 @@
import cpp import cpp
from Expr e from Expr e
where e.isUnevaluated() where e.isUnevaluated()
select e select e

View File

@@ -1,5 +1,5 @@
import cpp import cpp
from Expr e from Expr e
where e.hasLValueToRValueConversion() where e.hasLValueToRValueConversion()
select e select e

View File

@@ -1,7 +1,7 @@
import cpp import cpp
from Expr e, string valcat from Expr e, string valcat
where where
e.isLValueCategory() and valcat = "lvalue" or e.isLValueCategory() and valcat = "lvalue" or
e.isXValueCategory() and valcat = "xvalue" e.isXValueCategory() and valcat = "xvalue"
select e, e.getType().toString(), valcat select e, e.getType().toString(), valcat

View File

@@ -1,11 +1,11 @@
/** /**
* @name EnumConst * @name EnumConst
* @kind table * @kind table
*/ */
import cpp import cpp
from Enum e, Declaration c, string reason from Enum e, Declaration c, string reason
where (c.(EnumConstant).getDeclaringEnum() = e and reason = "getDeclaringEnum()") or where (c.(EnumConstant).getDeclaringEnum() = e and reason = "getDeclaringEnum()") or
(c.(EnumConstant).getType() = e and reason = "getType()") or (c.(EnumConstant).getType() = e and reason = "getType()") or
(c.(Field).getDeclaringType() = e and reason = "getDeclaringType()") (c.(Field).getDeclaringType() = e and reason = "getDeclaringType()")
select e, c, reason select e, c, reason

View File

@@ -1,40 +1,40 @@
/** /**
* @name Fields * @name Fields
* @kind table * @kind table
*/ */
import cpp import cpp
predicate nameCheck(Declaration d) { predicate nameCheck(Declaration d) {
count(d.toString()) = 1 and count(d.toString()) = 1 and
count(string s | d.hasName(s)) = 1 and count(string s | d.hasName(s)) = 1 and
d.hasName(d.toString()) d.hasName(d.toString())
} }
string accessType(Field f) { string accessType(Field f) {
(f.isPublic() and result = "public") or (f.isPublic() and result = "public") or
(f.isProtected() and result = "protected") or (f.isProtected() and result = "protected") or
(f.isPrivate() and result = "private") (f.isPrivate() and result = "private")
} }
string fieldType(Field f) { string fieldType(Field f) {
result = f.getType().getAQlClass() and result = f.getType().getAQlClass() and
( (
result.matches("%Type") or result.matches("%Type") or
result = "Enum" result = "Enum"
) )
} }
string pointedType(Field f) { string pointedType(Field f) {
if f.getType() instanceof PointerType then ( if f.getType() instanceof PointerType then (
result = f.getType().(PointerType).getBaseType().toString() result = f.getType().(PointerType).getBaseType().toString()
) else ( ) else (
result = "" result = ""
) )
} }
from Class c, Field f from Class c, Field f
where f.getDeclaringType() = c and where f.getDeclaringType() = c and
c.getAField() = f and c.getAField() = f and
nameCheck(c) and nameCheck(c) and
nameCheck(f) nameCheck(f)
select c, f, accessType(f), fieldType(f), pointedType(f) select c, f, accessType(f), fieldType(f), pointedType(f)

View File

@@ -1,30 +1,30 @@
import default import default
import semmle.code.cpp.ssa.SSAIR import semmle.code.cpp.ssa.SSAIR
import semmle.code.cpp.ssa.internal.IntegerConstant import semmle.code.cpp.ssa.internal.IntegerConstant
language[monotonicAggregates] language[monotonicAggregates]
IntValue getConstantValue(Instruction instr) { IntValue getConstantValue(Instruction instr) {
result = instr.(IntegerConstantInstruction).getValue().toInt() or result = instr.(IntegerConstantInstruction).getValue().toInt() or
exists(BinaryInstruction binInstr, IntValue left, IntValue right | exists(BinaryInstruction binInstr, IntValue left, IntValue right |
binInstr = instr and binInstr = instr and
left = getConstantValue(binInstr.getLeftOperand()) and left = getConstantValue(binInstr.getLeftOperand()) and
right = getConstantValue(binInstr.getRightOperand()) and right = getConstantValue(binInstr.getRightOperand()) and
( (
binInstr instanceof AddInstruction and result = add(left, right) or binInstr instanceof AddInstruction and result = add(left, right) or
binInstr instanceof SubInstruction and result = sub(left, right) or binInstr instanceof SubInstruction and result = sub(left, right) or
binInstr instanceof MulInstruction and result = mul(left, right) or binInstr instanceof MulInstruction and result = mul(left, right) or
binInstr instanceof DivInstruction and result = div(left, right) binInstr instanceof DivInstruction and result = div(left, right)
) )
) or ) or
result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or
exists(PhiInstruction phi | exists(PhiInstruction phi |
phi = instr and phi = instr and
result = max(Instruction operand | operand = phi.getAnOperand() | getConstantValue(operand)) and result = max(Instruction operand | operand = phi.getAnOperand() | getConstantValue(operand)) and
result = min(Instruction operand | operand = phi.getAnOperand() | getConstantValue(operand)) result = min(Instruction operand | operand = phi.getAnOperand() | getConstantValue(operand))
) )
} }
from FunctionIR funcIR, int value from FunctionIR funcIR, int value
where where
value = getValue(getConstantValue(funcIR.getReturnInstruction().(ReturnValueInstruction).getReturnValue())) value = getValue(getConstantValue(funcIR.getReturnInstruction().(ReturnValueInstruction).getReturnValue()))
select funcIR, value select funcIR, value

View File

@@ -1,5 +1,5 @@
import default import default
import semmle.code.cpp.ssa.SSAIR import semmle.code.cpp.ssa.SSAIR
from FunctionIR funcIR from FunctionIR funcIR
select funcIR.toString(), count(funcIR.getABlock()) select funcIR.toString(), count(funcIR.getABlock())

View File

@@ -1,5 +1,5 @@
import cpp import cpp
from ArrayType a, ArrayAggregateLiteral al, int i from ArrayType a, ArrayAggregateLiteral al, int i
where a = al.getType() where a = al.getType()
select al, a, i, al.getElementExpr(i) select al, a, i, al.getElementExpr(i)

View File

@@ -1,6 +1,6 @@
import cpp import cpp
from ArrayType a, ArrayAggregateLiteral al, int i from ArrayType a, ArrayAggregateLiteral al, int i
where a = al.getType() where a = al.getType()
and al.isValueInitialized(i) and al.isValueInitialized(i)
select al, a, i select al, a, i

View File

@@ -1,6 +1,6 @@
import cpp import cpp
from Class c, ClassAggregateLiteral al, Field f from Class c, ClassAggregateLiteral al, Field f
where c = al.getType() where c = al.getType()
and f = c.getAField() and f = c.getAField()
select al, c, f, al.getFieldExpr(f) select al, c, f, al.getFieldExpr(f)

View File

@@ -1,6 +1,6 @@
import cpp import cpp
from Class c, ClassAggregateLiteral al, Field f from Class c, ClassAggregateLiteral al, Field f
where c = al.getType() where c = al.getType()
and al.isValueInitialized(f) and al.isValueInitialized(f)
select al, c, f select al, c, f

View File

@@ -2,13 +2,13 @@
* @name Parameters3 * @name Parameters3
* @kind table * @kind table
*/ */
import cpp import cpp
from Function f, int i, Parameter p, string pname, boolean named from Function f, int i, Parameter p, string pname, boolean named
where f.hasName("Dispatch") where f.hasName("Dispatch")
and f.getParameter(i) = p and f.getParameter(i) = p
and p.getName() = pname and p.getName() = pname
and ( and (
p.isNamed() and named = true p.isNamed() and named = true
or not p.isNamed() and named = false) or not p.isNamed() and named = false)
select f, i, pname, named select f, i, pname, named

View File

@@ -1,5 +1,5 @@
import cpp import cpp
from BreakStmt b, Stmt s from BreakStmt b, Stmt s
where b.getBreakable() = s where b.getBreakable() = s
select b, s select b, s

View File

@@ -1,4 +1,4 @@
import cpp import cpp
from Variable v from Variable v
select v select v

View File

@@ -1,5 +1,5 @@
import cpp import cpp
from Variable v, Class t from Variable v, Class t
where t = v.getType().(PointerType).getBaseType() where t = v.getType().(PointerType).getBaseType()
select v, t, count(t.getAMember()) select v, t, count(t.getAMember())

View File

@@ -1,29 +1,29 @@
import cpp import cpp
class MutexTypeForTest extends MutexType { class MutexTypeForTest extends MutexType {
MutexTypeForTest() { MutexTypeForTest() {
this.(Class).getName() = "Mutex7" this.(Class).getName() = "Mutex7"
} }
override predicate mustlockAccess(FunctionCall fc, Expr arg) { override predicate mustlockAccess(FunctionCall fc, Expr arg) {
exists(Function f | exists(Function f |
f = fc.getTarget() and f = fc.getTarget() and
f.getName() = "custom_l" and f.getName() = "custom_l" and
f.getDeclaringType() = this and f.getDeclaringType() = this and
arg = fc.getQualifier() arg = fc.getQualifier()
) )
} }
override predicate trylockAccess(FunctionCall fc, Expr arg) { override predicate trylockAccess(FunctionCall fc, Expr arg) {
none() none()
} }
override predicate unlockAccess(FunctionCall fc, Expr arg) { override predicate unlockAccess(FunctionCall fc, Expr arg) {
exists(Function f | exists(Function f |
f = fc.getTarget() and f = fc.getTarget() and
f.getName() = "custom_ul" and f.getName() = "custom_ul" and
f.getDeclaringType() = this and f.getDeclaringType() = this and
arg = fc.getQualifier() arg = fc.getQualifier()
) )
} }
} }

View File

@@ -1,4 +1,4 @@
import Critical.MemoryFreed import Critical.MemoryFreed
from FreedExpr fe from FreedExpr fe
select fe select fe

View File

@@ -1 +1 @@
Critical/NewArrayDeleteMismatch.ql Critical/NewArrayDeleteMismatch.ql

View File

@@ -1 +1 @@
Critical/NewDeleteArrayMismatch.ql Critical/NewDeleteArrayMismatch.ql

View File

@@ -1 +1 @@
Critical/NewFreeMismatch.ql Critical/NewFreeMismatch.ql

View File

@@ -1,5 +1,5 @@
import cpp import cpp
from ControlFlowNode n from ControlFlowNode n
select n.getLocation().getStartLine(), n.getControlFlowScope(), n, select n.getLocation().getStartLine(), n.getControlFlowScope(), n,
count(n.getAPredecessor()), count(n.getASuccessor()) count(n.getAPredecessor()), count(n.getASuccessor())

View File

@@ -1 +1 @@
Bad Practices/Comments/CommentedOutCode.ql Bad Practices/Comments/CommentedOutCode.ql

View File

@@ -1 +1 @@
Bad Practices/Comments/TodoComments.ql Bad Practices/Comments/TodoComments.ql

View File

@@ -1 +1 @@
Bad Practices/Naming Conventions/ConfusingMethodNames.ql Bad Practices/Naming Conventions/ConfusingMethodNames.ql

View File

@@ -1 +1 @@
Documentation/XmldocExtraParam.ql Documentation/XmldocExtraParam.ql

View File

@@ -1 +1 @@
Documentation/XmldocMissingException.ql Documentation/XmldocMissingException.ql

View File

@@ -1 +1 @@
Documentation/XmldocMissingParam.ql Documentation/XmldocMissingParam.ql

View File

@@ -1 +1 @@
Documentation/XmldocMissingReturn.ql Documentation/XmldocMissingReturn.ql

View File

@@ -1 +1 @@
Documentation/XmldocMissingSummary.ql Documentation/XmldocMissingSummary.ql

View File

@@ -1 +1 @@
Documentation/XmldocMissingTypeParam.ql Documentation/XmldocMissingTypeParam.ql

View File

@@ -1 +1 @@
Likely Bugs/Statements/EmptyBlock.ql Likely Bugs/Statements/EmptyBlock.ql

View File

@@ -1 +1 @@
Language Abuse/ChainedIs.ql Language Abuse/ChainedIs.ql

View File

@@ -1 +1 @@
Language Abuse/ForeachCapture.ql Language Abuse/ForeachCapture.ql

Some files were not shown because too many files have changed in this diff Show More