Skip to content

Instantly share code, notes, and snippets.

@ianloic
Last active March 3, 2020 07:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ianloic/a0c39a34d4b3ea40a86551cd34da432d to your computer and use it in GitHub Desktop.
Save ianloic/a0c39a34d4b3ea40a86551cd34da432d to your computer and use it in GitHub Desktop.
Why is this wrong?
#include <iostream>
#include <string>
#include <vector>
void test_string_vector() {
std::vector<std::string> v;
const char* one = v.emplace_back("one").data();
std::cout << "added one" << std::endl;
std::cout << "v.capacity() = " << v.capacity() << std::endl;
std::cout << "v.front().data() = " << (void*)v.front().data() << std::endl;
const char* two = v.emplace_back("two").data();
std::cout << "added two" << std::endl;
std::cout << "v.capacity() = " << v.capacity() << std::endl;
std::cout << "v.front().data() = " << (void*)v.front().data() << std::endl;
std::cout << "one = " << (void*)one << std::endl;
std::cout << "two = " << (void*)two << std::endl;
std::cout << "one[0] = '" << one[0] << "'" << std::endl;
std::cout << "two[0] = '" << two[0] << "'" << std::endl;
}
int main() {
test_string_vector();
return 0;
}
added one
v.capacity() = 1
v.front().data() = 0x603000000010
added two
v.capacity() = 2
v.front().data() = 0x604000000090
one = 0x603000000010
two = 0x6040000000a8
=================================================================
==19795==ERROR: AddressSanitizer: heap-use-after-free on address 0x603000000010 at pc 0x0000003565cd bp 0x7fffb63d4610 sp 0x7fffb63d4608
READ of size 1 at 0x603000000010 thread T0
#0 0x3565cc in test_string_vector() /usr/local/google/home/ianloic/tmp/crashpants/crashypants.cc:19:32
#1 0x356803 in main /usr/local/google/home/ianloic/tmp/crashpants/crashypants.cc:24:3
#2 0x7f504d7ac2b0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202b0)
#3 0x27b029 in _start (/usr/local/google/home/ianloic/tmp/crashpants/crashypants+0x27b029)
0x603000000010 is located 0 bytes inside of 24-byte region [0x603000000010,0x603000000028)
freed by thread T0 here:
#0 0x353e82 in operator delete(void*) /b/s/w/ir/kitchen-workdir/llvm-project/compiler-rt/lib/asan/asan_new_delete.cc:167:3
#1 0x357b14 in std::__2::_DeallocateCaller::__do_call(void*) /usr/local/google/home/ianloic/fuchsia/buildtools/linux-x64/clang/lib/clang/8.0.0/include/c++/v1/new:320:12
#2 0x357ac8 in std::__2::_DeallocateCaller::__do_deallocate_handle_size(void*, unsigned long) /usr/local/google/home/ianloic/fuchsia/buildtools/linux-x64/clang/lib/clang/8.0.0/include/c++/v1/new:278:12
#3 0x357a54 in std::__2::_DeallocateCaller::__do_deallocate_handle_size_align(void*, unsigned long, unsigned long) /usr/local/google/home/ianloic/fuchsia/buildtools/linux-x64/clang/lib/clang/8.0.0/include/c++/v1/new:254:14
#4 0x3579f4 in std::__2::__libcpp_deallocate(void*, unsigned long, unsigned long) /usr/local/google/home/ianloic/fuchsia/buildtools/linux-x64/clang/lib/clang/8.0.0/include/c++/v1/new:326:3
#5 0x3579ad in std::__2::allocator<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> > >::deallocate(std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> >*, unsigned long) /usr/local/google/home/ianloic/fuchsia/buildtools/linux-x64/clang/lib/clang/8.0.0/include/c++/v1/memory:1803:10
#6 0x357634 in std::__2::allocator_traits<std::__2::allocator<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> > > >::deallocate(std::__2::allocator<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> > >&, std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> >*, unsigned long) /usr/local/google/home/ianloic/fuchsia/buildtools/linux-x64/clang/lib/clang/8.0.0/include/c++/v1/memory:1557:14
#7 0x358e5c in std::__2::__split_buffer<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> >, std::__2::allocator<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> > >&>::~__split_buffer() /usr/local/google/home/ianloic/fuchsia/buildtools/linux-x64/clang/lib/clang/8.0.0/include/c++/v1/__split_buffer:343:9
#8 0x3581ad in void std::__2::vector<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> >, std::__2::allocator<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> > > >::__emplace_back_slow_path<char const (&) [4]>(char const (&) [4]) /usr/local/google/home/ianloic/fuchsia/buildtools/linux-x64/clang/lib/clang/8.0.0/include/c++/v1/vector:1668:1
#9 0x356b2f in std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> >& std::__2::vector<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> >, std::__2::allocator<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> > > >::emplace_back<char const (&) [4]>(char const (&) [4]) /usr/local/google/home/ianloic/fuchsia/buildtools/linux-x64/clang/lib/clang/8.0.0/include/c++/v1/vector:1690:9
#10 0x356397 in test_string_vector() /usr/local/google/home/ianloic/tmp/crashpants/crashypants.cc:12:23
#11 0x356803 in main /usr/local/google/home/ianloic/tmp/crashpants/crashypants.cc:24:3
#12 0x7f504d7ac2b0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202b0)
previously allocated by thread T0 here:
#0 0x353242 in operator new(unsigned long) /b/s/w/ir/kitchen-workdir/llvm-project/compiler-rt/lib/asan/asan_new_delete.cc:106:3
#1 0x35990c in std::__2::__libcpp_allocate(unsigned long, unsigned long) /usr/local/google/home/ianloic/fuchsia/buildtools/linux-x64/clang/lib/clang/8.0.0/include/c++/v1/new:239:10
#2 0x359834 in std::__2::allocator<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> > >::allocate(unsigned long, void const*) /usr/local/google/home/ianloic/fuchsia/buildtools/linux-x64/clang/lib/clang/8.0.0/include/c++/v1/memory:1800:37
#3 0x359720 in std::__2::allocator_traits<std::__2::allocator<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> > > >::allocate(std::__2::allocator<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> > >&, unsigned long) /usr/local/google/home/ianloic/fuchsia/buildtools/linux-x64/clang/lib/clang/8.0.0/include/c++/v1/memory:1549:21
#4 0x358a91 in std::__2::__split_buffer<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> >, std::__2::allocator<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> > >&>::__split_buffer(unsigned long, unsigned long, std::__2::allocator<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> > >&) /usr/local/google/home/ianloic/fuchsia/buildtools/linux-x64/clang/lib/clang/8.0.0/include/c++/v1/__split_buffer:311:29
#5 0x3580f6 in void std::__2::vector<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> >, std::__2::allocator<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> > > >::__emplace_back_slow_path<char const (&) [4]>(char const (&) [4]) /usr/local/google/home/ianloic/fuchsia/buildtools/linux-x64/clang/lib/clang/8.0.0/include/c++/v1/vector:1663:49
#6 0x356b2f in std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> >& std::__2::vector<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> >, std::__2::allocator<std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char> > > >::emplace_back<char const (&) [4]>(char const (&) [4]) /usr/local/google/home/ianloic/fuchsia/buildtools/linux-x64/clang/lib/clang/8.0.0/include/c++/v1/vector:1690:9
#7 0x356259 in test_string_vector() /usr/local/google/home/ianloic/tmp/crashpants/crashypants.cc:8:23
#8 0x356803 in main /usr/local/google/home/ianloic/tmp/crashpants/crashypants.cc:24:3
#9 0x7f504d7ac2b0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202b0)
SUMMARY: AddressSanitizer: heap-use-after-free /usr/local/google/home/ianloic/tmp/crashpants/crashypants.cc:19:32 in test_string_vector()
Shadow bytes around the buggy address:
0x0c067fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c067fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c067fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c067fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c067fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c067fff8000: fa fa[fd]fd fd fa fa fa fa fa fa fa fa fa fa fa
0x0c067fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c067fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c067fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c067fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c067fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
Shadow gap: cc
==19795==ABORTING
@gmoryes
Copy link

gmoryes commented Mar 3, 2020

Maybe because after second emplace_back memory was reallocated and one is looking to freed memory. Consider using v.reserve(2) before emplace_back

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment