Andrea Pinski <[email protected]> writes: > On Mon, Aug 31, 2026 at 7:42 AM Léo Hardt <[email protected]> wrote:
>> >> fix(libcpp): Don't ICE parsing __has_include outside directive. >> cc: libcpp maintainers. >> >> Fixes an ICE wherein 'glue_header_name' is called outside >> parsing a preprocessor directive, causing an entire file to >> be read and presumed to be a header name. Then, on the next >> read (the closing '>' or ')'), the parser ICEs since the input >> has already come to an end. >> >> Affects __has_include and __has_embed when used outside directives. >> Minimal reproducible crash has two tokens (both gcc and g++): >> >> __has_include< >> >> Given glue_header_name was written for usage inside preprocessor >> parsing, we could either change it or not call it in case of errors. >> I opted to bail out early on an error case, since there is no chance >> it could influence valid code parsing. >> >> See more on https://gcc.gnu.org/PR121508. >> >> PR preprocessor/121508 >> PR preprocessor/123339 >> >> libcpp/ChangeLog: >> >> * macro.cc (builtin_has_include_1): Bail early if >> not on a preprocessor directive. > > Ok. > >> >> Signed-off-by: Léo Hardt <[email protected]> >> --- >> libcpp/macro.cc | 7 +++++-- >> 1 file changed, 5 insertions(+), 2 deletions(-) >> >> diff --git a/libcpp/macro.cc b/libcpp/macro.cc >> index 736c360336d..064df1d4134 100644 >> --- a/libcpp/macro.cc >> +++ b/libcpp/macro.cc >> @@ -392,8 +392,11 @@ builtin_has_include_1 (cpp_reader *pfile, const char >> *name, bool *paren, >> bool *bracket, location_t *loc) >> { >> if (!pfile->state.in_directive) >> - cpp_error (pfile, CPP_DL_ERROR, >> - "%qs used outside of preprocessing directive", name); >> + { >> + cpp_error (pfile, CPP_DL_ERROR, >> + "%qs used outside of preprocessing directive", name); >> + return NULL; >> + } Unless I'm missing something... This commit added an early return to builtin_has_include_1 that skips the set to paren: if (!pfile->state.in_directive) { cpp_error (pfile, CPP_DL_ERROR, "%qs used outside of preprocessing directive", name); return NULL; } pfile->state.angled_headers = true; const auto sav_padding = pfile->state.directive_wants_padding; pfile->state.directive_wants_padding = true; const cpp_token *token = _cpp_get_token_no_padding (pfile); *paren = token->type == CPP_OPEN_PAREN; But every call to builtin_has_include_1 has paren uninitialized: static int builtin_has_include (cpp_reader *pfile, cpp_hashnode *op, bool has_next) { int result = 0; bool paren, bracket; char *fname = builtin_has_include_1 (pfile, (const char *) NODE_NAME (op), &paren, &bracket, NULL); This is causing spurious test failures for me, seemingly from the uninitialized read. Aldy
