fix buffer overflow on all emphasis flags set #4498
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Found while fuzzing some code.
The following code compiled with sanitizer overflows a buffer in
fmt::detail::ansi_color_escape.================================================================= ==1064648==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7b5f2a0004a0 at pc 0x56231c89794d bp 0x7fff64601a90 sp 0x7fff64601a80 WRITE of size 1 at 0x7b5f2a0004a0 thread T0 #0 0x56231c89794c in fmt::v11::detail::ansi_color_escape<char>::ansi_color_escape(fmt::v11::emphasis) (/home/dominic/tmp/fmt_overflow/a.out+0x2494c) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #1 0x56231c88fc0c in fmt::v11::detail::ansi_color_escape<char> fmt::v11::detail::make_emphasis<char>(fmt::v11::emphasis) (/home/dominic/tmp/fmt_overflow/a.out+0x1cc0c) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #2 0x56231c8b3b36 in decltype (({parm#2}.out)()) fmt::v11::formatter<fmt::v11::detail::styled_arg<char [5]>, char, void>::format<fmt::v11::context>(fmt::v11::detail::styled_arg<char [5]> const&, fmt::v11::context&) const (/home/dominic/tmp/fmt_overflow/a.out+0x40b36) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #3 0x56231c8a09ff in void fmt::v11::detail::value<fmt::v11::context>::format_custom<fmt::v11::detail::styled_arg<char [5]>, fmt::v11::formatter<fmt::v11::detail::styled_arg<char [5]>, char, void> >(void*, fmt::v11::parse_context<char>&, fmt::v11::context&) (/home/dominic/tmp/fmt_overflow/a.out+0x2d9ff) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #4 0x56231c895114 in fmt::v11::basic_format_arg<fmt::v11::context>::handle::format(fmt::v11::parse_context<char>&, fmt::v11::context&) const (/home/dominic/tmp/fmt_overflow/a.out+0x22114) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #5 0x56231c88f524 in fmt::v11::detail::default_arg_formatter<char>::operator()(fmt::v11::basic_format_arg<fmt::v11::context>::handle) (/home/dominic/tmp/fmt_overflow/a.out+0x1c524) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #6 0x56231c882ffb in fmt::v11::detail::vformat_to(fmt::v11::detail::buffer<char>&, fmt::v11::basic_string_view<char>, fmt::v11::basic_format_args<fmt::v11::context>, fmt::v11::detail::locale_ref) (/home/dominic/tmp/fmt_overflow/a.out+0xfffb) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #7 0x56231c883779 in fmt::v11::vprint(_IO_FILE*, fmt::v11::basic_string_view<char>, fmt::v11::basic_format_args<fmt::v11::context>) (/home/dominic/tmp/fmt_overflow/a.out+0x10779) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #8 0x56231c883905 in fmt::v11::vprint(fmt::v11::basic_string_view<char>, fmt::v11::basic_format_args<fmt::v11::context>) (/home/dominic/tmp/fmt_overflow/a.out+0x10905) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #9 0x56231c878cc9 in main (/home/dominic/tmp/fmt_overflow/a.out+0x5cc9) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #10 0x7f5f2c0376b4 (/usr/lib/libc.so.6+0x276b4) (BuildId: 468e3585c794491a48ea75fceb9e4d6b1464fc35) #11 0x7f5f2c037768 in __libc_start_main (/usr/lib/libc.so.6+0x27768) (BuildId: 468e3585c794491a48ea75fceb9e4d6b1464fc35) #12 0x56231c878524 in _start (/home/dominic/tmp/fmt_overflow/a.out+0x5524) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) Address 0x7b5f2a0004a0 is located in stack of thread T0 at offset 160 in frame #0 0x56231c8b39d3 in decltype (({parm#2}.out)()) fmt::v11::formatter<fmt::v11::detail::styled_arg<char [5]>, char, void>::format<fmt::v11::context>(fmt::v11::detail::styled_arg<char [5]> const&, fmt::v11::context&) const (/home/dominic/tmp/fmt_overflow/a.out+0x409d3) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) This frame has 6 object(s): [32, 40) 'out' (line 589) [64, 80) '<unknown>' [96, 112) 'reset_color' (line 611) [128, 160) 'emphasis' (line 594) <== Memory access at offset 160 overflows this variable [192, 224) 'foreground' (line 599) [256, 288) 'background' (line 605) HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork (longjmp and C++ exceptions *are* supported) SUMMARY: AddressSanitizer: stack-buffer-overflow (/home/dominic/tmp/fmt_overflow/a.out+0x2494c) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) in fmt::v11::detail::ansi_color_escape<char>::ansi_color_escape(fmt::v11::emphasis) Shadow bytes around the buggy address: 0x7b5f2a000200: f1 f1 f1 f1 f1 f1 01 f2 00 f2 f2 f2 00 f2 f2 f2 0x7b5f2a000280: 00 00 f2 f2 00 00 f2 f2 00 00 f2 f2 00 00 00 00 0x7b5f2a000300: f2 f2 f2 f2 00 00 00 00 00 00 00 f3 f3 f3 f3 f3 0x7b5f2a000380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7b5f2a000400: f1 f1 f1 f1 00 f2 f2 f2 00 00 f2 f2 00 00 f2 f2 =>0x7b5f2a000480: 00 00 00 00[f2]f2 f2 f2 00 00 00 00 f2 f2 f2 f2 0x7b5f2a000500: 00 00 00 00 f3 f3 f3 f3 00 00 00 00 00 00 00 00 0x7b5f2a000580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7b5f2a000600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7b5f2a000680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7b5f2a000700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 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 ==1064648==ABORTINGfmt version latest commit as of writing. git commit hash 553ec11