Skip to content

C++: Use fully converted expressions for cpp/use-after-free and cpp/double-free #14193

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

In tests such as:

void test_ref_delete(int *&p) {
  delete p;
  p = new int;
  use(p); // GOOD [FALSE POSITIVE]
}

we were getting a FP because we didn't block flow at the write to p. The reason dataflow wasn't blocking this write was because we didn't use the result of the reference dereference as the source, but instead we were using the value of type int*& as the source (because asExpr doesn't return ReferenceDereference expressions since they're conversions).

The fix is to actually pick the fully converted expression (i.e., the value of type int*) as the source for dataflow. SSA then correctly sees that the variable is reassigned, and the flow is blocked.

Commit-by-commit review recommended:

  • The first commit changes the sources in cpp/use-after-free and cpp/double-free to use the fully converted expression. This commit accepts one regression caused by asConvertedExpr never returning a ParenthesisExpr.
  • The second commit fixes the above regression. This introduces yet another regression because LeapYear.qll uses asConvertedExpr instead of asExpr. The library really shouldn't deal with conversions since it looks like the rest of the library only handles unconverted expressions
  • The final commit fixes LeapYear.qll by the changing use of asConvertedExpr to asExpr.

@MathiasVP MathiasVP requested a review from a team as a code owner September 12, 2023 18:56
@MathiasVP MathiasVP requested a review from alexet September 12, 2023 18:56
@github-actions github-actions bot added the C++ label Sep 12, 2023
@MathiasVP MathiasVP added the no-change-note-required This PR does not need a change note label Sep 12, 2023
Copy link
Contributor

@alexet alexet left a comment

Choose a reason for hiding this comment

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

LGTM

@@ -1113,6 +1113,13 @@ private module GetConvertedResultExpression {
result = tas.getExtent().getExpr() and
instr = tas.getInstruction(any(AllocationExtentConvertTag tag))
)
or
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason why we don't make this change at the IR level to have the instruction also return ParenthesisExpr rather than add a special case here? The other cases feel more like adjusting to make dataflow easier rather than more correct but this just feels like a missing case for at the IR level.

There's not really any reason to change it here I am just wanting to understand the decision.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think there are two reasons that combine to fully explain this:

  1. Given an instruction i there's always at most one result for instr.getConvertedResultExpression().
  2. Reading https://github.com/github/codeql/blob/main/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll#L3236 it sounds like it's a conscious decision to not generate a CopyValue instruction for parenthesis expressions.

So since instr.getConvertedResultExpression() can only return one expression, and there's no instruction generated for parenthesis expressions, I don't think there's an easy way to fit this change into the IR level.

@MathiasVP MathiasVP merged commit a0018c9 into github:main Sep 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C++ no-change-note-required This PR does not need a change note
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants