Skip to content

Packed and unpacked types are not the same when using msgpack::type::variant. #1070

@aint-no-programmer

Description

@aint-no-programmer

Problem appears when using msgpack::type::variant serialization for float number with zero decimal part.
Here motivation example:

# include <msgpack.hpp>
# include <cassert>

int main() {
	msgpack::type::variant val(212.f);
	std::stringstream ss;
	msgpack::pack(ss, val);

	auto unpacked = msgpack::unpack(ss.str().data(), ss.str().size());
	auto obj = unpacked.get();
	msgpack::type::variant restored_val;
	obj.convert(restored_val);

	assert(val == restored_val);//failed here
}

The reason for the failed assert is different types of variant’s values.
There are float type of val and uint64 type of the restored_val
I’ve found out that positive float number with zero decimal part is stored as uint64, hence when it is deserialized, it turns into an uint64 number.

As I know, it happens in line 1165 of msgpack/v1/pack.hpp, here:

template <typename Stream>
inline packer<Stream>& packer<Stream>::pack_double(double d)
{
    if(d == d) { // check for nan
        // compare d to limits to avoid undefined behaviour
        if(d >= 0 && d <= double(std::numeric_limits<uint64_t>::max()) && d == double(uint64_t(d))) {
            pack_imp_uint64(uint64_t(d));
            return *this;
        } else if(d < 0 && d >= double(std::numeric_limits<int64_t>::min()) && d == double(int64_t(d))) {
            pack_imp_int64(int64_t(d));
            return *this;
        }
    }
    //other code

Here https://gist.github.com/redboltz/672c5af16b2907488977 same problem.

Thank you for response.

msgpack version: 6.0.0
OS: Windows 10

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions