Skip to content

CPP: Fix FPs for 'Resource not released in destructor' involving virtual method calls #562

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

Merged
merged 4 commits into from
Dec 3, 2018

Conversation

geoffw0
Copy link
Contributor

@geoffw0 geoffw0 commented Nov 28, 2018

Fixes https://jira.semmle.com/browse/CPP-308. The fix is to account for calls to virtual methods releasing memory via overriding function definitions in derived classes.

@jbj I'm tempted to move the fix into Function.qll with the addition of a function:

  Function getAPossibleTarget() {
    result = getTarget() or
    (
      result = getTarget().(MemberFunction).getAnOverridingFunction*() and
      exists(getQualifier()) // exclude overrides when the target is fixed
    )
  }

This comes very close to your ideas about a virtual dispatch library, however my solution appears rather trivial (and I'm not completely sure about the last line). How much complexity do you think there would need to be in such a library? What can we do better than the above?

@geoffw0 geoffw0 added the C++ label Nov 28, 2018
@geoffw0 geoffw0 requested a review from a team as a code owner November 28, 2018 14:25
@jbj
Copy link
Contributor

jbj commented Nov 29, 2018

Without a proper virtual-dispatch library you'll get false negatives in the test if you define a class MyClass5b : MyClass4 that overrides Release to do nothing. When you then release a MyClass5b that has static type MyClass4, it'll appear to be correctly deleted because a correct delete exists in a subclass of MyClass4.

I can probably be persuaded to merge a stub virtual-dispatch library since it'll be better than having nothing at all. I'm wary of adding it to Function.qll, though. I find that all heuristic analysis we've added to the basic AST classes so far has become out of date quickly and is hard to change without breaking existing code that relies on the bad behaviour. Earlier this year I improved Call.passesByReference, and it took a lot of iterations to fix all the code that was relying on its old broken behaviour. C# has a getARuntimeTarget predicate on Call, but Java requires you to explicitly call the virtual-dispatch library, and I think we should follow Java.

Copy link
Contributor

@jbj jbj left a comment

Choose a reason for hiding this comment

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

How is performance?

e.(FunctionCall).getTarget() = f and
(
e.(FunctionCall).getTarget() = f or
e.(FunctionCall).getTarget().(MemberFunction).getAnOverridingFunction*() = f
Copy link
Contributor

Choose a reason for hiding this comment

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

These two * can be +, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. Done.

@geoffw0
Copy link
Contributor Author

geoffw0 commented Dec 3, 2018

When you then release a MyClass5b that has static type MyClass4, it'll appear to be correctly deleted because a correct delete exists in a subclass of MyClass4.

I've added some test cases that verify this behaviour.

I can probably be persuaded to merge a stub virtual-dispatch library
...
I'm wary of adding it to Function.qll, though

OK, let's do a proper library at a later date then.

How is performance?

Not too bad:

qt before: 137s, 233 results
qt after: 153s, 228 results
wireshark before: 203s, 445 results
wireshark after: 192s, 445 results

Note that leakedInSameMethod is quite slow:

	AV Rule 79.ql-3:AV Rule 79::leakedInSameMethod#ff ............................... 1m21s

due to the a.getEnclosingFunction() = b.getEnclosingFunction() pattern. This is just because I don't yet have #580.

@jbj jbj merged commit b80cf30 into github:master Dec 3, 2018
geoffw0 added a commit to geoffw0/ql that referenced this pull request Dec 10, 2018
cklin pushed a commit that referenced this pull request May 23, 2022
Remove accidentally added binary
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.

2 participants