mirror of
https://github.com/github/codeql.git
synced 2026-04-25 00:35:20 +02:00
Merge remote-tracking branch 'upstream/master' into DefaultTaintTracking-Configuration
This commit is contained in:
@@ -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)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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() }
|
||||
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()) }
|
||||
|
||||
@@ -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`.
|
||||
*/
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user