Skip to content

C++: Add an experimental query for surprising lifetimes from range-based for loops #15939

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

MathiasVP
Copy link
Contributor

This PR adds an experimental query to detect issues such as:

std::vector<std::vector<int>> CreateCollection();

void use(...);

void test() {
  // BUG: CreateCollection() is destroyed before CreateCollection()[0].begin() is called
  for (auto x : CreateCollection()[0]) {
    use(x);
  }
}

I think the precision of this query is actually perfectly suited for Code Scanning (🤞), but since the query depends on ongoing work on both the extractor side and the analysis side it'll start its lifetime (pun very much intended!) in experimental.

All the NOT DETECTED tests are actually detected when running with the yet-to-be-released version of the extractor and with #15858 merged.

I don't think it makes much sense to run this on DCA yet as that DCA run will mostly test #15858 (and the internal extractor changes) I guess. I'll try doing it anyway just for fun, though!

@MathiasVP MathiasVP requested a review from a team as a code owner March 15, 2024 14:37
@MathiasVP MathiasVP added the no-change-note-required This PR does not need a change note label Mar 15, 2024
@MathiasVP MathiasVP added the ready-for-doc-review This PR requires and is ready for review from the GitHub docs team. label Mar 15, 2024
@MathiasVP MathiasVP force-pushed the experimental-surprising-lifetimes-for-range-based-for-loop branch from 0cf1838 to e23e3d7 Compare March 15, 2024 17:36
@github github deleted a comment from github-actions bot Mar 15, 2024
Copy link
Contributor

QHelp previews:

cpp/ql/src/experimental/Security/CWE/CWE-416/IteratorToExpiredContainer.qhelp

Iterator to expired container

Using an iterator owned by a container after the lifetime of the container has expired can lead to undefined behavior. This is because the iterator may be invalidated when the container is destroyed, and dereferencing an invalidated iterator is undefined behavior. These problems can be hard to spot due to C++'s complex rules for temporary object lifetimes and their extensions.

Recommendation

Never create an iterator to a temporary container when the iterator is expected to be used after the container's lifetime has expired.

Example

The rules for lifetime extension ensures that the code in lifetime_of_temp_extended is well-defined. This is because the lifetime of the temporary container returned by get_vector is extended to the end of the loop. However, prior to C++23, the lifetime extension rules do not ensure that the container returned by get_vector is extended in lifetime_of_temp_not_extended. This is because the temporary container is not bound to a rvalue reference.

#include <vector>

std::vector<int> get_vector();

void use(int);

void lifetime_of_temp_extended() {
  for(auto x : get_vector()) {
    use(x); // GOOD: The lifetime of the vector returned by `get_vector()` is extended until the end of the loop.
  }
}

// Writes the the values of `v` to an external log and returns it unchanged.
const std::vector<int>& log_and_return_argument(const std::vector<int>& v);

void lifetime_of_temp_not_extended() {
  for(auto x : log_and_return_argument(get_vector())) {
    use(x); // BAD: The lifetime of the vector returned by `get_vector()` is not extended, and the behavior is undefined.
  }
}

References

Copy link
Contributor

@geoffw0 geoffw0 left a comment

Choose a reason for hiding this comment

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

This looks like a great query, and the .qhelp is a good explanation of the problem (with references for more detail). 👍

Some questions below.

We also need to do a DCA run, docs review, and a closer examination of real world results ... but for each of these, I don't really mind whether we do it now or when we're ready to promote the query out of experimental. It would certainly help to have the extractor change merged.

@MathiasVP
Copy link
Contributor Author

MathiasVP commented Mar 18, 2024

We also need to do a DCA run, docs review, and a closer examination of real world results ... but for each of these, I don't really mind whether we do it now or when we're ready to promote the query out of experimental. It would certainly help to have the extractor change merged.

Partial answer: See what I wrote above:

I don't think it makes much sense to run this on DCA yet as that DCA run will mostly test #15858 (and the internal extractor changes) I guess. I'll try doing it anyway just for fun, though!

Basically, there will be no real world results before the extractor (and analysis) changes are merged. Even then, we have to wait for MRVA databases to update before we can even run this on MRVA.

MathiasVP and others added 3 commits March 18, 2024 12:01
…Container.ql

Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
…Container.ql

Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
subatoi
subatoi previously approved these changes Mar 18, 2024
Copy link
Contributor

@subatoi subatoi left a comment

Choose a reason for hiding this comment

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

👍 from Docs

@MathiasVP
Copy link
Contributor Author

I believe I've addressed all your comments now @geoffw0. In terms of

We also need to do a DCA run, docs review, and a closer examination of real world results ... but for each of these, I don't really mind whether we do it now or when we're ready to promote the query out of experimental. It would certainly help to have the extractor change merged.

I believe it's best merge this query, and then we can do proper MRVA result investigations and DCA tests once we move the query out of experimental (since, at that point, we'll have both the QL and extractor changes merged, and possibly even MRVA data depending on how lucky we are with the timing of a release 🤞)

Copy link
Contributor

@geoffw0 geoffw0 left a comment

Choose a reason for hiding this comment

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

and 👍 from me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C++ documentation no-change-note-required This PR does not need a change note ready-for-doc-review This PR requires and is ready for review from the GitHub docs team.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants