Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc++][format] out of bounds read outside the format string #65011

Closed
pauldreik opened this issue Aug 26, 2023 · 3 comments
Closed

[libc++][format] out of bounds read outside the format string #65011

pauldreik opened this issue Aug 26, 2023 · 3 comments
Assignees
Labels
confirmed Verified by a second party format C++20 std::format or std::print, and anything related to them libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Comments

@pauldreik
Copy link

pauldreik commented Aug 26, 2023

The following program:

#include <format>
#include <string_view>
int main() {
    const char fmt[] = {'{','0'};
    char buf[4096];
    [[maybe_unused]] auto ignored = std::vformat_to(
        buf, std::string_view{fmt, fmt + sizeof(fmt)}, std::make_format_args());
}

causes an out of bounds read on the format buffer "fmt". When compiled with libc++ on the current clang trunk (as of what is compiler explorer on the 2023-08-26) and address sanitizer, the message below appears.

Compile flags: -std=c++23 -fsanitize=address,undefined -stdlib=libc++

Link to reproducer: https://godbolt.org/z/bEvYT4b1j

=================================================================
==1==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fc964b000e2 at pc 0x55efa5b48ff3 bp 0x7ffd9ed4f9f0 sp 0x7ffd9ed4f9e8
READ of size 1 at 0x7fc964b000e2 thread T0
#0 0x55efa5b48ff2 in char const* std::__1::__format::__handle_replacement_field[abi:v180000]<char const*, std::__1::basic_format_parse_context, std::__1::basic_format_context<std::__1::back_insert_iterator<std::__1::__format::__output_buffer>, char>>(char const*, char const*, std::__1::basic_format_parse_context&, std::__1::basic_format_context<std::__1::back_insert_iterator<std::__1::__format::__output_buffer>, char>&) /opt/compiler-explorer/clang-trunk-20230824/bin/../include/c++/v1/__format/format_functions.h:248:18
#1 0x55efa5b47263 in std::__1::basic_format_context<std::__1::back_insert_iterator<std::__1::__format::__output_buffer>, char>::iterator std::__1::__format::__vformat_to[abi:v180000]<std::__1::basic_format_parse_context, std::__1::basic_format_context<std::__1::back_insert_iterator<std::__1::__format::__output_buffer>, char>>(std::__1::basic_format_parse_context&&, std::__1::basic_format_context<std::__1::back_insert_iterator<std::__1::__format::__output_buffer>, char>&&) /opt/compiler-explorer/clang-trunk-20230824/bin/../include/c++/v1/__format/format_functions.h:312:13
#2 0x55efa5b46a17 in char* std::__1::__vformat_to[abi:v180000]<char*, char, std::__1::back_insert_iterator<std::__1::__format::__output_buffer>>(char*, std::__1::basic_string_view<char, std::__1::char_traits>, std::__1::basic_format_args<std::__1::basic_format_context<std::__1::back_insert_iterator<std::__1::__format::__output_buffer>, char>>) /opt/compiler-explorer/clang-trunk-20230824/bin/../include/c++/v1/__format/format_functions.h:387:5
#3 0x55efa5b46109 in char* std::__1::vformat_to[abi:v180000]<char*>(char*, std::__1::basic_string_view<char, std::__1::char_traits>, std::__1::basic_format_args<std::__1::basic_format_context<std::__1::back_insert_iterator<std::__1::__format::__output_buffer>, char>>) /opt/compiler-explorer/clang-trunk-20230824/bin/../include/c++/v1/__format/format_functions.h:399:10
#4 0x55efa5b46109 in main /app/example.cpp:6:37
#5 0x7fc966844082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
#6 0x55efa5a6b4ad in _start (/app/output.s+0x4a4ad)

Address 0x7fc964b000e2 is located in stack of thread T0 at offset 226 in frame
#0 0x55efa5b45b87 in main /app/example.cpp:3

This frame has 9 object(s):
[32, 48) '__fmt.i'
[64, 80) 'agg.tmp.i'
[96, 120) 'agg.tmp1.i'
[160, 184) 'agg.tmp46'
[224, 226) 'fmt' (line 4) <== Memory access at offset 226 overflows this variable
[240, 4336) 'buf' (line 5)
[4464, 4480) 'agg.tmp' (line 6)
[4496, 4520) 'agg.tmp4' (line 6)
[4560, 4576) 'ref.tmp' (line 6)
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 /opt/compiler-explorer/clang-trunk-20230824/bin/../include/c++/v1/__format/format_functions.h:248:18 in char const* std::__1::__format::__handle_replacement_field[abi:v180000]<char const*, std::__1::basic_format_parse_context, std::__1::basic_format_context<std::__1::back_insert_iterator<std::__1::__format::__output_buffer>, char>>(char const*, char const*, std::__1::basic_format_parse_context&, std::__1::basic_format_context<std::__1::back_insert_iterator<std::__1::__format::__output_buffer>, char>&)
Shadow bytes around the buggy address:
0x7fc964affe00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fc964affe80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fc964afff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fc964afff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fc964b00000: f1 f1 f1 f1 00 00 f2 f2 00 00 f2 f2 00 00 00 f2
=>0x7fc964b00080: f2 f2 f2 f2 00 00 00 f2 f2 f2 f2 f2[02]f2 00 00
0x7fc964b00100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fc964b00180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fc964b00200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fc964b00280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fc964b00300: 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
==1==ABORTING

@EugeneZelenko EugeneZelenko added libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. format C++20 std::format or std::print, and anything related to them and removed new issue labels Aug 26, 2023
@mordante mordante self-assigned this Aug 26, 2023
@mordante mordante added the confirmed Verified by a second party label Aug 26, 2023
@mordante
Copy link
Member

A simpler reproducer https://godbolt.org/z/bfMxfhTx6

#include <format>
int main() {
    (void)std::vformat("{0", std::make_format_args());
}

@mordante
Copy link
Member

Thanks for the bug report. https://reviews.llvm.org/D158940 should fix it.

@mordante
Copy link
Member

The patch has landed and is scheduled to be backported to LLVM 17.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed Verified by a second party format C++20 std::format or std::print, and anything related to them libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

No branches or pull requests

3 participants