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

Strings of integers over 2^63-1 gets encoded as float64 instead of uint64

Open aesy opened this issue 7 years ago • 0 comments

The problem lies in the following code:

https://github.com/msgpack/msgpack-java/blob/87d38a08dcd23ca67aff61ab05f4a18888055b7e/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java#L437-L477

I will provide an example. Take the following input: "9223372036854775808" (2^63) Since Javas Long type max value is 2^63-1, the first try will fail, continuing to the next try. Double will succeed resulting in the input being encoded as a float64. As a user of the library I would've assumed that the input got encoded as a uint64.

I'm not sure, but it may also be a problem that integers can silently lose precision. I think an IllegalArgumentException would've been preferred in that case, unless there are decimals in the number (even if just a trailing zero).

Double#parseDouble will succeed to parse all integers, although integers past Double.MAX_VALUE will yield Infinity, so the try to parse BigInteger will either never be reached or never succeed for any input.

Unless I'm mistaken, these issues could be solved by swapping the ordering of the parse tries, placing BigInteger before Double, and in that case I don't think it's even necessary to try parse Long and Double rather than just BigInteger and BigDecimal. Maybe it's less performant?

I realize that the other writeNumber methods are preferred over this one. I'm using a library that has a dependency on this library (dd-trace-java) where the same assumption that a string of a 64-bit integer would be encoded as a uint64 was made.

I will make a pull request shortly.

aesy avatar Oct 15 '18 21:10 aesy