Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

memcpy buffer overflow: load_construct_data() and std::complex members #2839

Closed
krivenko opened this issue Aug 16, 2017 · 2 comments · Fixed by #2841
Closed

memcpy buffer overflow: load_construct_data() and std::complex members #2839

krivenko opened this issue Aug 16, 2017 · 2 comments · Fixed by #2841

Comments

@krivenko
Copy link

I get a weird compilation warning and a subsequent runtime failure (buffer overflow) from the following code:

#include <complex>
#include <iostream>

#include <hpx/runtime/serialization/complex.hpp>
#include <hpx/runtime/serialization/vector.hpp>

struct my_struct {

    using x_type = std::complex<double>;

    my_struct() = delete;
    my_struct(x_type x) : x(x) {}

    bool operator==(my_struct const& ms) const { return x == ms.x; }

    x_type x;

    /// HPX.Serialization
    template<typename Archive>
    inline void serialize(Archive & ar, const unsigned int) {
        ar & x;
    }
    template <class Archive>
    inline void friend load_construct_data(Archive & ar, my_struct* b, const unsigned int) {
        ::new(b) my_struct(0);
    }
};

int main(int argc, char **argv) {

    std::vector<char> buf;

    // Serialize
    std::vector<my_struct> in;
    in.push_back(my_struct(1.0));
    in.push_back(my_struct(2.0));
    hpx::serialization::output_archive oa(buf);
    oa << in;

    // Deserialize
    std::vector<my_struct> out;
    hpx::serialization::input_archive ia(buf);
    ia >> out;

    if(!(in == out)) {
        std::cout << "Serialization failure" << std::endl;
        return -1;
    }
    return 0;
}

The warning reads

/usr/include/bits/string3.h:53:71: warning: call to void* __builtin___memcpy_chk(void*, const void*, long unsigned int, long unsigned int) will always overflow destination buffer
   return __builtin___memcpy_chk (__dest, __src, __len, __bos0 (__dest));

valgrind reveals the point of the failure to be in serialization_access_data.hpp:159

**14384** *** memcpy_chk: buffer overflow detected ***: program terminated
==14384==    at 0x4C2EB04: VALGRIND_PRINTF_BACKTRACE (valgrind.h:6818)
==14384==    by 0x4C3363A: __memcpy_chk (vg_replace_strmem.c:1574)
==14384==    by 0x404D33: memcpy (string3.h:53)
==14384==    by 0x404D33: read (serialization_access_data.hpp:159)
==14384==    by 0x404D33: load_binary (input_container.hpp:107)
==14384==    by 0x404D33: load_binary (input_archive.hpp:243)
==14384==    by 0x404D33: load_bitwise<std::complex<double> > (input_archive.hpp:156)
==14384==    by 0x404D33: load<std::complex<double> > (input_archive.hpp:89)
==14384==    by 0x404D33: invoke_impl<std::complex<double> > (input_archive.hpp:78)
==14384==    by 0x404D33: invoke<std::complex<double> > (basic_archive.hpp:66)
==14384==    by 0x404D33: operator&<std::complex<double> > (serialize.hpp:43)
==14384==    by 0x404D33: serialize<hpx::serialization::input_archive> (hpx_bug.cpp:21)
==14384==    by 0x404D33: call<hpx::serialization::input_archive> (access.hpp:88)
==14384==    by 0x404D33: serialize<hpx::serialization::input_archive, my_struct> (access.hpp:113)
==14384==    by 0x404D33: load_nonintrusively_polymorphic<my_struct> (input_archive.hpp:163)
==14384==    by 0x404D33: load_bitwise<my_struct> (input_archive.hpp:141)
==14384==    by 0x404D33: load<my_struct> (input_archive.hpp:89)
==14384==    by 0x404D33: invoke_impl<my_struct> (input_archive.hpp:78)
==14384==    by 0x404D33: invoke<my_struct> (basic_archive.hpp:66)
==14384==    by 0x404D33: operator>><my_struct> (serialize.hpp:29)
==14384==    by 0x404D33: call<hpx::serialization::input_archive, std::vector<my_struct> > (serialize_collection.hpp:100)
==14384==    by 0x404D33: load_collection<hpx::serialization::input_archive, std::vector<my_struct> > (serialize_collection.hpp:124)
==14384==    by 0x404D33: load_impl<my_struct, std::allocator<my_struct> > (vector.hpp:34)
==14384==    by 0x404D33: serialize<my_struct, std::allocator<my_struct> > (vector.hpp:88)
==14384==    by 0x404D33: serialize_force_adl<std::vector<my_struct> > (access.hpp:33)
==14384==    by 0x404D33: call<hpx::serialization::input_archive> (access.hpp:69)
==14384==    by 0x404D33: serialize<hpx::serialization::input_archive, std::vector<my_struct> > (access.hpp:113)
==14384==    by 0x404D33: load_nonintrusively_polymorphic<std::vector<my_struct> > (input_archive.hpp:163)
==14384==    by 0x404D33: load_bitwise<std::vector<my_struct> > (input_archive.hpp:141)
==14384==    by 0x404D33: load<std::vector<my_struct> > (input_archive.hpp:89)
==14384==    by 0x404D33: invoke_impl<std::vector<my_struct> > (input_archive.hpp:78)
==14384==    by 0x404D33: invoke<std::vector<my_struct> > (basic_archive.hpp:66)
==14384==    by 0x404D33: operator>><std::vector<my_struct> > (serialize.hpp:29)
==14384==    by 0x404D33: main (hpx_bug.cpp:43)

The most interesting part here is that if I change x_type to double, the program compiles and runs perfectly.

@hkaiser
Copy link
Member

hkaiser commented Aug 16, 2017

@krivenko this looks like it is unrelated to the struct my_struct not being default constructible. Is this happening also if you allow for it to have a default constructor?

I have no explanation for this yet and I'm not able to reproduce this on my platform (Windows/MSVC).

The problem occurs during deserialization of an instance of type std::complex. We treat std::complex as bitwise-serializable, which is the only thing 'special' about this type. Does the problem occur if you comment out these lines: https://github.com/STEllAR-GROUP/hpx/blob/master/hpx/runtime/serialization/complex.hpp#L33-L39?

@krivenko
Copy link
Author

Is this happening also if you allow for it to have a default constructor?

No, with my_struct() = default the problem disappears.

I have no explanation for this yet and I'm not able to reproduce this on my platform (Windows/MSVC).

My compiler is GCC 5.4.0 on Linux.

Does the problem occur if you comment out these lines: https://github.com/STEllAR-GROUP/hpx/blob/master/hpx/runtime/serialization/complex.hpp#L33-L39?

With those lines commented out the crash does not occur.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants