Bug 78569 - "internal compiler error: in get_substring_ranges_for_loc" processing sprintf buffer overflow
Summary: "internal compiler error: in get_substring_ranges_for_loc" processing sprintf...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: preprocessor (show other bugs)
Version: 7.0
: P3 normal
Target Milestone: ---
Assignee: David Malcolm
URL:
Keywords:
: 78169 78836 (view as bug list)
Depends on:
Blocks: 79210
  Show dependency treegraph
 
Reported: 2016-11-28 15:51 UTC by Arnd Bergmann
Modified: 2017-03-24 18:52 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2016-11-29 00:00:00


Attachments
preprocessed drivers/tty/nozomi.c from linux-4.9-rc5+next (228.19 KB, application/gzip)
2016-11-28 15:51 UTC, Arnd Bergmann
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Arnd Bergmann 2016-11-28 15:51:07 UTC
Created attachment 40180 [details]
preprocessed drivers/tty/nozomi.c from linux-4.9-rc5+next

Originally replied to bug #78169, but I believe it's different now, so I opened a new one here.

When building the Linux kernel with gcc snapshot x86_64-linux-gcc-7.0.0 (GCC) 7.0.0 20161124 (experimental), I get this output for incorrect code:

/git/arm-soc/drivers/tty/nozomi.c: In function 'receive_flow_control':
/git/arm-soc/drivers/tty/nozomi.c:919:12: internal compiler error: in get_substring_ranges_for_loc, at input.c:1388
 static int receive_flow_control(struct nozomi *dc)
            ^~~~~~~~~~~~~~~~~~~~
0x110f22f get_substring_ranges_for_loc
	/home/arnd/git/gcc/gcc/input.c:1388
0x110f22f get_source_location_for_substring(cpp_reader*, string_concat_db*, unsigned int, cpp_ttype, int, int, int, unsigned int*)
	/home/arnd/git/gcc/gcc/input.c:1458
0x67230e c_get_substring_location(substring_loc const&, unsigned int*)
	/home/arnd/git/gcc/gcc/c-family/c-common.c:865
0xa5ce8f substring_loc::get_location(unsigned int*) const
	/home/arnd/git/gcc/gcc/substring-locations.c:194
0xa5ce8f format_warning_va(substring_loc const&, source_range const*, char const*, int, char const*, __va_list_tag (*) [1])
	/home/arnd/git/gcc/gcc/substring-locations.c:112
0xa5d1f4 format_warning_at_substring(substring_loc const&, source_range const*, char const*, int, char const*, ...)
	/home/arnd/git/gcc/gcc/substring-locations.c:179
0x1038159 add_bytes
	/home/arnd/git/gcc/gcc/gimple-ssa-sprintf.c:2083
0x1038159 compute_format_length
	/home/arnd/git/gcc/gcc/gimple-ssa-sprintf.c:2208
0x1038159 handle_gimple_call
	/home/arnd/git/gcc/gcc/gimple-ssa-sprintf.c:2772
0x1038159 execute
	/home/arnd/git/gcc/gcc/gimple-ssa-sprintf.c:2799
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.

It seems to only happen when I first preprocess the file and feed that into compiler again (as done by ccache, but easily reproduced without it).

command to reproduce is:
x86_64-linux-gcc-7.0.0 -Wall -O -Wno-pointer-sign -s nozomi.i

I've only seen this with an x86 target, not with ARM, but that could be coincidence.

The code line causing this is

  do {if (0x01 & debug) do { char tmp[128]; snprintf(tmp, sizeof(tmp),"The Base Band sends this value as a response to a " "request for IMSI detach sent over the control " "channel uplink (see section 7.6.1)."); printk("\001" "7" "[%d] %s(): %s\n", 932, __func__, tmp); } while (0); } while (0);

and this in turn causes a stack overflow of the 'tmp' array as the string that gets copied in there is slightly longer than 128 bytes.
Comment 1 Andrew Pinski 2016-11-28 19:26:20 UTC
I think this is also the same issue as PR 78498.
Comment 2 David Malcolm 2016-11-29 19:48:52 UTC
Thanks for filing this bug report.

(In reply to Andrew Pinski from comment #1)
> I think this is also the same issue as PR 78498.

Thanks, but I think it's a separate issue.


The backtrace shows the ICE is at line 1388 of input.c, which would suggest it's a failure of this assertion:

      gcc_assert (line_width >= (start.column - 1 + literal_length));

where it earlier called:

      const char *line = location_get_source_line (start.file, start.line,
						   &line_width);

I *think* what's happening is that that line is reading the latest on-disk copy of the input file, but using location information based on the state of the input file when the .i file was created.

I'm not able to reproduce this yet, but I'll try to based on the above theory.
Comment 3 David Malcolm 2016-11-29 20:13:31 UTC
I'm able to reproduce this, based on the theory in comment #2.

I'm working on a fix.
Comment 4 David Malcolm 2016-11-29 21:21:50 UTC
*** Bug 78169 has been marked as a duplicate of this bug. ***
Comment 5 David Malcolm 2016-11-30 01:14:09 UTC
Author: dmalcolm
Date: Wed Nov 30 01:13:37 2016
New Revision: 242990

URL: https://gcc.gnu.org/viewcvs?rev=242990&root=gcc&view=rev
Log:
substring locations and # line directives (PR preprocessor/78569)

The ICE in PR preprocessor/78569 appears to be due to an attempt to
generate substring locations in a .i file where the underlying .c file
has changed since the .i file was generated.

This can't work, so it seems safest for the on-demand substring
locations to be unavailable for such files, falling back to
"whole string" locations for such cases.

gcc/ChangeLog:
	PR preprocessor/78569
	* input.c (get_substring_ranges_for_loc): Fail gracefully if
	line directives were present.

gcc/testsuite/ChangeLog:
	PR preprocessor/78569
	* gcc.dg/format/pr78569.c: New test case.

Added:
    trunk/gcc/testsuite/gcc.dg/format/pr78569.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/input.c
    trunk/gcc/testsuite/ChangeLog
Comment 6 David Malcolm 2016-11-30 01:20:37 UTC
Should be fixed by r242990; marking this as resolved.  Feel free to reopen it if you still see the problem after r242990.
Comment 7 Arnd Bergmann 2016-11-30 08:31:52 UTC
Confirmed fixed for all source files in which I'd seen the problem. Thanks!
Comment 8 Martin Sebor 2017-03-24 18:52:00 UTC
*** Bug 78836 has been marked as a duplicate of this bug. ***