rogersce / cnpy

library to read/write .npy and .npz files in C/C++
MIT License
1.34k stars 301 forks source link

Error with AddressSanitizer (container-overflow) #96

Open TobiasDuswald opened 11 months ago

TobiasDuswald commented 11 months ago

Dear maintainers,

I'm using cnpy in one of my projects to export data from C++ and later process and visualize it with python. I compiled my project with -fsanitize=address and the compiler complains about cnpy::npy_save.

I copied the the first few lines of example 1, i.e., I have the minimal test

TEST(CNPYTest, AddressSanitizer) {
  const int Nx = 128;
  const int Ny = 64;
  const int Nz = 32;
  // set random seed so that result is reproducible (for testing)
  srand(0);
  // create random data
  std::vector<std::complex<double>> data(Nx * Ny * Nz);
  for (int i = 0; i < Nx * Ny * Nz; i++)
    data[i] = std::complex<double>(rand(), rand());

  // save it to file
  cnpy::npy_save("arr1.npy", &data[0], {Nz, Ny, Nx}, "w");
}

Compiled with -fsanitize=address, clang 14.0, macOS 13.4.1, arm64, I get the following error log:

[ RUN      ] CNPYTest.ErrorLog
3: =================================================================
3: ==91626==ERROR: AddressSanitizer: container-overflow on address 0x00010390658d at pc 0x00010195b83c bp 0x00016f876010 sp 0x00016f8757c8
3: READ of size 15 at 0x00010390658d thread T0
3:     #0 0x10195b838 in wrap_memcpy+0x13c (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x17838)
3:     #1 0x10141a8bc in void std::__1::__construct_backward_with_exception_guarantees<std::__1::allocator<char>, char, void>(std::__1::allocator<char>&, char*, char*, char*&)+0x5c (libcnpy.dylib:arm64+0xa8bc)
3:     #2 0x10141ac3c in std::__1::vector<char, std::__1::allocator<char>>::__swap_out_circular_buffer(std::__1::__split_buffer<char, std::__1::allocator<char>&>&)+0x3c (libcnpy.dylib:arm64+0xac3c)
3:     #3 0x101413ad0 in std::__1::vector<char, std::__1::allocator<char>>::reserve(unsigned long)+0x74 (libcnpy.dylib:arm64+0x3ad0)
3:     #4 0x101413a10 in std::__1::vector<char, std::__1::allocator<char>>& cnpy::operator+=<char const*>(std::__1::vector<char, std::__1::allocator<char>>&, char const*)+0x28 (libcnpy.dylib:arm64+0x3a10)
3:     #5 0x1005ab008 in std::__1::vector<char, std::__1::allocator<char>> cnpy::create_npy_header<std::__1::complex<double>>(std::__1::vector<unsigned long, std::__1::allocator<unsigned long>> const&) cnpy.h:242
3:     #6 0x10059329c in void cnpy::npy_save<std::__1::complex<double>>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::complex<double> const*, std::__1::vector<unsigned long, std::__1::allocator<unsigned long>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>) cnpy.h:123
3:     #7 0x100592f20 in CNPYTest_ErrorLog_Test::TestBody() cnpy-test.cpp:81
3:     #8 0x100ce086c in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) gtest.cc:2645
3:     #9 0x100ce0414 in testing::Test::Run() gtest.cc:2684
3:     #10 0x100ce38ac in testing::TestInfo::Run() gtest.cc:2864
3:     #11 0x100ce8398 in testing::TestSuite::Run() gtest.cc:3023
3:     #12 0x100d0b9a4 in testing::internal::UnitTestImpl::RunAllTests() gtest.cc:5885
3:     #13 0x100d0a39c in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) gtest.cc:2645
3:     #14 0x100d09f3c in testing::UnitTest::Run() gtest.cc:5459
3:     #15 0x100609408 in main gtest_main.cc:63
3:     #16 0x194f63f24  (<unknown module>)
3: 
3: 0x000103906596 is located 0 bytes to the right of 22-byte region [0x000103906580,0x000103906596)
3: allocated by thread T0 here:
3:     #0 0x101991ef0 in wrap__Znwm+0x74 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x4def0)
3:     #1 0x1005a5468 in std::__1::__split_buffer<char, std::__1::allocator<char>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<char>&) __split_buffer:315
3:     #2 0x1005a3e88 in std::__1::vector<char, std::__1::allocator<char>>::push_back(char const&) vector:1663
3:     #3 0x1005aaf94 in std::__1::vector<char, std::__1::allocator<char>> cnpy::create_npy_header<std::__1::complex<double>>(std::__1::vector<unsigned long, std::__1::allocator<unsigned long>> const&) cnpy.h:239
3:     #4 0x10059329c in void cnpy::npy_save<std::__1::complex<double>>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::complex<double> const*, std::__1::vector<unsigned long, std::__1::allocator<unsigned long>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>) cnpy.h:123
3:     #5 0x100592f20 in CNPYTest_ErrorLog_Test::TestBody() cnpy-test.cpp:81
3:     #6 0x100ce086c in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) gtest.cc:2645
3:     #7 0x100ce0414 in testing::Test::Run() gtest.cc:2684
3:     #8 0x100ce38ac in testing::TestInfo::Run() gtest.cc:2864
3:     #9 0x100ce8398 in testing::TestSuite::Run() gtest.cc:3023
3:     #10 0x100d0b9a4 in testing::internal::UnitTestImpl::RunAllTests() gtest.cc:5885
3:     #11 0x100d0a39c in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) gtest.cc:2645
3:     #12 0x100d09f3c in testing::UnitTest::Run() gtest.cc:5459
3:     #13 0x100609408 in main gtest_main.cc:63
3:     #14 0x194f63f24  (<unknown module>)
3: 
3: HINT: if you don't care about these errors you may set ASAN_OPTIONS=detect_container_overflow=0.
3: If you suspect a false positive see also: https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow.
3: SUMMARY: AddressSanitizer: container-overflow (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x17838) in wrap_memcpy+0x13c
3: Shadow bytes around the buggy address:
3:   0x007020740c60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
3:   0x007020740c70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
3:   0x007020740c80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
3:   0x007020740c90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
3:   0x007020740ca0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
3: =>0x007020740cb0: 00[05]fc fa fa fa 00 00 00 fa fa fa 00 00 00 fa
3:   0x007020740cc0: fa fa fd fd fd fd fa fa fd fd fd fd fa fa fd fd
3:   0x007020740cd0: fd fd fa fa fd fd fd fd fa fa fd fd fd fd fa fa
3:   0x007020740ce0: fd fd fd fd fa fa fd fd fd fa fa fa fd fd fd fd
3:   0x007020740cf0: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd
3:   0x007020740d00: fd fd fa fa fd fd fd fd fa fa fd fd fd fd fa fa
3: Shadow byte legend (one shadow byte represents 8 application bytes):
3:   Addressable:           00
3:   Partially addressable: 01 02 03 04 05 06 07 
3:   Heap left redzone:       fa
3:   Freed heap region:       fd
3:   Stack left redzone:      f1
3:   Stack mid redzone:       f2
3:   Stack right redzone:     f3
3:   Stack after return:      f5
3:   Stack use after scope:   f8
3:   Global redzone:          f9
3:   Global init order:       f6
3:   Poisoned by user:        f7
3:   Container overflow:      fc
3:   Array cookie:            ac
3:   Intra object redzone:    bb
3:   ASan internal:           fe
3:   Left alloca redzone:     ca
3:   Right alloca redzone:    cb
3: ==91626==ABORTING

Is this a problem?

Kind regards,

Tobias