Skip to content

[backend_cpu] Heap buffer overflow

What commit version of aidge do you use

  • aidge_backend_cpu: 0.2.0 (dev)

Problem description

While running the tests with ASAN I found a heap buffer overflow bug. The issue isn't critical as it doesn't impairs the tests results but it still is a potential instability.

ASAN output

 6/32 Test  #6: [cpu/operator] Conv(forward) ......................   Passed    0.01 sec
      Start  7: [cpu/operator] Div
 7/32 Test  #7: [cpu/operator] Div ................................***Failed    0.19 sec
Filters: \[cpu/operator\] Div
Randomness seeded to: 4085358928
number of elements over time spent: 72.3167
total time: 60μs
number of elements over time spent: 22.1143
total time: 245μs
=================================================================
==24169==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60300001bcf8 at pc 0x563c66b68bc3 bp 0x7ffd530c7a30 sp 0x7ffd530c7a20
READ of size 8 at 0x60300001bcf8 thread T0
    #0 0x563c66b68bc2 in Aidge::DivImpl_cpu::forward() /home/greg/workspace/cea/aidge/aidge/aidge_backend_cpu/src/operator/DivImpl.cpp:101
    #1 0x563c66c4b868 in Aidge::Operator::forward() /home/greg/workspace/cea/aidge/aidge/aidge_core/src/operator/Operator.cpp:56
    #2 0x563c66c32e43 in Aidge::Node::forward() /home/greg/workspace/cea/aidge/aidge/aidge_core/src/graph/Node.cpp:68
    #3 0x563c66a64686 in CATCH2_INTERNAL_TEST_0 /home/greg/workspace/cea/aidge/aidge/aidge_backend_cpu/unit_tests/operator/Test_DivImpl.cpp:296
    #4 0x563c66d1d153 in Catch::TestInvokerAsFunction::invoke() const src/catch2/internal/catch_test_case_registry_impl.cpp:149
    #5 0x563c66cfb5e4 in Catch::TestCaseHandle::invoke() const (/home/greg/workspace/cea/aidge/aidge/aidge_backend_cpu/build_bundle_cpp/unit_tests/tests_aidge_backend_cpu+0x3a95e4)
    #6 0x563c66cfa76f in Catch::RunContext::invokeActiveTestCase() src/catch2/internal/catch_run_context.cpp:503
    #7 0x563c66cfa4a9 in Catch::RunContext::runCurrentTest(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) src/catch2/internal/catch_run_context.cpp:473
    #8 0x563c66cf8d92 in Catch::RunContext::runTest(Catch::TestCaseHandle const&) src/catch2/internal/catch_run_context.cpp:238
    #9 0x563c66d03ae1 in execute src/catch2/catch_session.cpp:112
    #10 0x563c66d04f21 in Catch::Session::runInternal() src/catch2/catch_session.cpp:334
    #11 0x563c66d04a3a in Catch::Session::run() src/catch2/catch_session.cpp:265
    #12 0x563c66c0a288 in int Catch::Session::run<char>(int, char const* const*) src/catch2/../catch2/catch_session.hpp:41
    #13 0x563c66c0a176 in main src/catch2/internal/catch_main.cpp:36
    #14 0x7f0830696082 in __libc_start_main ../csu/libc-start.c:308
    #15 0x563c669bb2ad in _start (/home/greg/workspace/cea/aidge/aidge/aidge_backend_cpu/build_bundle_cpp/unit_tests/tests_aidge_backend_cpu+0x692ad)

0x60300001bcf8 is located 8 bytes to the left of 32-byte region [0x60300001bd00,0x60300001bd20)
allocated by thread T0 here:
    #0 0x7f0830cbf587 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cc:104
    #1 0x563c669f7081 in __gnu_cxx::new_allocator<unsigned long>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
    #2 0x563c669eb397 in std::allocator_traits<std::allocator<unsigned long> >::allocate(std::allocator<unsigned long>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:443
    #3 0x563c669de051 in std::_Vector_base<unsigned long, std::allocator<unsigned long> >::_M_allocate(unsigned long) /usr/include/c++/9/bits/stl_vector.h:343
    #4 0x563c66a66fa1 in std::vector<unsigned long, std::allocator<unsigned long> >::_M_fill_insert(__gnu_cxx::__normal_iterator<unsigned long*, std::vector<unsigned long, std::allocator<unsigned long> > >, unsigned long, unsigned long const&) /usr/include/c++/9/bits/vector.tcc:561
    #5 0x563c66a65f77 in std::vector<unsigned long, std::allocator<unsigned long> >::insert(__gnu_cxx::__normal_iterator<unsigned long const*, std::vector<unsigned long, std::allocator<unsigned long> > >, unsigned long, unsigned long const&) /usr/include/c++/9/bits/stl_vector.h:1335
    #6 0x563c66b68917 in Aidge::DivImpl_cpu::forward() /home/greg/workspace/cea/aidge/aidge/aidge_backend_cpu/src/operator/DivImpl.cpp:82
    #7 0x563c66c4b868 in Aidge::Operator::forward() /home/greg/workspace/cea/aidge/aidge/aidge_core/src/operator/Operator.cpp:56
    #8 0x563c66c32e43 in Aidge::Node::forward() /home/greg/workspace/cea/aidge/aidge/aidge_core/src/graph/Node.cpp:68
    #9 0x563c66a64686 in CATCH2_INTERNAL_TEST_0 /home/greg/workspace/cea/aidge/aidge/aidge_backend_cpu/unit_tests/operator/Test_DivImpl.cpp:296
    #10 0x563c66d1d153 in Catch::TestInvokerAsFunction::invoke() const src/catch2/internal/catch_test_case_registry_impl.cpp:149
    #11 0x563c66cfb5e4 in Catch::TestCaseHandle::invoke() const (/home/greg/workspace/cea/aidge/aidge/aidge_backend_cpu/build_bundle_cpp/unit_tests/tests_aidge_backend_cpu+0x3a95e4)
    #12 0x563c66cfa76f in Catch::RunContext::invokeActiveTestCase() src/catch2/internal/catch_run_context.cpp:503
    #13 0x563c66cfa4a9 in Catch::RunContext::runCurrentTest(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) src/catch2/internal/catch_run_context.cpp:473
    #14 0x563c66cf8d92 in Catch::RunContext::runTest(Catch::TestCaseHandle const&) src/catch2/internal/catch_run_context.cpp:238
    #15 0x563c66d03ae1 in execute src/catch2/catch_session.cpp:112
    #16 0x563c66d04f21 in Catch::Session::runInternal() src/catch2/catch_session.cpp:334
    #17 0x563c66d04a3a in Catch::Session::run() src/catch2/catch_session.cpp:265
    #18 0x563c66c0a288 in int Catch::Session::run<char>(int, char const* const*) src/catch2/../catch2/catch_session.hpp:41
    #19 0x563c66c0a176 in main src/catch2/internal/catch_main.cpp:36
    #20 0x7f0830696082 in __libc_start_main ../csu/libc-start.c:308

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/greg/workspace/cea/aidge/aidge/aidge_backend_cpu/src/operator/DivImpl.cpp:101 in Aidge::DivImpl_cpu::forward()
Shadow bytes around the buggy address:
  0x0c067fffb740: 00 00 00 00 fa fa 00 00 00 00 fa fa fd fd fd fd
  0x0c067fffb750: fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa fd fd
  0x0c067fffb760: fd fd fa fa fd fd fd fd fa fa 00 00 00 00 fa fa
  0x0c067fffb770: 00 00 00 00 fa fa fd fd fd fd fa fa fd fd fd fd
  0x0c067fffb780: fa fa fd fd fd fd fa fa 00 00 00 00 fa fa 00 00
=>0x0c067fffb790: 00 00 fa fa fd fd fd fd fa fa 00 00 00 00 fa[fa]
  0x0c067fffb7a0: 00 00 00 00 fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffb7b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffb7c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffb7d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffb7e0: 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
==24169==ABORTING

Reproducible example code

This bug can only be reproduced on my branch for now as I have added asan support for backend_cpu there. Branch : feat/operator_globalAveragePooling To do so, go in the cmakelists.txt and add the following line just before the "ASAN" block

set(ENABLE_ASAN ON)

Then run the tests :

./setup.sh -m backend_cpu -t
Edited by Maxence Naud