mirror of
https://github.com/github/codeql.git
synced 2026-04-29 10:45:15 +02:00
C++: Explicitly model data flow in through reference return values.
This commit is contained in:
@@ -83,16 +83,16 @@ predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeT
|
||||
or
|
||||
exprToPartialDefinitionStep(nodeFrom.asExpr(), nodeTo.asPartialDefinition())
|
||||
or
|
||||
// Reverse taint: if a function model has taint from the qualifier to the
|
||||
// dereferenced return value, also apply reverse taint from the post-update
|
||||
// of the return value back to the qualifier. This allows taint to flow 'in'
|
||||
// through references returned by a modeled function such as `operator[]`.
|
||||
// Reverse taint: taint that flows from the post-update node of a reference
|
||||
// returned by a function call, back into the qualifier of that function.
|
||||
// This allows taint to flow 'in' through references returned by a modeled
|
||||
// function such as `operator[]`.
|
||||
exists(
|
||||
TaintFunction f, Call call, FunctionInput inModel, FunctionOutput outModel
|
||||
|
|
||||
call.getTarget() = f and
|
||||
inModel.isQualifierObject() and
|
||||
outModel.isReturnValueDeref() and
|
||||
inModel.isReturnValueDeref() and
|
||||
outModel.isQualifierObject() and
|
||||
f.hasTaintFlow(inModel, outModel) and
|
||||
nodeFrom.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = call and
|
||||
nodeTo.asDefiningArgument() = call.getQualifier()
|
||||
|
||||
@@ -100,5 +100,9 @@ class StdSequenceContainerAt extends TaintFunction {
|
||||
// flow from qualifier to referenced return value
|
||||
input.isQualifierObject() and
|
||||
output.isReturnValueDeref()
|
||||
or
|
||||
// reverse flow from returned reference to the qualifier
|
||||
input.isReturnValueDeref() and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,5 +154,9 @@ class StdStringAt extends TaintFunction {
|
||||
// flow from qualifier to referenced return value
|
||||
input.isQualifierObject() and
|
||||
output.isReturnValueDeref()
|
||||
or
|
||||
// reverse flow from returned reference to the qualifier
|
||||
input.isReturnValueDeref() and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,8 @@ private newtype TFunctionInput =
|
||||
TInParameter(ParameterIndex i) or
|
||||
TInParameterDeref(ParameterIndex i) or
|
||||
TInQualifierObject() or
|
||||
TInQualifierAddress()
|
||||
TInQualifierAddress() or
|
||||
TInReturnValueDeref()
|
||||
|
||||
/**
|
||||
* An input to a function. This can be:
|
||||
@@ -106,6 +107,31 @@ class FunctionInput extends TFunctionInput {
|
||||
* (with type `C const *`) on entry to the function.
|
||||
*/
|
||||
predicate isQualifierAddress() { none() }
|
||||
|
||||
/**
|
||||
* Holds if this is the input value pointed to by the return value of a
|
||||
* function, if the function returns a pointer, or the input value referred
|
||||
* to by the return value of a function, if the function returns a reference.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
* char* getPointer();
|
||||
* float& getReference();
|
||||
* int getInt();
|
||||
* ```
|
||||
* - `isReturnValueDeref()` holds for the `FunctionInput` that represents the
|
||||
* value of `*getPointer()` (with type `char`).
|
||||
* - `isReturnValueDeref()` holds for the `FunctionInput` that represents the
|
||||
* value of `getReference()` (with type `float`).
|
||||
* - There is no `FunctionInput` of `getInt()` for which
|
||||
* `isReturnValueDeref()` holds because the return type of `getInt()` is
|
||||
* neither a pointer nor a reference.
|
||||
*
|
||||
* Note that data flows in through function return values are relatively
|
||||
* rare, but they do occur when a function returns a reference to itself,
|
||||
* part of itself, or one of its other inputs.
|
||||
*/
|
||||
predicate isReturnValueDeref() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,6 +225,34 @@ class InQualifierAddress extends FunctionInput, TInQualifierAddress {
|
||||
override predicate isQualifierAddress() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The input value pointed to by the return value of a function, if the
|
||||
* function returns a pointer, or the input value referred to by the return
|
||||
* value of a function, if the function returns a reference.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
* char* getPointer();
|
||||
* float& getReference();
|
||||
* int getInt();
|
||||
* ```
|
||||
* - `InReturnValueDeref` represents the value of `*getPointer()` (with type
|
||||
* `char`).
|
||||
* - `InReturnValueDeref` represents the value of `getReference()` (with type
|
||||
* `float`).
|
||||
* - `InReturnValueDeref` does not represent the return value of `getInt()`
|
||||
* because the return type of `getInt()` is neither a pointer nor a reference.
|
||||
*
|
||||
* Note that data flows in through function return values are relatively
|
||||
* rare, but they do occur when a function returns a reference to itself,
|
||||
* part of itself, or one of its other inputs.
|
||||
*/
|
||||
class InReturnValueDeref extends FunctionInput, TInReturnValueDeref {
|
||||
override string toString() { result = "InReturnValueDeref" }
|
||||
|
||||
override predicate isReturnValueDeref() { any() }
|
||||
}
|
||||
|
||||
private newtype TFunctionOutput =
|
||||
TOutParameterDeref(ParameterIndex i) or
|
||||
TOutQualifierObject() or
|
||||
|
||||
Reference in New Issue
Block a user