Skip to content

C++: Rudimentary support for IR data flow virtual dispatch#2262

Merged
rdmarsh2 merged 3 commits intogithub:masterfrom
jbj:ir-virtual-dispatch-local
Nov 7, 2019
Merged

C++: Rudimentary support for IR data flow virtual dispatch#2262
rdmarsh2 merged 3 commits intogithub:masterfrom
jbj:ir-virtual-dispatch-local

Conversation

@jbj
Copy link
Copy Markdown
Contributor

@jbj jbj commented Nov 6, 2019

This virtual dispatch support is not up to par with the one in security.TaintTracking, but it's enough to handle the two examples of virtual dispatch we have in our qltests: UncontrolledProcessOperation/test.cpp in this repo and UncontrolledProcessOperation/test.cpp in the internal repo.

jbj added 3 commits November 6, 2019 14:04
This is just good enough to cause no performance regressions and pass
the virtual-dispatch tests we have for `security.TaintTracking`. In
particular, it fixes the tests for `UncontrolledProcessOperation.ql`
when enabling `DefaultTaintTracking.qll`.
This makes IR data flow behave more like AST data flow, and it makes IR
virtual dispatch work without further changes.
This bit is only used by the compatibility code that sends flow into
parameters of functions without body.
@jbj jbj added the C++ label Nov 6, 2019
@jbj jbj requested a review from a team as a code owner November 6, 2019 13:11
* as a chain of `ConvertToBaseInstruction`s and will cause the search to start
* from each of them and pass through subsequent ones. There might be
* performance to gain by stopping before a second upcast and reconstructing
* the full chain in a "big-step" recursion after this one.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't there also a precision improvement to be made there, if there's a cast through more than one class that overrides the same virtual function?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

Copy link
Copy Markdown
Contributor

@rdmarsh2 rdmarsh2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@rdmarsh2 rdmarsh2 merged commit c5396d9 into github:master Nov 7, 2019
* the full chain in a "big-step" recursion after this one.
*/
private predicate nodeMayHaveClass(Class derived, DataFlow::Node node) {
exists(ConvertToBaseInstruction toBase |
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably also consider ConvertToVirtualBaseInstruction. Perhaps we need a common base class for that and ConvertToBaseInstruction.

* performance to gain by stopping before a second upcast and reconstructing
* the full chain in a "big-step" recursion after this one.
*/
private predicate nodeMayHaveClass(Class derived, DataFlow::Node node) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given a function declared void foo(Base* p) { p->vfunc(); }, will this consider that p->vfunc() could be any override of Base::vfunc()? Or do we only think that it could call Derived::vfunc() if we see a derived-to-base cast from Derived*?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The latter. To make this interprocedural will be follow-up work. I don't think we should make it overapproximating to begin with since the goal for now is just to replace security.TaintTracking.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants