gcc.dg/tree-ssa/builtin-sprintf-2.c is showing intermittent failures, which valgrind shows to be a read past the end of a buffer.
The root cause is that the on-demand substring loc code isn't set up to cope with -ftrack-macro-expansion != 2 (the default). In the failing case, it attempts to use this location as the location of the literal: ../../src/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-2.c:95:1: note: RNG (0, 0, 0, "%hhi", i) ^~~ rather than: RNG (0, 0, 0, "%hhi", i) ^~~~ On re-parsing to generate the on-demand substring locations, it thus erroneously attempts to parse the 'R' as a raw string, and so this code within cpp_interpret_string_1 fires: if (*p == 'R') { const uchar *prefix; /* Skip over 'R"'. */ p += 2; prefix = p; while (*p != '(') p++; and the issue happens in the "while" loop, as it erroneously walks through this memory: (gdb) p strs.m_vec.m_vecdata[0] $20 = {len = 3, text = 0xc9bcca0 "RNG"} trying to find the open parenthesis, and starts reading beyond the allocated buffer. The fix is to require that -ftrack-macro-expansion == 2 (the default) for on-demand string literal locations to be available, failing gracefully to simply using the whole location_t otherwise. Doing so requires some fixups to existing test cases: [gcc.dg/tree-ssa/builtin-sprintf-warn-{1,4}.c both have -ftrack-macro-expansion=0. In the latter case, it seems to be unnecessary, so this patch removes it. In the former case, it seems to be needed, but there are some expected locations in test_sprintf_note that are changed by the patch. It's not clear to me how to fix that, so for now the patch removes the expected column numbers from that function within the test case. Successfully bootstrapped®rtested on x86_64-pc-linux-gnu. I think I can self-approve the input.c change and new test cases, but I'm not sure about the changes to Martin's test cases. Martin: are the changes to your test cases OK by you, or is there a better way to rewrite them? gcc/ChangeLog: PR preprocessor/78324 * input.c (get_substring_ranges_for_loc): Fail gracefully if -ftrack-macro-expansion has a value other than 2. gcc/testsuite/ChangeLog: PR preprocessor/78324 * gcc.dg/plugin/diagnostic-test-string-literals-1.c (test_multitoken_macro): New function. * gcc.dg/plugin/diagnostic-test-string-literals-3.c: New test case. * gcc.dg/plugin/diagnostic-test-string-literals-4.c: New test case. * gcc.dg/plugin/plugin.exp (plugin_test_list): Add the new test cases. * gcc.dg/tree-ssa/builtin-sprintf-warn-1.c (test_sprintf_note): Drop expected column numbers from dg-warning directives. * gcc.dg/tree-ssa/builtin-sprintf-warn-4.c: Drop -ftrack-macro-expansion=0. --- gcc/input.c | 9 +++++ .../plugin/diagnostic-test-string-literals-1.c | 16 ++++++++ .../plugin/diagnostic-test-string-literals-3.c | 43 ++++++++++++++++++++++ .../plugin/diagnostic-test-string-literals-4.c | 43 ++++++++++++++++++++++ gcc/testsuite/gcc.dg/plugin/plugin.exp | 4 +- .../gcc.dg/tree-ssa/builtin-sprintf-warn-1.c | 6 +-- .../gcc.dg/tree-ssa/builtin-sprintf-warn-4.c | 2 +- 7 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-3.c create mode 100644 gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-4.c diff --git a/gcc/input.c b/gcc/input.c index 728f4dd..611e18b 100644 --- a/gcc/input.c +++ b/gcc/input.c @@ -1322,6 +1322,15 @@ get_substring_ranges_for_loc (cpp_reader *pfile, if (strloc == UNKNOWN_LOCATION) return "unknown location"; + /* Reparsing the strings requires accurate location information. + If -ftrack-macro-expansion has been overridden from its default + of 2, then we might have a location of a macro expansion point, + rather than the location of the literal itself. + Avoid this by requiring that we have full macro expansion tracking + for substring locations to be available. */ + if (cpp_get_options (pfile)->track_macro_expansion != 2) + return "track_macro_expansion != 2"; + /* If string concatenation has occurred at STRLOC, get the locations of all of the literal tokens making up the compound string. Otherwise, just use STRLOC. */ diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c index 3e44936..76a085e 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c @@ -243,6 +243,22 @@ test_macro (void) { dg-end-multiline-output "" } */ } +void +test_multitoken_macro (void) +{ +#define RANGE ("0123456789") /* { dg-error "unable to read substring location: macro expansion" } */ + __emit_string_literal_range (RANGE, 4, 3, 6); +/* { dg-begin-multiline-output "" } + #define RANGE ("0123456789") + ^ + { dg-end-multiline-output "" } */ +/* { dg-begin-multiline-output "" } + __emit_string_literal_range (RANGE, 4, 3, 6); + ^~~~~ + { dg-end-multiline-output "" } */ +#undef RANGE +} + /* Verify that the location of the closing quote is used for the location of the null terminating character. */ diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-3.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-3.c new file mode 100644 index 0000000..95b78bc --- /dev/null +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-3.c @@ -0,0 +1,43 @@ +/* Similar to diagnostic-test-string-literals-1.c, but with + -ftrack-macro-expansion=0. */ + +/* { dg-do compile } */ +/* { dg-options "-O -ftrack-macro-expansion=0" } */ + +extern void __emit_string_literal_range (const void *literal, int caret_idx, + int start_idx, int end_idx); + +void +test_simple_string_literal (void) +{ + __emit_string_literal_range ("0123456789", /* { dg-error "unable to read substring location: track_macro_expansion != 2" } */ + 6, 6, 7); +} + +void +test_concatenated_string_literal (void) +{ + __emit_string_literal_range ("01234" "56789", /* { dg-error "unable to read substring location: track_macro_expansion != 2" } */ + 4, 3, 6); +} + +/* To reproduce PR preprocessor/78324, the macro name should start + with the letter 'R'. */ + +void +test_macro (void) +{ +#define RANGE "01234" + __emit_string_literal_range (RANGE /* { dg-error "unable to read substring location: track_macro_expansion != 2" } */ + "56789", + 4, 3, 6); +#undef RANGE +} + +void +test_multitoken_macro (void) +{ +#define RANGE ("0123456789") + __emit_string_literal_range (RANGE, 4, 3, 6); /* { dg-error "unable to read substring location: track_macro_expansion != 2" } */ +#undef RANGE +} diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-4.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-4.c new file mode 100644 index 0000000..d47818a --- /dev/null +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-4.c @@ -0,0 +1,43 @@ +/* Similar to diagnostic-test-string-literals-1.c, but with + -ftrack-macro-expansion=1. */ + +/* { dg-do compile } */ +/* { dg-options "-O -ftrack-macro-expansion=1" } */ + +extern void __emit_string_literal_range (const void *literal, int caret_idx, + int start_idx, int end_idx); + +void +test_simple_string_literal (void) +{ + __emit_string_literal_range ("0123456789", /* { dg-error "unable to read substring location: track_macro_expansion != 2" } */ + 6, 6, 7); +} + +void +test_concatenated_string_literal (void) +{ + __emit_string_literal_range ("01234" "56789", /* { dg-error "unable to read substring location: track_macro_expansion != 2" } */ + 4, 3, 6); +} + +/* To reproduce PR preprocessor/78324, the macro name should start + with the letter 'R'. */ + +void +test_macro (void) +{ +#define RANGE "01234" /* { dg-error "unable to read substring location: track_macro_expansion != 2" } */ + __emit_string_literal_range (RANGE + "56789", + 4, 3, 6); +#undef RANGE +} + +void +test_multitoken_macro (void) +{ +#define RANGE ("0123456789") /* { dg-error "unable to read substring location: track_macro_expansion != 2" } */ + __emit_string_literal_range (RANGE, 4, 3, 6); +#undef RANGE +} diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp index 32ca748..eb15a66 100644 --- a/gcc/testsuite/gcc.dg/plugin/plugin.exp +++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp @@ -73,7 +73,9 @@ set plugin_test_list [list \ diagnostic-test-show-trees-1.c } \ { diagnostic_plugin_test_string_literals.c \ diagnostic-test-string-literals-1.c \ - diagnostic-test-string-literals-2.c } \ + diagnostic-test-string-literals-2.c \ + diagnostic-test-string-literals-3.c \ + diagnostic-test-string-literals-4.c } \ { location_overflow_plugin.c \ location-overflow-test-1.c \ location-overflow-test-2.c } \ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c index 5779a95..b6a6011 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c @@ -181,13 +181,13 @@ void test_sprintf_note (void) /* Diagnostic column numbers are 1-based. */ P (buffer (0), /* { dg-message "format output 4 bytes into a destination of size 0" } */ - "%c%s%i", '1', "2", 3); /* { dg-warning "7:.%c. directive writing 1 byte into a region of size 0" } */ + "%c%s%i", '1', "2", 3); /* { dg-warning ".%c. directive writing 1 byte into a region of size 0" } */ P (buffer (1), /* { dg-message "format output 6 bytes into a destination of size 1" } */ - "%c%s%i", '1', "23", 45); /* { dg-warning "9:.%s. directive writing 2 bytes into a region of size 0" } */ + "%c%s%i", '1', "23", 45); /* { dg-warning ".%s. directive writing 2 bytes into a region of size 0" } */ P (buffer (2), /* { dg-message "format output 6 bytes into a destination of size 2" } */ - "%c%s%i", '1', "2", 345); /* { dg-warning "11:.%i. directive writing 3 bytes into a region of size 0" } */ + "%c%s%i", '1', "2", 345); /* { dg-warning ".%i. directive writing 3 bytes into a region of size 0" } */ /* It would be nice if the caret in the location range for the format string below could be made to point at the closing quote of the format diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-4.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-4.c index faa5806..b587d00 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-4.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-4.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-Wformat -Wformat-length=1 -fdiagnostics-show-caret -ftrack-macro-expansion=0" } */ +/* { dg-options "-Wformat -Wformat-length=1 -fdiagnostics-show-caret" } */ extern int sprintf (char*, const char*, ...); -- 1.8.5.3