Merge remote-tracking branch 'upstream/master' into detect-conflated-memory

Conflicts:
	cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll
	cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.qll
	cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.qll
	cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected
	cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity_unsound.expected
	cpp/ql/test/library-tests/ir/ir/raw_sanity.expected
	cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected
	cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity_unsound.expected
	cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected
	cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity_unsound.expected
	cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected
	cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity_unsound.expected
	cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected
	cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected
	cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected
	csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRSanity.qll
	csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRSanity.qll
	csharp/ql/test/library-tests/ir/ir/raw_ir_sanity.expected
	csharp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected
This commit is contained in:
Jonas Jensen
2020-03-25 11:55:39 +01:00
161 changed files with 16053 additions and 14692 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -243,7 +243,7 @@ private module Cached {
* - Types are checked using the `compatibleTypes()` relation.
*/
cached
module Final {
private module Final {
/**
* Holds if `p` can flow to `node` in the same callable using only
* value-preserving steps, not taking call contexts into account.

View File

@@ -8,6 +8,22 @@ abstract class BuiltInOperation extends Expr {
override string getCanonicalQLClass() { result = "BuiltInOperation" }
}
/**
* A C/C++ built-in operation that is used to support functions with variable numbers of arguments.
* This includes `va_start`, `va_end`, `va_copy`, and `va_arg`.
*/
class VarArgsExpr extends BuiltInOperation {
VarArgsExpr() {
this instanceof BuiltInVarArgsStart
or
this instanceof BuiltInVarArgsEnd
or
this instanceof BuiltInVarArg
or
this instanceof BuiltInVarArgCopy
}
}
/**
* A C/C++ `__builtin_va_start` built-in operation (used by some
* implementations of `va_start`).
@@ -20,6 +36,16 @@ class BuiltInVarArgsStart extends BuiltInOperation, @vastartexpr {
override string toString() { result = "__builtin_va_start" }
override string getCanonicalQLClass() { result = "BuiltInVarArgsStart" }
/**
* Gets the `va_list` argument.
*/
final Expr getVAList() { result = getChild(0) }
/**
* Gets the argument that specifies the last named parameter before the ellipsis.
*/
final VariableAccess getLastNamedParameter() { result = getChild(1) }
}
/**
@@ -35,6 +61,11 @@ class BuiltInVarArgsEnd extends BuiltInOperation, @vaendexpr {
override string toString() { result = "__builtin_va_end" }
override string getCanonicalQLClass() { result = "BuiltInVarArgsEnd" }
/**
* Gets the `va_list` argument.
*/
final Expr getVAList() { result = getChild(0) }
}
/**
@@ -48,6 +79,11 @@ class BuiltInVarArg extends BuiltInOperation, @vaargexpr {
override string toString() { result = "__builtin_va_arg" }
override string getCanonicalQLClass() { result = "BuiltInVarArg" }
/**
* Gets the `va_list` argument.
*/
final Expr getVAList() { result = getChild(0) }
}
/**
@@ -63,6 +99,16 @@ class BuiltInVarArgCopy extends BuiltInOperation, @vacopyexpr {
override string toString() { result = "__builtin_va_copy" }
override string getCanonicalQLClass() { result = "BuiltInVarArgCopy" }
/**
* Gets the destination `va_list` argument.
*/
final Expr getDestinationVAList() { result = getChild(0) }
/**
* Gets the the source `va_list` argument.
*/
final Expr getSourceVAList() { result = getChild(1) }
}
/**

View File

@@ -243,7 +243,7 @@ private module Cached {
* - Types are checked using the `compatibleTypes()` relation.
*/
cached
module Final {
private module Final {
/**
* Holds if `p` can flow to `node` in the same callable using only
* value-preserving steps, not taking call contexts into account.

View File

@@ -70,7 +70,7 @@ private newtype TOpcode =
TVarArgsStart() or
TVarArgsEnd() or
TVarArg() or
TVarArgCopy() or
TNextVarArg() or
TCallSideEffect() or
TCallReadSideEffect() or
TIndirectReadSideEffect() or
@@ -629,20 +629,20 @@ module Opcode {
final override string toString() { result = "BuiltIn" }
}
class VarArgsStart extends BuiltInOperationOpcode, TVarArgsStart {
class VarArgsStart extends UnaryOpcode, TVarArgsStart {
final override string toString() { result = "VarArgsStart" }
}
class VarArgsEnd extends BuiltInOperationOpcode, TVarArgsEnd {
class VarArgsEnd extends UnaryOpcode, TVarArgsEnd {
final override string toString() { result = "VarArgsEnd" }
}
class VarArg extends BuiltInOperationOpcode, TVarArg {
class VarArg extends UnaryOpcode, TVarArg {
final override string toString() { result = "VarArg" }
}
class VarArgCopy extends BuiltInOperationOpcode, TVarArgCopy {
final override string toString() { result = "VarArgCopy" }
class NextVarArg extends UnaryOpcode, TNextVarArg {
final override string toString() { result = "NextVarArg" }
}
class CallSideEffect extends WriteSideEffectOpcode, EscapedWriteOpcode, MayWriteOpcode,

View File

@@ -5,6 +5,7 @@ import IRTypeSanity // module is in IRType.qll
module InstructionSanity {
private import internal.InstructionImports as Imports
private import Imports::OperandTag
private import Imports::Overlap
private import internal.IRInternal
/**
@@ -302,4 +303,18 @@ module InstructionSanity {
instr.isResultConflated() and
not shouldBeConflated(instr)
}
query predicate invalidOverlap(
MemoryOperand useOperand, string message, IRFunction func, string funcText
) {
exists(Overlap overlap |
overlap = useOperand.getDefinitionOverlap() and
overlap instanceof MayPartiallyOverlap and
message =
"MemoryOperand '" + useOperand.toString() + "' has a `getDefinitionOverlap()` of '" +
overlap.toString() + "'." and
func = useOperand.getEnclosingIRFunction() and
funcText = Language::getIdentityString(func.getFunction())
)
}
}

View File

@@ -384,6 +384,8 @@ class PositionalArgumentOperand extends ArgumentOperand {
class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override string toString() { result = "SideEffect" }
}
/**

View File

@@ -3,3 +3,4 @@ import semmle.code.cpp.ir.implementation.IRType as IRType
import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind
import semmle.code.cpp.ir.implementation.Opcode as Opcode
import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag
import semmle.code.cpp.ir.internal.Overlap as Overlap

View File

@@ -107,14 +107,15 @@ private module Cached {
oldOperand instanceof OldIR::NonPhiMemoryOperand and
exists(
OldBlock useBlock, int useRank, Alias::MemoryLocation useLocation,
Alias::MemoryLocation defLocation, OldBlock defBlock, int defRank, int defOffset
Alias::MemoryLocation defLocation, OldBlock defBlock, int defRank, int defOffset,
Alias::MemoryLocation actualDefLocation
|
useLocation = Alias::getOperandMemoryLocation(oldOperand) and
hasUseAtRank(useLocation, useBlock, useRank, oldInstruction) and
definitionReachesUse(useLocation, defBlock, defRank, useBlock, useRank) and
hasDefinitionAtRank(useLocation, defLocation, defBlock, defRank, defOffset) and
instr = getDefinitionOrChiInstruction(defBlock, defOffset, defLocation, _) and
overlap = Alias::getOverlap(defLocation, useLocation)
instr = getDefinitionOrChiInstruction(defBlock, defOffset, defLocation, actualDefLocation) and
overlap = Alias::getOverlap(actualDefLocation, useLocation)
)
}

View File

@@ -5,6 +5,7 @@ import IRTypeSanity // module is in IRType.qll
module InstructionSanity {
private import internal.InstructionImports as Imports
private import Imports::OperandTag
private import Imports::Overlap
private import internal.IRInternal
/**
@@ -302,4 +303,18 @@ module InstructionSanity {
instr.isResultConflated() and
not shouldBeConflated(instr)
}
query predicate invalidOverlap(
MemoryOperand useOperand, string message, IRFunction func, string funcText
) {
exists(Overlap overlap |
overlap = useOperand.getDefinitionOverlap() and
overlap instanceof MayPartiallyOverlap and
message =
"MemoryOperand '" + useOperand.toString() + "' has a `getDefinitionOverlap()` of '" +
overlap.toString() + "'." and
func = useOperand.getEnclosingIRFunction() and
funcText = Language::getIdentityString(func.getFunction())
)
}
}

View File

@@ -384,6 +384,8 @@ class PositionalArgumentOperand extends ArgumentOperand {
class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override string toString() { result = "SideEffect" }
}
/**

View File

@@ -3,3 +3,4 @@ import semmle.code.cpp.ir.implementation.IRType as IRType
import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind
import semmle.code.cpp.ir.implementation.Opcode as Opcode
import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag
import semmle.code.cpp.ir.internal.Overlap as Overlap

View File

@@ -64,6 +64,13 @@ newtype TInstructionTag =
InitializerElementAddressTag() or
InitializerElementDefaultValueTag() or
InitializerElementDefaultValueStoreTag() or
VarArgsStartEllipsisAddressTag() or
VarArgsStartTag() or
VarArgsVAListLoadTag() or
VarArgsArgAddressTag() or
VarArgsArgLoadTag() or
VarArgsMoveNextTag() or
VarArgsVAListStoreTag() or
AsmTag() or
AsmInputTag(int elementIndex) { exists(AsmStmt asm | exists(asm.getChild(elementIndex))) }
@@ -188,6 +195,20 @@ string getInstructionTagId(TInstructionTag tag) {
or
tag = InitializerElementDefaultValueStoreTag() and result = "InitElemDefValStore"
or
tag = VarArgsStartEllipsisAddressTag() and result = "VarArgsStartEllipsisAddr"
or
tag = VarArgsStartTag() and result = "VarArgsStart"
or
tag = VarArgsVAListLoadTag() and result = "VarArgsVAListLoad"
or
tag = VarArgsArgAddressTag() and result = "VarArgsArgAddr"
or
tag = VarArgsArgLoadTag() and result = "VaArgsArgLoad"
or
tag = VarArgsMoveNextTag() and result = "VarArgsMoveNext"
or
tag = VarArgsVAListStoreTag() and result = "VarArgsVAListStore"
or
tag = AsmTag() and result = "Asm"
or
exists(int index | tag = AsmInputTag(index) and result = "AsmInputTag(" + index + ")")

View File

@@ -83,6 +83,10 @@ private predicate ignoreExprAndDescendants(Expr expr) {
exists(DeleteExpr deleteExpr | deleteExpr.getAllocatorCall() = expr)
or
exists(DeleteArrayExpr deleteArrayExpr | deleteArrayExpr.getAllocatorCall() = expr)
or
exists(BuiltInVarArgsStart vaStartExpr |
vaStartExpr.getLastNamedParameter().getFullyConverted() = expr
)
}
/**

View File

@@ -2020,7 +2020,12 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {
override BuiltInOperation expr;
TranslatedBuiltInOperation() {
not expr instanceof BuiltInOperationBuiltInAddressOf // Handled specially
// The following expressions are handled specially.
not expr instanceof BuiltInOperationBuiltInAddressOf and
not expr instanceof BuiltInVarArgsStart and
not expr instanceof BuiltInVarArg and
not expr instanceof BuiltInVarArgsEnd and
not expr instanceof BuiltInVarArgCopy
}
final override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) }
@@ -2075,39 +2080,318 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {
}
/**
* The IR translation of a `BuiltInVarArgsStart` expression.
* Holds if the expression `expr` is one of the `va_list` operands to a `va_*` macro.
*/
class TranslatedVarArgsStart extends TranslatedBuiltInOperation {
override BuiltInVarArgsStart expr;
final override Opcode getOpcode() { result instanceof Opcode::VarArgsStart }
private predicate isVAListExpr(Expr expr) {
exists(VarArgsExpr parent, Expr originalExpr |
(
originalExpr = parent.(BuiltInVarArgsStart).getVAList()
or
originalExpr = parent.(BuiltInVarArgsEnd).getVAList()
or
originalExpr = parent.(BuiltInVarArg).getVAList()
or
originalExpr = parent.(BuiltInVarArgCopy).getSourceVAList()
or
originalExpr = parent.(BuiltInVarArgCopy).getDestinationVAList()
) and
expr = originalExpr.getFullyConverted()
)
}
/**
* The IR translation of a `BuiltInVarArgsEnd` expression.
* Gets the type of the `va_list` being accessed by `expr`, where `expr` is a `va_list` operand of a
* `va_*` macro.
*
* In the Unix ABI, `va_list` is declared as `typedef struct __va_list_tag va_list[1];`. When used
* as the type of a local variable, this gets an implicit array-to-pointer conversion, so that the
* actual argument to the `va_*` macro is a prvalue of type `__va_list_tag*`. When used as the type
* of a function parameter, the parameter's type decays to `__va_list_tag*`, so that the argument
* to the `va_*` macro is still a prvalue of type `__va_list_tag*`, with no implicit conversion
* necessary. In either case, we treat `__va_list_tag` as the representative type of the `va_list`.
*
* In the Windows ABI, `va_list` is declared as a pointer type (usually `char*`). Whether used as
* the type of a local variable or of a parameter, this means that the argument to the `va_*` macro
* is always an _lvalue_ of type `char*`. We treat `char*` as the representative type of the
* `va_list`.
*/
class TranslatedVarArgsEnd extends TranslatedBuiltInOperation {
override BuiltInVarArgsEnd expr;
private Type getVAListType(Expr expr) {
isVAListExpr(expr) and
if expr.isPRValueCategory()
then
// In the Unix ABI, this will be a prvalue of type `__va_list_tag*`. We want the `__va_list_tag`
// type.
result = expr.getType().getUnderlyingType().(PointerType).getBaseType()
else
// In the Windows ABI, this will be an lvalue of some pointer type. We want that pointer type.
result = expr.getType()
}
final override Opcode getOpcode() { result instanceof Opcode::VarArgsEnd }
/**
* The IR translation of a `BuiltInVarArgsStart` expression.
*/
class TranslatedVarArgsStart extends TranslatedNonConstantExpr {
override BuiltInVarArgsStart expr;
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = VarArgsStartEllipsisAddressTag() and
opcode instanceof Opcode::VariableAddress and
resultType = getEllipsisVariableGLValueType()
or
tag = VarArgsStartTag() and
opcode instanceof Opcode::VarArgsStart and
resultType = getTypeForPRValue(getVAListType(expr.getVAList().getFullyConverted()))
or
tag = VarArgsVAListStoreTag() and
opcode instanceof Opcode::Store and
resultType = getTypeForPRValue(getVAListType(expr.getVAList().getFullyConverted()))
}
final override Instruction getFirstInstruction() {
result = getInstruction(VarArgsStartEllipsisAddressTag())
}
final override Instruction getResult() { none() }
final override TranslatedElement getChild(int id) { id = 0 and result = getVAList() }
private TranslatedExpr getVAList() {
result = getTranslatedExpr(expr.getVAList().getFullyConverted())
}
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = VarArgsStartEllipsisAddressTag() and
kind instanceof GotoEdge and
result = getInstruction(VarArgsStartTag())
or
tag = VarArgsStartTag() and
kind instanceof GotoEdge and
result = getVAList().getFirstInstruction()
or
tag = VarArgsVAListStoreTag() and
kind instanceof GotoEdge and
result = getParent().getChildSuccessor(this)
}
final override Instruction getChildSuccessor(TranslatedElement child) {
child = getVAList() and
result = getInstruction(VarArgsVAListStoreTag())
}
final override IRVariable getInstructionVariable(InstructionTag tag) {
tag = VarArgsStartEllipsisAddressTag() and
result = getEnclosingFunction().getEllipsisVariable()
}
final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
tag = VarArgsStartTag() and
operandTag instanceof UnaryOperandTag and
result = getInstruction(VarArgsStartEllipsisAddressTag())
or
tag = VarArgsVAListStoreTag() and
(
operandTag instanceof AddressOperandTag and result = getVAList().getResult()
or
operandTag instanceof StoreValueOperandTag and result = getInstruction(VarArgsStartTag())
)
}
}
/**
* The IR translation of a `BuiltInVarArg` expression.
*/
class TranslatedVarArg extends TranslatedBuiltInOperation {
class TranslatedVarArg extends TranslatedNonConstantExpr {
override BuiltInVarArg expr;
final override Opcode getOpcode() { result instanceof Opcode::VarArg }
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = VarArgsVAListLoadTag() and
opcode instanceof Opcode::Load and
resultType = getTypeForPRValue(getVAListType(expr.getVAList().getFullyConverted()))
or
tag = VarArgsArgAddressTag() and
opcode instanceof Opcode::VarArg and
resultType = getResultType()
or
tag = VarArgsMoveNextTag() and
opcode instanceof Opcode::NextVarArg and
resultType = getTypeForPRValue(getVAListType(expr.getVAList().getFullyConverted()))
or
tag = VarArgsVAListStoreTag() and
opcode instanceof Opcode::Store and
resultType = getTypeForPRValue(getVAListType(expr.getVAList().getFullyConverted()))
}
final override Instruction getFirstInstruction() { result = getVAList().getFirstInstruction() }
final override Instruction getResult() { result = getInstruction(VarArgsArgAddressTag()) }
final override TranslatedElement getChild(int id) { id = 0 and result = getVAList() }
private TranslatedExpr getVAList() {
result = getTranslatedExpr(expr.getVAList().getFullyConverted())
}
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = VarArgsVAListLoadTag() and
kind instanceof GotoEdge and
result = getInstruction(VarArgsArgAddressTag())
or
tag = VarArgsArgAddressTag() and
kind instanceof GotoEdge and
result = getInstruction(VarArgsMoveNextTag())
or
tag = VarArgsMoveNextTag() and
kind instanceof GotoEdge and
result = getInstruction(VarArgsVAListStoreTag())
or
tag = VarArgsVAListStoreTag() and
kind instanceof GotoEdge and
result = getParent().getChildSuccessor(this)
}
final override Instruction getChildSuccessor(TranslatedElement child) {
child = getVAList() and
result = getInstruction(VarArgsVAListLoadTag())
}
final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
tag = VarArgsVAListLoadTag() and
(
operandTag instanceof AddressOperandTag and
result = getVAList().getResult()
or
operandTag instanceof LoadOperandTag and
result = getEnclosingFunction().getUnmodeledDefinitionInstruction()
)
or
tag = VarArgsArgAddressTag() and
operandTag instanceof UnaryOperandTag and
result = getInstruction(VarArgsVAListLoadTag())
or
tag = VarArgsMoveNextTag() and
operandTag instanceof UnaryOperandTag and
result = getInstruction(VarArgsVAListLoadTag())
or
tag = VarArgsVAListStoreTag() and
(
operandTag instanceof AddressOperandTag and result = getVAList().getResult()
or
operandTag instanceof StoreValueOperandTag and result = getInstruction(VarArgsMoveNextTag())
)
}
}
/**
* The IR translation of a `BuiltInVarArgsEnd` expression.
*/
class TranslatedVarArgsEnd extends TranslatedNonConstantExpr {
override BuiltInVarArgsEnd expr;
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = OnlyInstructionTag() and
opcode instanceof Opcode::VarArgsEnd and
resultType = getVoidType()
}
final override Instruction getFirstInstruction() { result = getVAList().getFirstInstruction() }
final override Instruction getResult() { none() }
final override TranslatedElement getChild(int id) { id = 0 and result = getVAList() }
private TranslatedExpr getVAList() {
result = getTranslatedExpr(expr.getVAList().getFullyConverted())
}
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
kind instanceof GotoEdge and
result = getParent().getChildSuccessor(this)
}
final override Instruction getChildSuccessor(TranslatedElement child) {
child = getVAList() and
result = getInstruction(OnlyInstructionTag())
}
final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
tag = OnlyInstructionTag() and
operandTag instanceof UnaryOperandTag and
result = getVAList().getResult()
}
}
/**
* The IR translation of a `BuiltInVarArgCopy` expression.
*/
class TranslatedVarArgCopy extends TranslatedBuiltInOperation {
class TranslatedVarArgCopy extends TranslatedNonConstantExpr {
override BuiltInVarArgCopy expr;
final override Opcode getOpcode() { result instanceof Opcode::VarArgCopy }
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = VarArgsVAListLoadTag() and
opcode instanceof Opcode::Load and
resultType = getTypeForPRValue(getVAListType(expr.getSourceVAList().getFullyConverted()))
or
tag = VarArgsVAListStoreTag() and
opcode instanceof Opcode::Store and
resultType = getTypeForPRValue(getVAListType(expr.getDestinationVAList().getFullyConverted()))
}
final override Instruction getFirstInstruction() {
result = getSourceVAList().getFirstInstruction()
}
final override Instruction getResult() { result = getInstruction(VarArgsVAListStoreTag()) }
final override TranslatedElement getChild(int id) {
id = 0 and result = getDestinationVAList()
or
id = 1 and result = getSourceVAList()
}
private TranslatedExpr getDestinationVAList() {
result = getTranslatedExpr(expr.getDestinationVAList().getFullyConverted())
}
private TranslatedExpr getSourceVAList() {
result = getTranslatedExpr(expr.getSourceVAList().getFullyConverted())
}
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = VarArgsVAListLoadTag() and
kind instanceof GotoEdge and
result = getDestinationVAList().getFirstInstruction()
or
tag = VarArgsVAListStoreTag() and
kind instanceof GotoEdge and
result = getParent().getChildSuccessor(this)
}
final override Instruction getChildSuccessor(TranslatedElement child) {
child = getSourceVAList() and
result = getInstruction(VarArgsVAListLoadTag())
or
child = getDestinationVAList() and
result = getInstruction(VarArgsVAListStoreTag())
}
final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
tag = VarArgsVAListLoadTag() and
(
operandTag instanceof AddressOperandTag and
result = getSourceVAList().getResult()
or
operandTag instanceof LoadOperandTag and
result = getEnclosingFunction().getUnmodeledDefinitionInstruction()
)
or
tag = VarArgsVAListStoreTag() and
(
operandTag instanceof AddressOperandTag and result = getDestinationVAList().getResult()
or
operandTag instanceof StoreValueOperandTag and result = getInstruction(VarArgsVAListLoadTag())
)
}
}
/**

View File

@@ -43,6 +43,12 @@ private int getEllipsisVariableByteSize() {
)
}
CppType getEllipsisVariablePRValueType() {
result = getUnknownOpaqueType(getEllipsisVariableByteSize())
}
CppType getEllipsisVariableGLValueType() { result = getTypeForGLValue(any(UnknownType t)) }
/**
* Represents the IR translation of a function. This is the root elements for
* all other elements associated with this function.
@@ -280,7 +286,7 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction {
or
tag = EllipsisTempVar() and
func.isVarargs() and
type = getUnknownOpaqueType(getEllipsisVariableByteSize())
type = getEllipsisVariablePRValueType()
}
/**
@@ -298,6 +304,11 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction {
result = getIRTempVariable(func, ReturnValueTempVar())
}
/**
* Get the variable that represents the `...` parameter, if any.
*/
final IREllipsisVariable getEllipsisVariable() { result.getEnclosingFunction() = func }
/**
* Holds if the function has a non-`void` return type.
*/
@@ -512,13 +523,13 @@ class TranslatedEllipsisParameter extends TranslatedParameter, TTranslatedEllips
final override predicate hasIndirection() { any() }
final override CppType getGLValueType() { result = getTypeForGLValue(any(UnknownType t)) }
final override CppType getGLValueType() { result = getEllipsisVariableGLValueType() }
final override CppType getPRValueType() {
result = getUnknownOpaqueType(getEllipsisVariableByteSize())
final override CppType getPRValueType() { result = getEllipsisVariablePRValueType() }
final override IREllipsisVariable getIRVariable() {
result = getTranslatedFunction(func).getEllipsisVariable()
}
final override IREllipsisVariable getIRVariable() { result.getEnclosingFunction() = func }
}
private TranslatedConstructorInitList getTranslatedConstructorInitList(Function func) {

View File

@@ -5,6 +5,7 @@ import IRTypeSanity // module is in IRType.qll
module InstructionSanity {
private import internal.InstructionImports as Imports
private import Imports::OperandTag
private import Imports::Overlap
private import internal.IRInternal
/**
@@ -302,4 +303,18 @@ module InstructionSanity {
instr.isResultConflated() and
not shouldBeConflated(instr)
}
query predicate invalidOverlap(
MemoryOperand useOperand, string message, IRFunction func, string funcText
) {
exists(Overlap overlap |
overlap = useOperand.getDefinitionOverlap() and
overlap instanceof MayPartiallyOverlap and
message =
"MemoryOperand '" + useOperand.toString() + "' has a `getDefinitionOverlap()` of '" +
overlap.toString() + "'." and
func = useOperand.getEnclosingIRFunction() and
funcText = Language::getIdentityString(func.getFunction())
)
}
}

View File

@@ -384,6 +384,8 @@ class PositionalArgumentOperand extends ArgumentOperand {
class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override string toString() { result = "SideEffect" }
}
/**

View File

@@ -3,3 +3,4 @@ import semmle.code.cpp.ir.implementation.IRType as IRType
import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind
import semmle.code.cpp.ir.implementation.Opcode as Opcode
import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag
import semmle.code.cpp.ir.internal.Overlap as Overlap

View File

@@ -107,14 +107,15 @@ private module Cached {
oldOperand instanceof OldIR::NonPhiMemoryOperand and
exists(
OldBlock useBlock, int useRank, Alias::MemoryLocation useLocation,
Alias::MemoryLocation defLocation, OldBlock defBlock, int defRank, int defOffset
Alias::MemoryLocation defLocation, OldBlock defBlock, int defRank, int defOffset,
Alias::MemoryLocation actualDefLocation
|
useLocation = Alias::getOperandMemoryLocation(oldOperand) and
hasUseAtRank(useLocation, useBlock, useRank, oldInstruction) and
definitionReachesUse(useLocation, defBlock, defRank, useBlock, useRank) and
hasDefinitionAtRank(useLocation, defLocation, defBlock, defRank, defOffset) and
instr = getDefinitionOrChiInstruction(defBlock, defOffset, defLocation, _) and
overlap = Alias::getOverlap(defLocation, useLocation)
instr = getDefinitionOrChiInstruction(defBlock, defOffset, defLocation, actualDefLocation) and
overlap = Alias::getOverlap(actualDefLocation, useLocation)
)
}