Merge remote-tracking branch 'upstream/master' into DefaultTaintTracking-Configuration

This commit is contained in:
Jonas Jensen
2020-04-05 07:27:07 +02:00
75 changed files with 1905 additions and 337 deletions

View File

@@ -30,7 +30,13 @@ predicate functionsMissingReturnStmt(Function f, ControlFlowNode blame) {
) and
exists(ReturnStmt s |
f.getAPredecessor() = s and
blame = s.getAPredecessor()
(
blame = s.getAPredecessor() and
count(blame.getASuccessor()) = 1
or
blame = s and
exists(ControlFlowNode pred | pred = s.getAPredecessor() | count(pred.getASuccessor()) != 1)
)
)
}

View File

@@ -2,6 +2,7 @@ import semmle.code.cpp.Element
private import semmle.code.cpp.Enclosing
private import semmle.code.cpp.internal.ResolveClass
private import semmle.code.cpp.internal.AddressConstantExpression
private import semmle.code.cpp.models.implementations.Allocation
/**
* A C/C++ expression.
@@ -804,8 +805,10 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr {
* call the constructor of `T` but will not allocate memory.
*/
Expr getPlacementPointer() {
isStandardPlacementNewAllocator(this.getAllocator()) and
result = this.getAllocatorCall().getArgument(1)
result =
this
.getAllocatorCall()
.getArgument(this.getAllocator().(OperatorNewAllocationFunction).getPlacementArgument())
}
}
@@ -1194,12 +1197,6 @@ private predicate convparents(Expr child, int idx, Element parent) {
)
}
private predicate isStandardPlacementNewAllocator(Function operatorNew) {
operatorNew.getName().matches("operator new%") and
operatorNew.getNumberOfParameters() = 2 and
operatorNew.getParameter(1).getType() instanceof VoidPointerType
}
// Pulled out for performance. See QL-796.
private predicate hasNoConversions(Expr e) { not e.hasConversion() }

View File

@@ -0,0 +1,17 @@
private import internal.ValueNumberingImports
private import ValueNumbering
/**
* Provides additional information about value numbering in IR dumps.
*/
class ValueNumberPropertyProvider extends IRPropertyProvider {
override string getInstructionProperty(Instruction instr, string key) {
exists(ValueNumber vn |
vn = valueNumber(instr) and
key = "valnum" and
if strictcount(vn.getAnInstruction()) > 1
then result = vn.getDebugString()
else result = "unique"
)
}
}

View File

@@ -1,21 +1,6 @@
private import internal.ValueNumberingInternal
private import internal.ValueNumberingImports
/**
* Provides additional information about value numbering in IR dumps.
*/
class ValueNumberPropertyProvider extends IRPropertyProvider {
override string getInstructionProperty(Instruction instr, string key) {
exists(ValueNumber vn |
vn = valueNumber(instr) and
key = "valnum" and
if strictcount(vn.getAnInstruction()) > 1
then result = vn.getDebugString()
else result = "unique"
)
}
}
/**
* The value number assigned to a particular set of instructions that produce equivalent results.
*/

View File

@@ -0,0 +1,17 @@
private import internal.ValueNumberingImports
private import ValueNumbering
/**
* Provides additional information about value numbering in IR dumps.
*/
class ValueNumberPropertyProvider extends IRPropertyProvider {
override string getInstructionProperty(Instruction instr, string key) {
exists(ValueNumber vn |
vn = valueNumber(instr) and
key = "valnum" and
if strictcount(vn.getAnInstruction()) > 1
then result = vn.getDebugString()
else result = "unique"
)
}
}

View File

@@ -1,21 +1,6 @@
private import internal.ValueNumberingInternal
private import internal.ValueNumberingImports
/**
* Provides additional information about value numbering in IR dumps.
*/
class ValueNumberPropertyProvider extends IRPropertyProvider {
override string getInstructionProperty(Instruction instr, string key) {
exists(ValueNumber vn |
vn = valueNumber(instr) and
key = "valnum" and
if strictcount(vn.getAnInstruction()) > 1
then result = vn.getDebugString()
else result = "unique"
)
}
}
/**
* The value number assigned to a particular set of instructions that produce equivalent results.
*/

View File

@@ -206,7 +206,44 @@ abstract class TranslatedCall extends TranslatedExpr {
predicate hasPreciseSideEffect() { exists(getSideEffects()) }
TranslatedSideEffects getSideEffects() { result.getCall() = expr }
final TranslatedSideEffects getSideEffects() { result.getExpr() = expr }
}
abstract class TranslatedSideEffects extends TranslatedElement {
abstract Expr getExpr();
final override Locatable getAST() { result = getExpr() }
final override Function getFunction() { result = getExpr().getEnclosingFunction() }
override TranslatedElement getChild(int i) {
result =
rank[i + 1](TranslatedSideEffect tse, int isWrite, int index |
(
tse.getCall() = getExpr() and
tse.getArgumentIndex() = index and
if tse.isWrite() then isWrite = 1 else isWrite = 0
)
|
tse order by isWrite, index
)
}
final override Instruction getChildSuccessor(TranslatedElement te) {
exists(int i |
getChild(i) = te and
if exists(getChild(i + 1))
then result = getChild(i + 1).getFirstInstruction()
else result = getParent().getChildSuccessor(this)
)
}
/**
* Gets the `TranslatedFunction` containing this expression.
*/
final TranslatedFunction getEnclosingFunction() {
result = getTranslatedFunction(getExpr().getEnclosingFunction())
}
}
/**
@@ -308,56 +345,27 @@ class TranslatedStructorCall extends TranslatedFunctionCall {
override predicate hasQualifier() { any() }
}
class TranslatedSideEffects extends TranslatedElement, TTranslatedSideEffects {
Call expr;
class TranslatedAllocationSideEffects extends TranslatedSideEffects,
TTranslatedAllocationSideEffects {
AllocationExpr expr;
TranslatedSideEffects() { this = TTranslatedSideEffects(expr) }
TranslatedAllocationSideEffects() { this = TTranslatedAllocationSideEffects(expr) }
override string toString() { result = "(side effects for " + expr.toString() + ")" }
final override AllocationExpr getExpr() { result = expr }
override Locatable getAST() { result = expr }
override string toString() { result = "(allocation side effects for " + expr.toString() + ")" }
Call getCall() { result = expr }
override TranslatedElement getChild(int i) {
result =
rank[i + 1](TranslatedSideEffect tse, int isWrite, int index |
(
tse.getCall() = getCall() and
tse.getArgumentIndex() = index and
if tse.isWrite() then isWrite = 1 else isWrite = 0
)
|
tse order by isWrite, index
)
}
override Instruction getChildSuccessor(TranslatedElement te) {
exists(int i |
getChild(i) = te and
if exists(getChild(i + 1))
then result = getChild(i + 1).getFirstInstruction()
else result = getParent().getChildSuccessor(this)
)
}
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
expr.getTarget() instanceof AllocationFunction and
opcode instanceof Opcode::InitializeDynamicAllocation and
tag = OnlyInstructionTag() and
type = getUnknownType()
}
override Instruction getFirstInstruction() {
if expr.getTarget() instanceof AllocationFunction
then result = getInstruction(OnlyInstructionTag())
else result = getChild(0).getFirstInstruction()
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
kind = gotoEdge() and
expr.getTarget() instanceof AllocationFunction and
if exists(getChild(0))
then result = getChild(0).getFirstInstruction()
else result = getParent().getChildSuccessor(this)
@@ -371,23 +379,34 @@ class TranslatedSideEffects extends TranslatedElement, TTranslatedSideEffects {
override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
tag = OnlyInstructionTag() and
result = getTranslatedExpr(expr).getInstruction(CallTag())
if expr instanceof NewOrNewArrayExpr
then result = getTranslatedAllocatorCall(expr).getInstruction(CallTag())
else result = getTranslatedExpr(expr).getInstruction(CallTag())
}
/**
* Gets the `TranslatedFunction` containing this expression.
*/
final TranslatedFunction getEnclosingFunction() {
result = getTranslatedFunction(expr.getEnclosingFunction())
}
/**
* Gets the `Function` containing this expression.
*/
override Function getFunction() { result = expr.getEnclosingFunction() }
}
class TranslatedStructorCallSideEffects extends TranslatedSideEffects {
class TranslatedCallSideEffects extends TranslatedSideEffects, TTranslatedCallSideEffects {
Call expr;
TranslatedCallSideEffects() { this = TTranslatedCallSideEffects(expr) }
override string toString() { result = "(side effects for " + expr.toString() + ")" }
override Call getExpr() { result = expr }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) { none() }
override Instruction getFirstInstruction() { result = getChild(0).getFirstInstruction() }
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
tag = OnlyInstructionTag() and
result = getTranslatedExpr(expr).getInstruction(CallTag())
}
}
class TranslatedStructorCallSideEffects extends TranslatedCallSideEffects {
TranslatedStructorCallSideEffects() { getParent().(TranslatedStructorCall).hasQualifier() }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType t) {

View File

@@ -442,11 +442,22 @@ newtype TTranslatedElement =
// The declaration/initialization part of a `ConditionDeclExpr`
TTranslatedConditionDecl(ConditionDeclExpr expr) { not ignoreExpr(expr) } or
// The side effects of a `Call`
TTranslatedSideEffects(Call expr) {
exists(TTranslatedArgumentSideEffect(expr, _, _, _)) or
expr instanceof ConstructorCall or
expr.getTarget() instanceof AllocationFunction
} or // A precise side effect of an argument to a `Call`
TTranslatedCallSideEffects(Call expr) {
// Exclude allocations such as `malloc` (which happen to also be function calls).
// Both `TranslatedCallSideEffects` and `TranslatedAllocationSideEffects` generate
// the same side effects for its children as they both extend the `TranslatedSideEffects`
// class.
// Note: We can separate allocation side effects and call side effects into two
// translated elements as no call can be both a `ConstructorCall` and an `AllocationExpr`.
not expr instanceof AllocationExpr and
(
exists(TTranslatedArgumentSideEffect(expr, _, _, _)) or
expr instanceof ConstructorCall
)
} or
// The side effects of an allocation, i.e. `new`, `new[]` or `malloc`
TTranslatedAllocationSideEffects(AllocationExpr expr) or
// A precise side effect of an argument to a `Call`
TTranslatedArgumentSideEffect(Call call, Expr expr, int n, boolean isWrite) {
(
expr = call.getArgument(n).getFullyConverted()

View File

@@ -1649,6 +1649,11 @@ class TranslatedAllocatorCall extends TTranslatedAllocatorCall, TranslatedDirect
final override int getNumberOfArguments() {
result = expr.getAllocatorCall().getNumberOfArguments()
or
// Make sure there's a result even when there is no allocator, as otherwise
// TranslatedCall::getChild() will not return the side effects for this call.
not exists(expr.getAllocatorCall()) and
result = 0
}
final override TranslatedExpr getArgument(int index) {

View File

@@ -0,0 +1,17 @@
private import internal.ValueNumberingImports
private import ValueNumbering
/**
* Provides additional information about value numbering in IR dumps.
*/
class ValueNumberPropertyProvider extends IRPropertyProvider {
override string getInstructionProperty(Instruction instr, string key) {
exists(ValueNumber vn |
vn = valueNumber(instr) and
key = "valnum" and
if strictcount(vn.getAnInstruction()) > 1
then result = vn.getDebugString()
else result = "unique"
)
}
}

View File

@@ -1,21 +1,6 @@
private import internal.ValueNumberingInternal
private import internal.ValueNumberingImports
/**
* Provides additional information about value numbering in IR dumps.
*/
class ValueNumberPropertyProvider extends IRPropertyProvider {
override string getInstructionProperty(Instruction instr, string key) {
exists(ValueNumber vn |
vn = valueNumber(instr) and
key = "valnum" and
if strictcount(vn.getAnInstruction()) > 1
then result = vn.getDebugString()
else result = "unique"
)
}
}
/**
* The value number assigned to a particular set of instructions that produce equivalent results.
*/

View File

@@ -12,4 +12,5 @@ private import implementations.Strcat
private import implementations.Strcpy
private import implementations.Strdup
private import implementations.Strftime
private import implementations.StdString
private import implementations.Swap

View File

@@ -215,6 +215,40 @@ class SizelessAllocationFunction extends AllocationFunction {
}
}
/**
* An `operator new` or `operator new[]` function that may be associated with `new` or
* `new[]` expressions. Note that `new` and `new[]` are not function calls, but these
* functions may also be called directly.
*/
class OperatorNewAllocationFunction extends AllocationFunction {
OperatorNewAllocationFunction() {
exists(string name |
hasGlobalName(name) and
(
// operator new(bytes, ...)
name = "operator new"
or
// operator new[](bytes, ...)
name = "operator new[]"
)
)
}
override int getSizeArg() { result = 0 }
override predicate requiresDealloc() { not exists(getPlacementArgument()) }
/**
* Gets the position of the placement pointer if this is a placement
* `operator new` function.
*/
int getPlacementArgument() {
getNumberOfParameters() = 2 and
getParameter(1).getType() instanceof VoidPointerType and
result = 1
}
}
/**
* An allocation expression that is a function call, such as call to `malloc`.
*/
@@ -227,7 +261,9 @@ class CallAllocationExpr extends AllocationExpr, FunctionCall {
not (
exists(target.getReallocPtrArg()) and
getArgument(target.getSizeArg()).getValue().toInt() = 0
)
) and
// these are modelled directly (and more accurately), avoid duplication
not exists(NewOrNewArrayExpr new | new.getAllocatorCall() = this)
}
override Expr getSizeExpr() { result = getArgument(target.getSizeArg()) }

View File

@@ -79,6 +79,28 @@ class StandardDeallocationFunction extends DeallocationFunction {
override int getFreedArg() { result = freedArg }
}
/**
* An `operator delete` or `operator delete[]` function that may be associated
* with `delete` or `delete[]` expressions. Note that `delete` and `delete[]`
* are not function calls, but these functions may also be called directly.
*/
class OperatorDeleteDeallocationFunction extends DeallocationFunction {
OperatorDeleteDeallocationFunction() {
exists(string name |
hasGlobalName(name) and
(
// operator delete(pointer, ...)
name = "operator delete"
or
// operator delete[](pointer, ...)
name = "operator delete[]"
)
)
}
override int getFreedArg() { result = 0 }
}
/**
* An deallocation expression that is a function call, such as call to `free`.
*/

View File

@@ -0,0 +1,27 @@
import semmle.code.cpp.models.interfaces.Taint
/**
* The `std::basic_string` constructor(s).
*/
class StdStringConstructor extends TaintFunction {
StdStringConstructor() { this.hasQualifiedName("std", "basic_string", "basic_string") }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from any constructor argument to return value
input.isParameter(_) and
output.isReturnValue()
}
}
/**
* The standard function `std::string.c_str`.
*/
class StdStringCStr extends TaintFunction {
StdStringCStr() { this.hasQualifiedName("std", "basic_string", "c_str") }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from string itself (qualifier) to return value
input.isQualifierObject() and
output.isReturnValue()
}
}