Skip to content

C++: Add 'unsafe use of this' query#4644

Merged
jbj merged 21 commits into
github:mainfrom
MathiasVP:unsafe-use-of-this-query
Nov 25, 2020
Merged

C++: Add 'unsafe use of this' query#4644
jbj merged 21 commits into
github:mainfrom
MathiasVP:unsafe-use-of-this-query

Conversation

@MathiasVP

@MathiasVP MathiasVP commented Nov 10, 2020

Copy link
Copy Markdown
Contributor

Fixes https://github.com/github/codeql-c-analysis-team/issues/163.

A couple of points are worth making:

  • I've restricted the scope of the query to just be uses of this in C++ constructors (as suggested in the discussion).
  • I've restricted the flow to be 'must' dataflow.

Since this is 'must' flow, I've designed a tiny ad-hoc 'must' dataflow library in the query. I suspect we could move this ad-hoc library out into a library file and generalize it if it turns out to be useful somewhere else.

  • I've specialized the query to only flag calls will cause undefined behavior, and not flag somewhat suspicious uses of calls to pure virtual in constructors that will actually resolve correctly to a function.

For instance, this will not be flagged:

struct Base { virtual void f() = 0; };

struct Derived : public Base {
  Derived() { f(); }

  void f() override {}
};

since the call to f in Derived's constructor will call f. However, the query does flag this:

struct Base { virtual void f() = 0; };

struct Derived : public Base {
  Derived() { call_f(this); }

  void f() override {}
};

void call_f(Base* b) { b->f(); }

since this is undefined behavior (and in practice will crash on the compilers I've tried).

I'm open to discussion on whether or not we want to flag the first example. It should only make the implementation simpler.
We do find some results on LGTM even though we throw away the somewhat benign cases: https://lgtm.com/query/3109442847251804192/.

TODO:

  • Write qhelp.
  • Check whether we need to add any CVE tags.

@MathiasVP MathiasVP added the C++ label Nov 10, 2020
@MathiasVP MathiasVP requested a review from a team as a code owner November 10, 2020 14:06
@MathiasVP MathiasVP force-pushed the unsafe-use-of-this-query branch from 321c3ec to a330cae Compare November 10, 2020 16:25
@jbj jbj self-assigned this Nov 11, 2020
Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql Outdated
Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql
Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql Outdated
Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql Outdated
Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql Outdated
Comment thread change-notes/1.26/analysis-cpp.md Outdated

@geoffw0 geoffw0 left a comment

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.

Couple of comments.

Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.cpp Outdated
Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql Outdated
MathiasVP and others added 3 commits November 11, 2020 18:12
@MathiasVP MathiasVP requested a review from a team as a code owner November 11, 2020 17:30
@github-actions github-actions Bot added the C# label Nov 11, 2020
@MathiasVP MathiasVP force-pushed the unsafe-use-of-this-query branch from b3400c4 to 50ddae4 Compare November 12, 2020 09:13
@MathiasVP MathiasVP force-pushed the unsafe-use-of-this-query branch from 50ddae4 to 50e9051 Compare November 12, 2020 09:27
Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql Outdated
Comment thread cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll Outdated
Comment thread cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll Outdated
Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql Outdated
Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql Outdated
Comment thread cpp/change-notes/2020-11-12-unsafe-use-of-this.md Outdated
MathiasVP and others added 5 commits November 12, 2020 11:28
Co-authored-by: Jonas Jensen <jbj@github.com>
…t-dominance removes some results. Second, that a cast to the pure virtual function's defining class (skipping past a derived class that overrides the function) followed by a call to the function still results in an alert. This is also undefined behavior.
Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql Outdated
Comment thread cpp/ql/test/query-tests/Critical/UnsafeUseOfThis/test.cpp Outdated
Comment thread cpp/ql/test/query-tests/Critical/UnsafeUseOfThis/test.cpp Outdated
Comment thread cpp/ql/test/query-tests/Critical/UnsafeUseOfThis/test.cpp Outdated
- Remove post-dominance requirement. It was really just hiding good
  results.
- Fix test annotations. Turns out Clang and GCC's 'undefined behavior'
  warning didn't align with the C++ standard.
@jbj

jbj commented Nov 13, 2020

Copy link
Copy Markdown
Contributor

The code LGTM now! Next steps include qhelp, CPP-Differences and another round of checking the query on lgtm.com.

@MathiasVP MathiasVP requested a review from hubwriter as a code owner November 16, 2020 10:21
@MathiasVP

Copy link
Copy Markdown
Contributor Author

The code LGTM now! Next steps include qhelp, CPP-Differences and another round of checking the query on lgtm.com.

I've added qhelp in 020af1c. Here's a fresh LGTM run: https://lgtm.com/query/3939119318730344544/. Removing the post-dominance gave quite a lot of new results that I'm still going through.

Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.qhelp Outdated
Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.qhelp Outdated
Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.qhelp Outdated
Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.qhelp Outdated
Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.qhelp Outdated
Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.qhelp Outdated
Comment thread cpp/change-notes/2020-11-12-unsafe-use-of-this.md Outdated
Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.qhelp Outdated
Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.qhelp Outdated
Comment thread cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql Outdated
Co-authored-by: hubwriter <hubwriter@github.com>
@MathiasVP

Copy link
Copy Markdown
Contributor Author

I've added qhelp in 020af1c. Here's a fresh LGTM run: https://lgtm.com/query/3939119318730344544/. Removing the post-dominance gave quite a lot of new results that I'm still going through.

I've been going through the results on LGTM, and it looks like removing post-dominance didn't introduce new false positives, but just added more flow (since the majority of the sinks didn't happen in a post-dominating position). It looks like it's raising a bunch of alerts on examples that follow this pattern:

struct A {
  virtual void f() = 0;
};

struct B : public A {
  void f() override {}
};

void call_f(A* a) { a->f(); }

struct C : public B {
  C() { call_f(this); }
}

(which is in the same spirit as the one marked as FALSE POSITIVE in the new tests).

We can fix this false positive (and all the ones on LGTM) by requiring that there is no override of the pure virtual function being called in any of the base classes of C. I've tested this here: https://lgtm.com/query/1100185598071201617/. This weeds out most results, with the exception of two which looks genuine:

  • One problem in a constructor in wxWidgets/wxWidgets
  • One problem in a destructor in scummvm/scummvm

So I guess it comes down to a choice between

  • Raise more alerts even though they won't trigger undefined behavior, but might not be what the programmer intended.
  • Raise fewer alerts, but only do so when it will definitely trigger undefined behavior.

I think I'm leaning toward the last option. I expect more results will pop up as we add more cases of 'must' flow. How does that sound?

@jbj

jbj commented Nov 19, 2020

Copy link
Copy Markdown
Contributor

I'm on board with the last option too: fewer but better alerts. The two results on LGTM LGTM (argh), and I especially like how clear it is in scummvm on line 51 that they forgot to write _orgStream->. Based on those results, I'd support setting @precision very-high.

…sts in any base class. This removes the false positive in the testcase. Based on the results on LGTM we have agreed to set the @precision to very-high.
@MathiasVP MathiasVP force-pushed the unsafe-use-of-this-query branch from f2e61ea to 072adaa Compare November 19, 2020 11:11
@MathiasVP

MathiasVP commented Nov 19, 2020

Copy link
Copy Markdown
Contributor Author

@jbj

jbj commented Nov 20, 2020

Copy link
Copy Markdown
Contributor

Please merge from main and start a new CPP-Differences so that #4696 is included in both the before-SHA and the after-SHA.

@MathiasVP

Copy link
Copy Markdown
Contributor Author

Please merge from main and start a new CPP-Differences so that #4696 is included in both the before-SHA and the after-SHA.

Done. I've started a fresh CPP-differences with #4696 included: https://jenkins.internal.semmle.com/job/Changes/job/CPP-Differences/1562/

@MathiasVP

MathiasVP commented Nov 21, 2020

Copy link
Copy Markdown
Contributor Author

Done. I've started a fresh CPP-differences with #4696 included: https://jenkins.internal.semmle.com/job/Changes/job/CPP-Differences/1562/

What a sad CPP-difference 👎 It seems to all be from the new query. I will investigate!

time_split_absolute

Edit: It looks like the new query is causing IR re-evaluation.

import cpp
// We don't actually use the global value numbering library in this query, but without it we end up
// recomputing the IR.
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering

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.

If this is true shouldn't semmle.code.cpp.valuenumbering.GlobalValueNumbering be imported in semmle.code.cpp.ir.IR, so that all users benefit?

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.

It was indeed true:
time_split_absolute
As far as I know, this cache re-evaluation problem happens only in unlucky cases. We can maybe this at the team meeting on Thursday? In any case, I don't think we should do that change in this PR.

@MathiasVP

Copy link
Copy Markdown
Contributor Author

648acc3 fixed the IR re-evaluation: https://jenkins.internal.semmle.com/job/Changes/job/CPP-Differences/1567/. Performance looks fine now.

@jbj jbj left a comment

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.

🎉

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants