[Bug libstdc++/102592] New: heap-use-after-free when constructing std::filesystem::path from iterator pair
dean.gcc.bugzilla at gmail dot com
gcc-bugzilla@gcc.gnu.org
Mon Oct 4 12:54:55 GMT 2021
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)
More information about the Gcc-bugs
mailing list