Re: [PATCH] libcpp: Fix up ICE with __VA_OPT__ [PR125048]
Jason Merrill <[email protected]> Wed, 5 Aug 2026 15:58:11 -0400
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
On 4/29/26 5:20 AM, Jakub Jelinek wrote: > Hi! > > The following testcase ICEs, because we call linemap_enter_macro > and remember what it returned and then in a loop sometimes call > vaopt_state::update (src) which can call expand_arg which under the > hood can reallocate the pfile->line_table->info_macro.maps array. > As linemap_enter_macro returns a pointer into that array, if the > array is reallocated, we then dereference the freed memory. This is a bit worrying about use of linemaps in general, but I guess most places look them up right before use. > The following patch fixes it by remembering the offset into the > pfile->line_table->info_macro.maps array and when we could have called > expand_arg, updates the map variable so that it is correct even after > possible reallocation. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/16.2? OK. > 2026-04-28 Jakub Jelinek <[email protected]> > > PR preprocessor/125048 > * macro.cc (replace_args): Remember the position of map > in the pfile->line_table->info_macro.maps array and if vostate > is DROP, recompute map pointer as expand_arg call could have > reallocated the pfile->line_table->info_macro.maps array. > > * c-c++-common/cpp/va-opt-11.c: New test. > > --- libcpp/macro.cc.jj 2026-03-27 10:17:21.000000000 +0100 > +++ libcpp/macro.cc 2026-04-28 11:25:22.767163448 +0200 > @@ -1995,6 +1995,7 @@ replace_args (cpp_reader *pfile, cpp_has > location_t *virt_locs = NULL; > unsigned int exp_count; > const line_map_macro *map = NULL; > + size_t map_idx = 0; > int track_macro_exp; > > /* First, fully macro-expand arguments, calculating the number of > @@ -2105,6 +2106,7 @@ replace_args (cpp_reader *pfile, cpp_has > map = linemap_enter_macro (pfile->line_table, node, > expansion_point_loc, > num_macro_tokens); > + map_idx = map - pfile->line_table->info_macro.maps; > } > i = 0; > vaopt_state vaopt_tracker (pfile, macro->variadic, &args[macro->paramc - 1]); > @@ -2226,6 +2228,11 @@ replace_args (cpp_reader *pfile, cpp_has > NULL, 0); > } > } > + else if (vostate == vaopt_state::DROP && map) > + /* For the DROP case vaopt_tracker.update (src) can call > + expand_arg and that can reallocate the maps, so need to > + update the map pointer. */ > + map = pfile->line_table->info_macro.maps + map_idx; > continue; > } > > --- gcc/testsuite/c-c++-common/cpp/va-opt-11.c.jj 2026-04-28 11:34:59.783177007 +0200 > +++ gcc/testsuite/c-c++-common/cpp/va-opt-11.c 2026-04-28 11:34:52.220307897 +0200 > @@ -0,0 +1,13 @@ > +/* PR preprocessor/125048 */ > +/* { dg-do preprocess } */ > +/* { dg-options "-std=c23" { target c } } */ > +/* { dg-options "-std=c++20" { target c++ } } */ > + > +#define A(...)B(B(B(B(__VA_ARGS__##__VA_OPT__())))) > +#define B(...)C(C(C(C(__VA_ARGS__##__VA_OPT__())))) > +#define C(...)D(D(D(D(__VA_ARGS__##__VA_OPT__())))) > +#define D(...)E(E(E(E(__VA_ARGS__##__VA_OPT__())))) > +#define E(...)__VA_ARGS__ > +#define F > +A(F) > +/* { dg-final { scan-file va-opt-11.i "D\\\(D\\\(D\\\(C\\\(C\\\(C\\\(B\\\(B\\\(B\\\(\\\)\\\)\\\)\\\)\\\)\\\)\\\)\\\)\\\)" } } */ > > Jakub >