GrzegDev
GrzegDev

Reputation: 135

gcc address sanitizer heap-buffer-overflow error during sort caused by change of condition?

This is the bare-bone version of my function which illustrates the error. File runtime-error.cpp:

#include <vector>
#include <algorithm>
using namespace std;

int main() {
  using vi = vector<int>;
  vector<vi> result = {{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
                       {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
                       {0}, {0}, {0}, {0}, {0}, {2}, {2}, {2}, {2}, {2},
                       {2}, {2}, {2}, {2}, {2}, {2}, {2}, {2}, {2}, {2},
                       {2}, {2}, {2}, {2}, {2}};

  sort(result.begin(), result.end(), [](const vi& v1, const vi& v2) {
                                       const auto v10 = v1[0];
                                       const auto v20 = v2[0];    // line 15
                                       return (v10 <= v20);       // error condition
                                       // return (v10 < v20);     // no error condition
                                     });
  return 0;
}

I build it and run it with the following command:

g++ -Wall -g -fsanitize=address -fno-omit-frame-pointer runtime-error.cpp -o re && ./re

gcc version:

gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)

if the //no error condition is used, no problem. but as it is, the following error occurs:

==4046513==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x619000000068 at pc 0x55dec650f945 bp 0x7ffc95746530 sp 0x7ffc95746520
READ of size 8 at 0x619000000068 thread T0
    #0 0x55dec650f944 in std::vector<int, std::allocator<int> >::operator[](unsigned long) const /usr/include/c++/9/bits/stl_vector.h:1061
    #1 0x55dec650851e in operator() ./runtime-error.cpp:15
    #2 0x55dec650d424 in operator()<__gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int> > >, __gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int> > > > /usr/include/c++/9/bits/predefined_ops.h:143
    #3 0x55dec650d8c1 in __unguarded_partition<__gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int> > >, __gnu_cxx::__ops::_Iter_comp_iter<main()::<lambda(const vi&, const vi&)> > > /usr/include/c++/9/bits/stl_algo.h:1910
    #4 0x55dec650c8ed in __unguarded_partition_pivot<__gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int> > >, __gnu_cxx::__ops::_Iter_comp_iter<main()::<lambda(const vi&, const vi&)> > > /usr/include/c++/9/bits/stl_algo.h:1928
    #5 0x55dec650c311 in __introsort_loop<__gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int> > >, long int, __gnu_cxx::__ops::_Iter_comp_iter<main()::<lambda(const vi&, const vi&)> > > /usr/include/c++/9/bits/stl_algo.h:1958
    #6 0x55dec650c011 in __sort<__gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int> > >, __gnu_cxx::__ops::_Iter_comp_iter<main()::<lambda(const vi&, const vi&)> > > /usr/include/c++/9/bits/stl_algo.h:1973
    #7 0x55dec650bd55 in sort<__gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int> > >, main()::<lambda(const vi&, const vi&)> > /usr/include/c++/9/bits/stl_algo.h:4905
    #8 0x55dec650aec7 in main ./runtime-error.cpp:13
    #9 0x7f42966df082 in __libc_start_main ../csu/libc-start.c:308
    #10 0x55dec65083ed in _start (./re+0x13ed)

0x619000000068 is located 24 bytes to the left of 1080-byte region [0x619000000080,0x6190000004b8)
allocated by thread T0 here:
    #0 0x7f4296d08587 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cc:104
    #1 0x55dec65113bf in __gnu_cxx::new_allocator<std::vector<int, std::allocator<int> > >::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
    #2 0x55dec6510f2e in std::allocator_traits<std::allocator<std::vector<int, std::allocator<int> > > >::allocate(std::allocator<std::vector<int, std::allocator<int> > >&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:443
    #3 0x55dec6510749 in std::_Vector_base<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >::_M_allocate(unsigned long) /usr/include/c++/9/bits/stl_vector.h:343
    #4 0x55dec650fe40 in void std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >::_M_range_initialize<std::vector<int, std::allocator<int> > const*>(std::vector<int, std::allocator<int> > const*, std::vector<int, std::allocator<int> > const*, std::forward_iterator_tag) /usr/include/c++/9/bits/stl_vector.h:1579
    #5 0x55dec650f588 in std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >::vector(std::initializer_list<std::vector<int, std::allocator<int> > >, std::allocator<std::vector<int, std::allocator<int> > > const&) /usr/include/c++/9/bits/stl_vector.h:626
    #6 0x55dec650a47a in main ./runtime-error.cpp:11
    #7 0x7f42966df082 in __libc_start_main ../csu/libc-start.c:308

SUMMARY: AddressSanitizer: heap-buffer-overflow /usr/include/c++/9/bits/stl_vector.h:1061 in std::vector<int, std::allocator<int> >::operator[](unsigned long) const
Shadow bytes around the buggy address:
  0x0c327fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c327fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c327fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c327fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c327fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c327fff8000: fa fa fa fa fa fa fa fa fa fa fa fa fa[fa]fa fa
  0x0c327fff8010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c327fff8020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c327fff8030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c327fff8040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c327fff8050: 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
  Shadow gap:              cc
==4046513==ABORTING

Upvotes: 1

Views: 411

Answers (1)

A. K.
A. K.

Reputation: 38098

<= does not conform to the semantics of strict partial ordering while < does.

Upvotes: 1

Related Questions