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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions