Skip to content

Commit 71ad307

Browse files
authored
[Clang] prevent crash on unterminated __has_embed (#163107)
Fixes #162953 --- This PR addresses the issue of Clang crashing on unterminated `__has_embed` by guarding all `DiscardUntilEndOfDirective` paths with the contextual end token and diagnosing the missing `)` before reporting _unknown_ parameters.
1 parent 0ded75c commit 71ad307

File tree

4 files changed

+41
-10
lines changed

4 files changed

+41
-10
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ Bug Fixes in This Version
413413
(#GH159080)
414414
- Fixed a failed assertion with empty filename arguments in ``__has_embed``. (#GH159898)
415415
- Fixed a failed assertion with empty filename in ``#embed`` directive. (#GH162951)
416+
- Fixed a crash triggered by unterminated ``__has_embed``. (#GH162953)
416417

417418
Bug Fixes to Compiler Builtins
418419
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Lex/PPDirectives.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3665,14 +3665,14 @@ Preprocessor::LexEmbedParameters(Token &CurTok, bool ForHasEmbed) {
36653665
std::pair<tok::TokenKind, SourceLocation> Matches) {
36663666
Diag(CurTok, diag::err_expected) << Expected;
36673667
Diag(Matches.second, diag::note_matching) << Matches.first;
3668-
if (CurTok.isNot(tok::eod))
3668+
if (CurTok.isNot(EndTokenKind))
36693669
DiscardUntilEndOfDirective(CurTok);
36703670
};
36713671

36723672
auto ExpectOrDiagAndSkipToEOD = [&](tok::TokenKind Kind) {
36733673
if (CurTok.isNot(Kind)) {
36743674
Diag(CurTok, diag::err_expected) << Kind;
3675-
if (CurTok.isNot(tok::eod))
3675+
if (CurTok.isNot(EndTokenKind))
36763676
DiscardUntilEndOfDirective(CurTok);
36773677
return false;
36783678
}
@@ -3763,7 +3763,7 @@ Preprocessor::LexEmbedParameters(Token &CurTok, bool ForHasEmbed) {
37633763
if (Result.isNegative()) {
37643764
Diag(CurTok, diag::err_requires_positive_value)
37653765
<< toString(Result, 10) << /*positive*/ 0;
3766-
if (CurTok.isNot(tok::eod))
3766+
if (CurTok.isNot(EndTokenKind))
37673767
DiscardUntilEndOfDirective(CurTok);
37683768
return std::nullopt;
37693769
}
@@ -3906,7 +3906,7 @@ Preprocessor::LexEmbedParameters(Token &CurTok, bool ForHasEmbed) {
39063906
}
39073907
if (!ForHasEmbed) {
39083908
Diag(ParamStartLoc, diag::err_pp_unknown_parameter) << 1 << Parameter;
3909-
if (CurTok.isNot(tok::eod))
3909+
if (CurTok.isNot(EndTokenKind))
39103910
DiscardUntilEndOfDirective(CurTok);
39113911
return std::nullopt;
39123912
}

clang/lib/Lex/PPMacroExpansion.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,16 +1262,11 @@ EmbedResult Preprocessor::EvaluateHasEmbed(Token &Tok, IdentifierInfo *II) {
12621262

12631263
std::optional<LexEmbedParametersResult> Params =
12641264
this->LexEmbedParameters(Tok, /*ForHasEmbed=*/true);
1265-
assert((Params || Tok.is(tok::eod)) &&
1266-
"expected success or to be at the end of the directive");
12671265

12681266
if (!Params)
12691267
return EmbedResult::Invalid;
12701268

1271-
if (Params->UnrecognizedParams > 0)
1272-
return EmbedResult::NotFound;
1273-
1274-
if (!Tok.is(tok::r_paren)) {
1269+
if (Tok.isNot(tok::r_paren)) {
12751270
Diag(this->getLocForEndOfToken(FilenameLoc), diag::err_pp_expected_after)
12761271
<< II << tok::r_paren;
12771272
Diag(LParenLoc, diag::note_matching) << tok::l_paren;
@@ -1280,6 +1275,9 @@ EmbedResult Preprocessor::EvaluateHasEmbed(Token &Tok, IdentifierInfo *II) {
12801275
return EmbedResult::Invalid;
12811276
}
12821277

1278+
if (Params->UnrecognizedParams > 0)
1279+
return EmbedResult::NotFound;
1280+
12831281
SmallString<128> FilenameBuffer;
12841282
StringRef Filename = this->getSpelling(FilenameTok, FilenameBuffer);
12851283
if (Filename.empty())

clang/test/Preprocessor/embed___has_embed_parsing_errors.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,3 +250,35 @@
250250

251251
#if __has_embed("") // expected-error {{empty filename}}
252252
#endif
253+
254+
// expected-error@+3 {{missing ')' after '__has_embed'}} \
255+
expected-error@+3 {{expected value in expression}} \
256+
expected-note@+3 {{to match this '('}}
257+
#if __has_embed (__FILE__ foo limit(1)
258+
#endif
259+
260+
//--- test3.c
261+
// expected-error@+3 {{missing ')' after '__has_embed'}} \
262+
expected-error@+3 {{expected value in expression}} \
263+
expected-note@+3 {{to match this '('}}
264+
#if __has_embed (__FILE__ foo
265+
#endif
266+
267+
// expected-error@+3 {{missing ')' after '__has_embed'}} \
268+
expected-error@+3 {{expected value in expression}} \
269+
expected-note@+3 {{to match this '('}}
270+
#if __has_embed ("a" foo()
271+
#endif
272+
273+
// expected-error@+3 {{missing ')' after '__has_embed'}} \
274+
expected-error@+3 {{expected value in expression}} \
275+
expected-note@+3 {{to match this '('}}
276+
#if __has_embed ("a" bar() foo
277+
#endif
278+
279+
// expected-error@+3 {{missing ')' after '__has_embed'}} \
280+
expected-error@+3 {{expected value in expression}} \
281+
expected-note@+3 {{to match this '('}}
282+
#if __has_embed (__FILE__ limit(1) foo
283+
int a = __has_embed (__FILE__);
284+
#endif

0 commit comments

Comments
 (0)