https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125723
Bug ID: 125723
Summary: heap-use-after-free in
cpp_display_width_computation::process_next_codepoint
when line marker file is 2^n * 8192 bytes
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: daniel.wait.dev at gmail dot com
Target Milestone: ---
Host: x86_64-pc-linux-gnu
Target: x86_64-pc-linux-gnu
Build: x86_64-pc-linux-gnu
Heap-use-after-free while producing the diagnostic for a parsing error on an
invalid preprocessed C input with an ASan-enabled GCC build.
This occurs when a preprocessed file, source.i, references another file via a
line marker and then contains invalid C.
The referenced line marker file, source.c, must have size 2^n * 8192 bytes,
where n = 0, 1, 2, 3, etc. For example, I can reproduce this with source.c
sizes: 8192, 16384, 32768, 65536.
The contents of source.c do not appear to matter. It is sufficient to create a
file of the required size with truncate.
GCC version 17.0.0
Commit b700707a77eeaa1d37f733c4b2d2e242063c29d2
System type x86_64-pc-linux-gnu
Configured with:
../gcc-latest/configure CFLAGS='-O2 -g' CXXFLAGS='-O2 -g' --enable-languages=c
--enable-checking=yes --enable-bootstrap --with-build-config=bootstrap-asan
--disable-multilib --disable-nls --disable-lto --disable-libgomp
--disable-libquadmath --disable-libssp
Reproduction steps:
$ cat > source.i <<EOF
# 1 "source.c"
x
EOF
$ truncate -s 8192 source.c
$ ASAN_OPTIONS=detect_leaks=0 ./gcc-latest-asan/gcc/xgcc
-B./gcc-latest-asan/gcc source.i
=================================================================
==588196==ERROR: AddressSanitizer: heap-use-after-free on address
0x709a001ec900 at pc 0x00000758b06f bp 0x7fffe072e960 sp 0x7fffe072e958
READ of size 1 at 0x709a001ec900 thread T0
#0 0x00000758b06e in
cpp_display_width_computation::process_next_codepoint(cpp_decoded_char*)
../../gcc-latest/libcpp/charset.cc:3413
#1 0x00000758b06e in cpp_byte_column_to_display_column(char const*, int,
int, cpp_char_column_policy const&) ../../gcc-latest/libcpp/charset.cc:3484
#2 0x0000074638d0 in
location_compute_display_column(diagnostics::file_cache&, expanded_location,
cpp_char_column_policy const&) ../../gcc-latest/gcc/input.cc:377
#3 0x0000071f7e86 in convert_column_unit
../../gcc-latest/gcc/diagnostics/context.cc:778
#4 0x0000071f7e86 in
diagnostics::column_options::convert_column(diagnostics::file_cache&,
expanded_location) const ../../gcc-latest/gcc/diagnostics/context.cc:793
#5 0x0000071f8188 in
diagnostics::column_policy::converted_column(expanded_location) const
../../gcc-latest/gcc/diagnostics/context.cc:811
#6 0x0000071f8188 in
diagnostics::column_policy::get_location_text(expanded_location const&, bool,
bool) const ../../gcc-latest/gcc/diagnostics/context.cc:830
#7 0x0000072e1f32 in
diagnostics::text_sink::get_location_text(expanded_location const&) const
../../gcc-latest/gcc/diagnostics/text-sink.cc:608
#8 0x0000072e1f32 in
diagnostics::text_sink::build_prefix(diagnostics::diagnostic_info const&) const
../../gcc-latest/gcc/diagnostics/text-sink.cc:331
#9 0x000002b0f485 in default_tree_diagnostic_text_starter
../../gcc-latest/gcc/tree-diagnostic.cc:55
#10 0x0000072e1359 in
diagnostics::text_sink::on_report_diagnostic(diagnostics::diagnostic_info
const&, diagnostics::kind) ../../gcc-latest/gcc/diagnostics/text-sink.cc:215
#11 0x0000071fd29b in
diagnostics::context::report_diagnostic(diagnostics::diagnostic_info*)
../../gcc-latest/gcc/diagnostics/context.cc:1535
#12 0x0000071fed50 in diagnostics::context::diagnostic_impl(rich_location*,
diagnostics::metadata const*, diagnostics::option_id, char const*,
__va_list_tag (*) [1], diagnostics::kind)
../../gcc-latest/gcc/diagnostics/context.cc:1689
#13 0x0000071d487e in error_at(rich_location*, char const*, ...)
../../gcc-latest/gcc/diagnostic-global-context.cc:676
#14 0x0000010c7b63 in c_parse_error(char const*, cpp_ttype, tree_node*,
unsigned char, rich_location*) ../../gcc-latest/gcc/c-family/c-common.cc:7096
#15 0x000000ecf55a in c_parser_error_richloc
../../gcc-latest/gcc/c/c-parser.cc:1117
#16 0x000000ed26c8 in c_parser_error(c_parser*, char const*)
../../gcc-latest/gcc/c/c-parser.cc:1140
#17 0x000000fa91c1 in c_parser_declaration_or_fndef
../../gcc-latest/gcc/c/c-parser.cc:3268
#18 0x000001005161 in c_parser_external_declaration
../../gcc-latest/gcc/c/c-parser.cc:2256
#19 0x00000100808f in c_parser_translation_unit
../../gcc-latest/gcc/c/c-parser.cc:2095
#20 0x00000100808f in c_parse_file()
../../gcc-latest/gcc/c/c-parser.cc:31480
#21 0x00000118e392 in c_common_parse_file()
../../gcc-latest/gcc/c-family/c-opts.cc:1430
#22 0x000002990bad in compile_file ../../gcc-latest/gcc/toplev.cc:455
#23 0x000000be1180 in do_compile ../../gcc-latest/gcc/toplev.cc:2228
#24 0x000000be1180 in toplev::main(int, char**)
../../gcc-latest/gcc/toplev.cc:2392
#25 0x000000bed450 in main ../../gcc-latest/gcc/main.cc:39
#26 0x724a00e471c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId:
8e9fd827446c24067541ac5390e6f527fb5947bb)
#27 0x724a00e4728a in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId:
8e9fd827446c24067541ac5390e6f527fb5947bb)
#28 0x000000c0b6b4 in _start
(/workspaces/fyp/new/sut/gcc-latest-asan/gcc/cc1+0xc0b6b4)
0x709a001ec900 is located 0 bytes inside of 8192-byte region
[0x709a001ec900,0x709a001ee900)
freed by thread T0 here:
#0 0x000000cf439f in realloc
../../../../gcc-latest/libsanitizer/asan/asan_malloc_linux.cpp:81
#1 0x0000076d0ad0 in xrealloc ../../gcc-latest/libiberty/xmalloc.c:181
previously allocated by thread T0 here:
#0 0x000000cf439f in realloc
../../../../gcc-latest/libsanitizer/asan/asan_malloc_linux.cpp:81
#1 0x0000076d0ad0 in xrealloc ../../gcc-latest/libiberty/xmalloc.c:181
SUMMARY: AddressSanitizer: heap-use-after-free
../../gcc-latest/libcpp/charset.cc:3413 in
cpp_display_width_computation::process_next_codepoint(cpp_decoded_char*)
Shadow bytes around the buggy address:
0x709a001ec680: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x709a001ec700: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x709a001ec780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x709a001ec800: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x709a001ec880: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x709a001ec900:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x709a001ec980: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x709a001eca00: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x709a001eca80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x709a001ecb00: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x709a001ecb80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==588196==ABORTING