Files
codeql/cpp/ql/test/library-tests/dataflow/fields/qualifiers.cpp
Jonas Jensen 1b1095ee75 C++: Post-update flow through &, *, +, ...
Flow from a definition by reference of a field into its object was
working inconsistently and in a very syntax-dependent way. For a
function `f` receiving a reference, `f(a->x)` could propagate data back
to `a` via the _reverse read_ mechanism in the shared data-flow library,
but for a function `g` receiving a pointer, `g(&a->x)` would not work.
And `f((*a).x)` would not work either.

In all cases, the issue was that the shared data-flow library propagates
data backwards between `PostUpdateNode`s only, but there is no
`PostUpdateNode` for `a->x` in `g(&a->x)`. This pull request inserts
such post-update nodes where appropriate and links them to their
neighbors. In this exapmle, flow back from the output parameter of `g`
passes first to the `PostUpdateNode` of `&`, then to the (new)
`PostUpdateNode` of `a->x`, and finally, as a _reverse read_ with the
appropriate field projection, to `a`.
2020-05-01 15:40:19 +02:00

50 lines
1.2 KiB
C++

void sink(void *o);
void *user_input(void);
namespace qualifiers {
struct Inner {
void *a;
void setA(void *value) { this->a = value; }
};
void pointerSetA(Inner *inner, void *value) { inner->a = value; }
void referenceSetA(Inner &inner, void *value) { inner.a = value; }
struct Outer {
Inner *inner;
Inner *getInner() { return inner; }
};
void assignToGetter(Outer outer) {
outer.getInner()->a = user_input();
sink(outer.inner->a); // flow [NOT DETECTED by IR]
}
void getterArgument1(Outer outer) {
outer.getInner()->setA(user_input());
sink(outer.inner->a); // flow [NOT DETECTED by IR]
}
void getterArgument2(Outer outer) {
pointerSetA(outer.getInner(), user_input());
sink(outer.inner->a); // flow [NOT DETECTED by IR]
}
void getterArgument2Ref(Outer outer) {
referenceSetA(*outer.getInner(), user_input());
sink(outer.inner->a); // flow [NOT DETECTED by IR]
}
void assignToGetterStar(Outer outer) {
(*outer.getInner()).a = user_input();
sink(outer.inner->a); // flow [NOT DETECTED by IR]
}
void assignToGetterAmp(Outer outer) {
(&outer)->getInner()->a = user_input();
sink(outer.inner->a); // flow [NOT DETECTED by IR]
}
}