msgpack-c icon indicating copy to clipboard operation
msgpack-c copied to clipboard

std::bad:cast when deserializing nested msgpack::object

Open Shin-nn opened this issue 6 years ago • 2 comments

We are currently having problem with deserializing nested msgpack::object in serialized class. The code below is minimum example I could think of. In our use case we send data over TCP/IP, detect what type of message we received and de-serialize it.

struct MSGA {
    std::string string{};

    MSGPACK_DEFINE_MAP(string)
};

enum class MsgType {
    A
};

MSGPACK_ADD_ENUM(MsgType)

struct Message {
    MsgType type{};
    msgpack::object payload{};

    MSGPACK_DEFINE_MAP(type,payload)
};

std::string msgPackToString(const std::string& recievedData) {
    std::stringstream stream;
    for(const auto& x : recievedData) {
        stream << std::hex << static_cast<unsigned int>(x) << " ";
    }
    return stream.str();
}
void process(const std::string& recievedData) {
    std::cout << "Data: " <<  recievedData << std::endl;
    std::cout << "Data as hex: " <<  msgPackToString(recievedData) << std::endl;

    msgpack::unpacker unpacker{};
    unpacker.reserve_buffer(recievedData.size());
    std::copy_n(recievedData.data(), recievedData.size(), unpacker.buffer());
    unpacker.buffer_consumed(static_cast<size_t>(recievedData.size()));

    msgpack::object_handle result;

    while (unpacker.next(result)) {

        msgpack::sbuffer messageBuffer;
        msgpack::pack(messageBuffer, *result);

        std::cout << "Packed again: " << std::string{messageBuffer.data(), messageBuffer.size()} << std::endl;
        std::cout << "Packed again as hex: " << msgPackToString(std::string{messageBuffer.data(), messageBuffer.size()}) << std::endl;
        try {
            auto msg = result->as<Message>();
            if(msg.type == MsgType::A) {
                auto msgA = msg.payload.as<MSGA>();
            }

        } catch (const std::bad_cast & except) {
            std::cerr << "BAD CAST" << std::endl;
        }
    }
}

int test () {
    MSGA msgA{"serialized"};
    Message messageToSend{};
    msgpack::zone z;
    messageToSend.payload = msgpack::object(msgA, z);
    messageToSend.type = MsgType::A;

    msgpack::sbuffer messageBuffer;
    msgpack::pack(messageBuffer, messageToSend);

    std::string stringToSend{messageBuffer.data(), messageBuffer.size()};

    process(stringToSend);
}

The code above fails on bad cast with this output:

Data: ��type �payload��string�serialized Data as hex: ffffff82 ffffffa4 74 79 70 65 0 ffffffa7 70 61 79 6c 6f 61 64 ffffff91 ffffffa6 73 74 72 69 6e 67 ffffffaa 73 65 72 69 61 6c 69 7a 65 64 BAD CAST Packed again: ��type �payload��string Packed again as hex: ffffff92 ffffffa4 74 79 70 65 0 ffffffa7 70 61 79 6c 6f 61 64 ffffff91 ffffffa6 73 74 72 69 6e 67 Packed again: �serialized Packed again as hex: ffffffaa 73 65 72 69 61 6c 69 7a 65 64 BAD CAST

It looks like it does not deserialize map correctly. Can you help us? Let me know, if you need any help. Thank you!

Shin-nn avatar Apr 10 '19 10:04 Shin-nn

I copied and pasted your code then added required include files, replaced test with main, and print msgpack-c version.

Here is the code: https://wandbox.org/permlink/O4K7A0HnafE0Rkqr

BAD CAST isn't output.

redboltz avatar Apr 10 '19 12:04 redboltz

I just tried that with your code : 3.0.1 Data: ��type �payload��string�serialized Data as hex: ffffff82 ffffffa4 74 79 70 65 0 ffffffa7 70 61 79 6c 6f 61 64 ffffff91 ffffffa6 73 74 72 69 6e 67 ffffffaa 73 65 72 69 61 6c 69 7a 65 64 Packed again: ��type �payload��string Packed again as hex: ffffff92 ffffffa4 74 79 70 65 0 ffffffa7 70 61 79 6c 6f 61 64 ffffff91 ffffffa6 73 74 72 69 6e 67 Packed again: �serialized Packed again as hex: ffffffaa 73 65 72 69 61 6c 69 7a 65 64

I will try to update to newer version. Thanks for help.

Shin-nn avatar Apr 10 '19 19:04 Shin-nn