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