-
Notifications
You must be signed in to change notification settings - Fork 1.9k
C++: Fix missing results for Node.asDefinition
#21212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Fixes DataFlow::Node.asDefinition so it returns a result (marked uncertain = true) even when the underlying StoreInstruction has no corresponding SSA definition, preventing “missing result” cases.
Changes:
- Adjusted
Node.asDefinition/1implementation to avoid depending onSsaImpl::defToNodefor producing any result. - Added a new InlineExpectations-based regression test for
asDefinitionover different store forms (including a field store / dead variable store).
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll | Updates asDefinition uncertainty determination so stores without SSA still yield a result. |
| cpp/ql/test/library-tests/dataflow/asDefinition/test.ql | Adds an InlineExpectations test query for Node.asDefinition. |
| cpp/ql/test/library-tests/dataflow/asDefinition/test.cpp | Adds C++ test cases exercising assignments/initializers including a field store. |
| cpp/ql/test/library-tests/dataflow/asDefinition/test.expected | Empty InlineExpectations expected-output file for the new test. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Could you explain why |
It's basically the sound choice. Notice this part of the QLDoc (emphasis mine) from this predicate:
In order words, the |
|
Thanks. In the case you're handling here there are effectively no paths, if I understand correctly, so wouldn't |
|
We're handling that we couldn't conclude whether we know about all the paths. Consider something like this (which is outside the scope of the C/C++ SSA since we don't have field-based SSA): void foo(int**);
struct S {
int* p;
};
S s;
foo(&s.p);
*s.p = 42;When we reach S s;
foo(&s.p);
*s.p = source();
... // (1)
*s.p = 42;
... // (2)
sink(*s.p);On main we don't have a result for When |
|
Thanks for the explanation. That makes sense. |
jketema
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM if DCA is happy.
|
DCA was uneventful 🎉 |
For a dataflow node
none can ask ifnis the node corresponding to aStoreInstruction. This is useful when one wants to deal uniformly with all kinds of assignments/initializers/increments/decrements/etc.The predicate also tells you whether an assignment overwrites an entire buffer or whether it may be a partial write (i.e.,
node.asDefinition(true)means the write may not overwrite the entire buffer). In order to do that it uses some of the SSA predicates (in particular,SsaImpl::defToNode) to find the correspondingSsa::Definitionbelonging to theStoreInstruction.However, if there's no corresponding SSA information for the
StoreInstruction(for instance, if it's a store to a field or to a variable that is not live) thenSsaImpl::defToNodewon't hold. And so the entirenode.asDefinitionpredicate did not have a result.This PR fixes this so that, instead of the predicate not having a result, it will have a result with
uncertain = true. This means thatnode.asDefinitioncan now be used to grab all assignments/initializers/increments/decrements/etc regardless of whether we have SSA information for it.cc @bdrodes