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