-
Notifications
You must be signed in to change notification settings - Fork 11.2k
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
[clang] fix sema init crashing on initialization sequences #98102
Conversation
@llvm/pr-subscribers-clang Author: Yuxuan Chen (yuxuanchen1997) ChangesWe ran into a FE crash and root caused to We have been using automated reduction tools (like CReduce) for a while and it is not performing well and would like to ask upstream opinions on whether this condition here is handled correctly. Preferably with help to write a small, well contained crash-on-valid test case. I do have a crash-on-invalid test here, would really appreciate any pointers. Full diff: https://github.com/llvm/llvm-project/pull/98102.diff 1 Files Affected:
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 41753a1661ace..80286302e9b9d 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -5576,6 +5576,10 @@ static void TryOrBuildParenListInitialization(
ExprResult ER;
ER = IS.Perform(S, SubEntity, SubKind,
Arg ? MultiExprArg(Arg) : std::nullopt);
+
+ if (ER.IsInvalid())
+ return false;
+
if (InitExpr)
*InitExpr = ER.get();
else
|
|
||
if (ER.IsInvalid()) | ||
return false; | ||
|
||
if (InitExpr) | ||
*InitExpr = ER.get(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ER.get() is null if we don't apply this fix.
82e3cb0
to
01a5dd6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
You should also add test coverage (clang/test/SemaCXX) for the changes and a release note (clang/docs/ReleaseNotes.rst).
@@ -5576,6 +5576,10 @@ static void TryOrBuildParenListInitialization( | |||
ExprResult ER; | |||
ER = IS.Perform(S, SubEntity, SubKind, | |||
Arg ? MultiExprArg(Arg) : std::nullopt); | |||
|
|||
if (ER.isInvalid()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Under what circumstances does IS.Failed()
return false
above but when we perform the initialization we get a null expression back? That seems strange to me -- I would have naively expected Failed()
to return true
in such a case. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you look at InitializationSequence::Perform
(this function is 1000 lines long), it first checks Failed()
then proceed to build a whole bunch of things. There are a couple of places it returned ExprError
. I think it's possible to still be invalid after !Failed()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah you are correct, sorry! I see now that the common code pattern is to check isInvalid()
on the returned result.
@Endilll you are able to reduce that further? |
@AaronBallman -- are you OK with a crash-on-invalid (the one in first post)? The original example we had crashed on valid code, but reducing a 35MB file with a lot of SFINAE is taking weeks with c-reduce. |
Ideally we'd have test coverage for both the crash-on-invalid and crash-on-valid code, if possible. If we can't get a reduction to a crash-on-valid case, then crash-on-invalid that also fixes the valid case would be okay. But we could perhaps help reduce the crash-on-valid code if you can share it. |
Thank you Aaron. Unfortunately this is from some Meta internal codebase, so it's hard to share. I'm trying to reduce myself. |
@AaronBallman I have good news. I was able to manually write a well-formed C++ file that crashes. https://gist.github.com/yuxuanchen1997/576dce964666f0f8713fccacf5847138 And I am able to validate that the fix I proposed here does fix the problem. I am going to add this test to the patch and figure out why we were crashing in the first place. |
f12bfc7
to
3c5b72d
Compare
I don't see the original reproducer anywhere. Snippet in the description is already reduced (and got quite damaged in the process). I can reduce it myself if someone points me out to the original reproducer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes LGTM, but please add a release note to clang/docs/ReleaseNotes.rst so users know about the fix.
@@ -5576,6 +5576,10 @@ static void TryOrBuildParenListInitialization( | |||
ExprResult ER; | |||
ER = IS.Perform(S, SubEntity, SubKind, | |||
Arg ? MultiExprArg(Arg) : std::nullopt); | |||
|
|||
if (ER.isInvalid()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah you are correct, sorry! I see now that the common code pattern is to check isInvalid()
on the returned result.
3c5b72d
to
4c2b881
Compare
Added. Thanks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thank you for the fix!
We ran into a FE crash and root caused to `ER.get()` on line 5584 here being nullptr. I think this is a result of not checking if ER here is invalid. Example of crash-on-valid C++ https://gist.github.com/yuxuanchen1997/576dce964666f0f8713fccacf5847138 Note that this crash happens only with `-std=c++20`.
We ran into a FE crash and root caused to
ER.get()
on line 5584 here being nullptr. I think this is a result of not checking if ER here is invalid.Example of crash-on-valid C++ https://gist.github.com/yuxuanchen1997/576dce964666f0f8713fccacf5847138
Note that this crash happens only with
-std=c++20
.