https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102592
Bug ID: 102592 Summary: heap-use-after-free when constructing std::filesystem::path from iterator pair Product: gcc Version: 11.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: dean.gcc.bugzilla at gmail dot com Target Milestone: --- The std::filesystem::path constructor that takes an iterator pair produces a heap-use-after-free error (address sanitizer) in case the iterators are non-contiguous and value_type != char. Full self-contained reproducible example on Compiler Explorer: https://godbolt.org/z/3nxqq5Ef8 I've also included the reproduction code and error below for completeness. Affected versions: 11.x, trunk Not affected: 10.x As far as I've been able to track this in the std::filesystem::path constructor, for the case of non-contiguous, non-char iterators, a temporary container is created and then assigned to a std::string_view. However that temp container has a shorter lifetime than the std::string_view. The code: #include <filesystem> namespace fs = std::filesystem; fs::path to_path(std::string_view sv) { struct AsU8 { std::string_view::const_iterator it; using iterator_category = std::forward_iterator_tag; using difference_type = std::ptrdiff_t; using value_type = char8_t; using reference = const value_type&; using pointer = const value_type*; char8_t operator*() const { return static_cast<char8_t>(*it); } AsU8& operator++() { return ++it, *this; } bool operator==(const AsU8&) const = default; }; return {AsU8{sv.begin()}, AsU8{sv.end()}}; } int main() { return to_path("/long/path/to/a/file/to/avoid/small/string/opt").string().size(); } =1==ERROR: AddressSanitizer: heap-use-after-free on address 0x604000000010 at pc 0x7fed85f999c0 bp 0x7ffdddc9ccc0 sp 0x7ffdddc9c470 READ of size 46 at 0x604000000010 thread T0 #0 0x7fed85f999bf in __interceptor_memcpy (/opt/compiler-explorer/gcc-11.2.0/lib64/libasan.so.6+0x3c9bf) #1 0x4039e5 in std::char_traits<char>::copy(char*, char const*, unsigned long) /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/char_traits.h:409 #2 0x405214 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_S_copy(char*, char const*, unsigned long) /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:359 #3 0x4058f1 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_S_copy_chars(char*, char const*, char const*) /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:406 #4 0x405109 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*>(char const*, char const*, std::forward_iterator_tag) /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.tcc:225 #5 0x40578b in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct_aux<char const*>(char const*, char const*, std::__false_type) /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:255 #6 0x404a8e in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*>(char const*, char const*) /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:274 #7 0x404119 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, unsigned long, std::allocator<char> const&) /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:521 #8 0x404e66 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::__sv_wrapper, std::allocator<char> const&) /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:154 #9 0x404373 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<std::basic_string_view<char, std::char_traits<char> >, void>(std::basic_string_view<char, std::char_traits<char> > const&, std::allocator<char> const&) /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:664 #10 0x402c63 in path<to_path(std::string_view)::AsU8> /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/fs_path.h:292 #11 0x4024ae in to_path[abi:cxx11](std::basic_string_view<char, std::char_traits<char> >) /app/example.cpp:19 #12 0x40265c in main /app/example.cpp:23 #13 0x7fed85a140b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2) #14 0x40226d in _start (/app/output.s+0x40226d)