-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang] Bounds checking on unclosed parentheses, brackets or braces in Expanded Tokens #69849
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
Tests are failing because of the |
474e43f
to
239302d
Compare
Rewrote the test and now it passes. Sorry for pinging you @HighCommander4, but I don't know who to ping and you participated in that issue. |
@@ -585,6 +585,17 @@ TEST_F(TokenCollectorTest, DelayedParsing) { | |||
EXPECT_THAT(collectAndDump(Code), StartsWith(ExpectedTokens)); | |||
} | |||
|
|||
TEST_F(TokenCollectorTest, UnclosedToken) { |
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.
I started looking at this to try and make some progress towards getting this landed. However, when running this test locally, I'm not seeing either of the branches added to spelledForExpandedToken()
being taken.
Am I missing something, or is this test not exercising the intended codepath?
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.
Indeed, it looks like TokenBuffer::spelledForExpanded()
(which is the only call site of spelledForExpandedToken()
) is not called by anything currently in this test.
To exercise spelledForExpanded()
, we will need to make an explicit call to it, the way a number of other tests in this file do.
@HighCommander4, thank you for reviewing this PR! Unfortunately, I’m currently in my finals and will only have time to look at this next week. So, I’ll update this later. |
I spent a bit more time looking at this. I'd say I'm still quite far from having a complete understanding of this code, but two things occur to me:
|
I poked at this a bit more. A few more notes:
I haven't dug into the implementation of |
Anyways, in a case like this, the behaviour I'd like to see after the fix would be for |
I second everything that @HighCommander4 said. It would be really useful to add an assertion that we never get out-of-bounds here, but this indicates a logic error somewhere in the code that should be fixed. I am slightly suspicious of source locations pointing at Asserting that |
I think in this case it's deliberate. If you look at the compiler error for the missing brace: test.cpp:1:13: error: expected '}'
1 | int main() {
| ^
test.cpp:1:12: note: to match this '{'
1 | int main() {
| ^ you can see that the diagnostic location points to one character past the opening brace, which is the
What do you think about this as an alternative: if This would have the advantage of gracefully handling AST nodes like this one whose end location is the |
I wrote this up at #78092 |
When getting the AST from clangd, if there is an unclosed token, a segfault or an UB can happen when accessing
File.SpelledTokens
because the supposed closing token is not present, so its index is greater than the vec's size.This fixes the issue by returning a
nullptr
on the function that caused the UB and then checking if the spelled token is null, returningnullopt
for the whole expanded token.Fixes clangd/clangd#1559.