mirror of
https://github.com/github/codeql.git
synced 2026-04-29 18:55:14 +02:00
Merge pull request #5035 from MathiasVP/implied-deref-flow
C++: Implied dataflow models
This commit is contained in:
@@ -920,6 +920,27 @@ private predicate modelFlow(Operand opFrom, Instruction iTo) {
|
||||
)
|
||||
)
|
||||
)
|
||||
or
|
||||
impliedModelFlow(opFrom, iTo)
|
||||
}
|
||||
|
||||
/**
|
||||
* When a `DataFlowFunction` specifies dataflow from a parameter `p` to the return value there should
|
||||
* also be dataflow from the parameter dereference (i.e., `*p`) to the return value dereference.
|
||||
*/
|
||||
private predicate impliedModelFlow(Operand opFrom, Instruction iTo) {
|
||||
exists(
|
||||
CallInstruction call, DataFlowFunction func, FunctionInput modelIn, FunctionOutput modelOut,
|
||||
int index
|
||||
|
|
||||
call.getStaticCallTarget() = func and
|
||||
func.hasDataFlow(modelIn, modelOut)
|
||||
|
|
||||
modelIn.isParameterOrQualifierAddress(index) and
|
||||
modelOut.isReturnValue() and
|
||||
opFrom = getSideEffectFor(call, index).(ReadSideEffectInstruction).getSideEffectOperand() and
|
||||
iTo = call // TODO: Add write side effects for return values
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -108,6 +108,16 @@ class FunctionInput extends TFunctionInput {
|
||||
*/
|
||||
predicate isQualifierAddress() { none() }
|
||||
|
||||
/**
|
||||
* Holds if `i >= 0` and `isParameter(i)` holds for this value, or
|
||||
* if `i = -1` and `isQualifierAddress()` holds for this value.
|
||||
*/
|
||||
final predicate isParameterOrQualifierAddress(ParameterIndex i) {
|
||||
i >= 0 and this.isParameter(i)
|
||||
or
|
||||
i = -1 and this.isQualifierAddress()
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -134,7 +144,7 @@ class FunctionInput extends TFunctionInput {
|
||||
predicate isReturnValueDeref() { none() }
|
||||
|
||||
/**
|
||||
* Holds if `i >= 0` and `isParameterDeref(i)` holds for this is value, or
|
||||
* Holds if `i >= 0` and `isParameterDeref(i)` holds for this value, or
|
||||
* if `i = -1` and `isQualifierObject()` holds for this value.
|
||||
*/
|
||||
final predicate isParameterDerefOrQualifierObject(ParameterIndex i) {
|
||||
|
||||
@@ -38,13 +38,13 @@ public:
|
||||
|
||||
void test_typedefs(int_iterator_by_typedefs source1) {
|
||||
sink(*source1); // $ ast,ir
|
||||
sink(*(source1++)); // $ ast MISSING: ir
|
||||
sink(*(source1++)); // $ ast,ir
|
||||
sink(*(++source1)); // $ ast MISSING: ir
|
||||
}
|
||||
|
||||
void test_trait(int_iterator_by_trait source1) {
|
||||
sink(*source1); // $ ast,ir
|
||||
sink(*(source1++)); // $ ast MISSING: ir
|
||||
sink(*(source1++)); // $ ast,ir
|
||||
sink(*(++source1)); // $ ast MISSING: ir
|
||||
}
|
||||
|
||||
|
||||
@@ -415,10 +415,10 @@ void test_string_iterators() {
|
||||
sink(*i9); // $ ast,ir
|
||||
|
||||
i10 = i2;
|
||||
sink(*(i10++)); // $ ast MISSING: ir
|
||||
sink(*(i10++)); // $ ast,ir
|
||||
sink(i10); // $ ast,ir
|
||||
i11 = i2;
|
||||
sink(*(i11--)); // $ ast MISSING: ir
|
||||
sink(*(i11--)); // $ ast,ir
|
||||
sink(i11); // $ ast,ir
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ void test_stringstream_int(int source)
|
||||
sink(ss1 << 1234);
|
||||
sink(ss2 << source); // $ ast MISSING: ir
|
||||
sink(ss1 >> v1);
|
||||
sink(ss2 >> v2); // $ ast MISSING: ir
|
||||
sink(ss2 >> v2); // $ ast,ir
|
||||
|
||||
sink(ss1);
|
||||
sink(ss2); // $ ast,ir
|
||||
@@ -143,27 +143,27 @@ void test_stringstream_in()
|
||||
sink(ss2 << source()); // $ ast,ir
|
||||
|
||||
sink(ss1 >> s1);
|
||||
sink(ss2 >> s2); // $ ast MISSING: ir
|
||||
sink(ss2 >> s3 >> s4); // $ ast MISSING: ir
|
||||
sink(ss2 >> s2); // $ ast,ir
|
||||
sink(ss2 >> s3 >> s4); // $ ast,ir
|
||||
sink(s1);
|
||||
sink(s2); // $ ast,ir
|
||||
sink(s3); // $ ast,ir
|
||||
sink(s4); // $ ast MISSING: ir
|
||||
sink(s4); // $ ast,ir
|
||||
|
||||
sink(ss1 >> b1);
|
||||
sink(ss2 >> b2); // $ ast MISSING: ir
|
||||
sink(ss2 >> b3 >> b4); // $ ast MISSING: ir
|
||||
sink(ss2 >> b2); // $ ast,ir
|
||||
sink(ss2 >> b3 >> b4); // $ ast,ir
|
||||
sink(b1);
|
||||
sink(b2); // $ ast,ir
|
||||
sink(b3); // $ ast,ir
|
||||
sink(b4); // $ ast MISSING: ir
|
||||
sink(b4); // $ ast,ir
|
||||
|
||||
sink(ss1.read(b5, 100));
|
||||
sink(ss2.read(b6, 100)); // $ ast MISSING: ir
|
||||
sink(ss2.read(b6, 100)); // $ ast,ir
|
||||
sink(ss1.readsome(b7, 100));
|
||||
sink(ss2.readsome(b8, 100)); // (returns a length, not significantly tainted)
|
||||
sink(ss1.get(b9, 100));
|
||||
sink(ss2.get(b10, 100)); // $ ast MISSING: ir
|
||||
sink(ss2.get(b10, 100)); // $ ast,ir
|
||||
sink(b5);
|
||||
sink(b6); // $ ast,ir
|
||||
sink(b7);
|
||||
@@ -176,7 +176,7 @@ void test_stringstream_in()
|
||||
sink(c3 = ss1.peek());
|
||||
sink(c4 = ss2.peek()); // $ ast,ir
|
||||
sink(ss1.get(c5));
|
||||
sink(ss2.get(c6)); // $ ast MISSING: ir
|
||||
sink(ss2.get(c6)); // $ ast,ir
|
||||
sink(c1);
|
||||
sink(c2); // $ ast,ir
|
||||
sink(c3);
|
||||
@@ -212,44 +212,44 @@ void test_getline()
|
||||
std::string s1, s2, s3, s4, s5, s6, s7, s8;
|
||||
|
||||
sink(ss1.getline(b1, 1000));
|
||||
sink(ss2.getline(b2, 1000)); // $ ast MISSING: ir
|
||||
sink(ss2.getline(b3, 1000)); // $ ast MISSING: ir
|
||||
sink(ss2.getline(b2, 1000)); // $ ast,ir
|
||||
sink(ss2.getline(b3, 1000)); // $ ast,ir
|
||||
sink(ss1.getline(b3, 1000));
|
||||
sink(b1);
|
||||
sink(b2); // $ ast,ir
|
||||
sink(b3); // $ SPURIOUS: ast,ir
|
||||
|
||||
sink(ss1.getline(b4, 1000, ' '));
|
||||
sink(ss2.getline(b5, 1000, ' ')); // $ ast MISSING: ir
|
||||
sink(ss2.getline(b6, 1000, ' ')); // $ ast MISSING: ir
|
||||
sink(ss2.getline(b5, 1000, ' ')); // $ ast,ir
|
||||
sink(ss2.getline(b6, 1000, ' ')); // $ ast,ir
|
||||
sink(ss1.getline(b6, 1000, ' '));
|
||||
sink(b4);
|
||||
sink(b5); // $ ast,ir
|
||||
sink(b6); // $ SPURIOUS: ast,ir
|
||||
|
||||
sink(ss2.getline(b7, 1000).getline(b8, 1000)); // $ ast MISSING: ir
|
||||
sink(ss2.getline(b7, 1000).getline(b8, 1000)); // $ ast,ir
|
||||
sink(b7); // $ ast,ir
|
||||
sink(b8); // $ ast MISSING: ir
|
||||
|
||||
sink(getline(ss1, s1));
|
||||
sink(getline(ss2, s2)); // $ ast MISSING: ir
|
||||
sink(getline(ss2, s3)); // $ ast MISSING: ir
|
||||
sink(getline(ss2, s2)); // $ ast,ir
|
||||
sink(getline(ss2, s3)); // $ ast,ir
|
||||
sink(getline(ss1, s3));
|
||||
sink(s1);
|
||||
sink(s2); // $ ast,ir
|
||||
sink(s3); // $ SPURIOUS: ast,ir
|
||||
|
||||
sink(getline(ss1, s4, ' '));
|
||||
sink(getline(ss2, s5, ' ')); // $ ast MISSING: ir
|
||||
sink(getline(ss2, s6, ' ')); // $ ast MISSING: ir
|
||||
sink(getline(ss2, s5, ' ')); // $ ast,ir
|
||||
sink(getline(ss2, s6, ' ')); // $ ast,ir
|
||||
sink(getline(ss1, s6, ' '));
|
||||
sink(s4);
|
||||
sink(s5); // $ ast,ir
|
||||
sink(s6); // $ SPURIOUS: ast,ir
|
||||
|
||||
sink(getline(getline(ss2, s7), s8)); // $ ast MISSING: ir
|
||||
sink(getline(getline(ss2, s7), s8)); // $ ast,ir
|
||||
sink(s7); // $ ast,ir
|
||||
sink(s8); // $ ast MISSING: ir
|
||||
sink(s8); // $ ast,ir
|
||||
}
|
||||
|
||||
void test_chaining()
|
||||
@@ -259,7 +259,7 @@ void test_chaining()
|
||||
char b1[1000] = {0};
|
||||
char b2[1000] = {0};
|
||||
|
||||
sink(ss1.get(b1, 100).unget().get(b2, 100)); // $ ast MISSING: ir
|
||||
sink(ss1.get(b1, 100).unget().get(b2, 100)); // $ ast,ir
|
||||
sink(b1); // $ ast,ir
|
||||
sink(b2); // $ ast MISSING: ir
|
||||
|
||||
|
||||
Reference in New Issue
Block a user