Skip to content

BUG: access to deleted memory in array_proxy index #1693

@vakopian

Description

@vakopian

The following code should work:

    array a = constant(1.0f, 3, 5, f32);
    array cond = constant(1, 5, b8);
    auto X = a(span, cond);
    array Y = X;

but it produces the error below:

terminate called after throwing an instance of 'af::exception'
  what():  ArrayFire Exception (Unknown error:208):
In function const ArrayInfo& getInfo(af_array, bool, bool)
In file src/api/c/array.cpp:30
Input Array not created on current device

In function af::array::array_proxy::operator af::array() const
In file src/api/cpp/array.cpp:686

I think this is a bug in the way memory is managed for the af_index_t structure within the array_proxy.
Below is what I think happens:

  1. the array::operator() is called to create the X proxy
  2. the cond array is first converted to a temporary index object (since operator() can only take index)
  3. the index constructor calls where which creates a new array that holds the indices (index.cpp:69)
  4. then the array created by where is copied over into a new array (index.cpp:71), that's used as the arr member of the index (index.cpp:72)
  5. the array::operator() calls gen_indexing array.cpp:350, which then just copies the indices into a local container array.cpp:312-316.

So at this point the pointer to the array allocated in step 4 within a temporary index is copied over into the index of the array_proxy. Then, once we exit the array::operator(), the temporary index is deleted, together with its arr: index.cpp:84. And we end-up with an array_proxy that's holding a dangling pointer in one if its indices. Because the ArrayInfo memory is now freed, it points to bad memory and we get the error above.

This analysis is confirmed by just making the automatic temporary index explicit, i.e. the following code works fine:

    array a = constant(1.0f, 3, 5, f32);
    array cond = constant(1, 5, b8);
    index condIdx = cond; // explicitly create the index to keep it in scope
    auto X = a(span, condIdx);
    array Y = X;

Another way to confirm the problem is to run the first version under valgrind, where I get

==16825== Invalid read of size 1
==16825==    at 0x79DB35F4: ArrayInfo::isSparse() const (ArrayInfo.cpp:172)
==16825==    by 0x79DCAD81: getInfo(void*, bool, bool) (array.cpp:26)
==16825==    by 0x7A00445C: af_index_gen (index.cpp:203)
==16825==    by 0x4ED6E21: af_err unified::AFSymbolManager::call<void**, void*, long long, af_index_t const*>(char const*, void**, void*, long long, af_index_t const*) (symbol_manager.hpp:71)
==16825==    by 0x4ED4782: af_index_gen (index.cpp:44)
==16825==    by 0x4F23879: af::array::array_proxy::operator af::array() const (array.cpp:686)
==16825==    by 0x400ED8: main (ArrayFireTest.cpp:111)
==16825==  Address 0xb5b2fc70 is 80 bytes inside a block of size 160 free'd
==16825==    at 0x4C2F24B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16825==    by 0x79CDF4C2: void cuda::destroyArray<unsigned int>(cuda::Array<unsigned int>*) (Array.cpp:327)
==16825==    by 0x79DD16D1: void releaseHandle<unsigned int>(void*) (handle.hpp:115)
==16825==    by 0x79DCCCEA: af_release_array (array.cpp:216)
==16825==    by 0x4E96E02: af_err unified::AFSymbolManager::call<void*>(char const*, void*) (symbol_manager.hpp:71)
==16825==    by 0x4E8FB66: af_release_array (array.cpp:51)
==16825==    by 0x4FD8839: af::index::~index() (index.cpp:84)
==16825==    by 0x400EA7: main (ArrayFireTest.cpp:110)
==16825==  Block was alloc'd at
==16825==    at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16825==    by 0x79CDF15F: cuda::Array<unsigned int>* cuda::initArray<unsigned int>() (Array.cpp:281)
==16825==    by 0x79DD1816: void* retainHandle<unsigned int>(void*) (array.cpp:238)
==16825==    by 0x79DCD22C: retain(void*) (array.cpp:261)
==16825==    by 0x79DCD512: af_retain_array (array.cpp:278)
==16825==    by 0x4E79E0F: af_err unified::AFSymbolManager::call<void**, void*>(char const*, void**, void*) (symbol_manager.hpp:71)
==16825==    by 0x4E8FE7C: af_retain_array (array.cpp:59)
==16825==    by 0x4FD8570: af::index::index(af::array const&) (index.cpp:71)
==16825==    by 0x400E49: main (ArrayFireTest.cpp:110)

Metadata

Metadata

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions