Skip Menu |

This queue is for tickets about the Data-MessagePack-Stream CPAN distribution.

Report information
The Basics
Id: 98134
Status: new
Priority: 0/
Queue: Data-MessagePack-Stream

People
Owner: Nobody in particular
Requestors: GRUBER [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 0.07
Fixed in: (no value)



Subject: Make the module not truncate large integers on perls with 32-bit ints
Currently, if the stream is fed a large integer (or a large uint), the module silently truncates the integer to fit in 32 bits (of course, this only happens on perls with 32-bit integeres). Of many ways of solving this issue, the current behavior is probably the worst. The attached patch creates a Math::BigInt object in such instances. I am not sure that this is the best possible solution, but it certainly better than the current behavior. This only affects the unpacker. I hope you can find time to make a new release incorporating the fix. If you do not have time, but in principle do not object to the fix, I'd like to offer to become a co-maintainer of the module so that the release can be made. Thanks, \Anton.
Subject: dms.patch
diff -ruN ../Data-MessagePack-Stream-0.07/lib/Data/MessagePack/Stream.pm ./lib/Data/MessagePack/Stream.pm --- lib/Data/MessagePack/Stream.pm 2012-07-25 03:22:13.000000000 +0200 +++ lib/Data/MessagePack/Stream.pm 2014-08-13 15:43:35.000000000 +0200 @@ -2,6 +2,7 @@ use strict; use warnings; use XSLoader; +use Math::BigInt; our $VERSION = '0.07'; diff -ruN ../Data-MessagePack-Stream-0.07/src/Data-MessagePack-Stream.xs ./src/Data-MessagePack-Stream.xs --- src/Data-MessagePack-Stream.xs 2012-07-25 03:14:01.000000000 +0200 +++ src/Data-MessagePack-Stream.xs 2014-08-18 12:48:30.000000000 +0200 @@ -16,6 +16,21 @@ msgpack_unpacked result; }; +static SV* bigint_object_from_string(const char *s) +{ + dSP; + + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSVpv("Math::BigInt", 0))); + XPUSHs(sv_2mortal(newSVpv(s, 0))); + PUTBACK; + + call_method("new", G_SCALAR); + + SPAGAIN; + return SvREFCNT_inc(POPs); +} + static SV* decode_msgpack_object(msgpack_object* obj) { SV* res = NULL; AV* av; @@ -33,10 +48,24 @@ res = newSViv(obj->via.boolean); break; case MSGPACK_OBJECT_POSITIVE_INTEGER: - res = newSVuv(obj->via.u64); + if (sizeof(UV) < 8 && obj->via.u64 > 4294967295ull) { + char s[40]; + + snprintf(s, 40, "%"PRIu64, obj->via.u64); + res = bigint_object_from_string(s); + } else { + res = newSVuv(obj->via.u64); + } break; case MSGPACK_OBJECT_NEGATIVE_INTEGER: - res = newSViv(obj->via.i64); + if (sizeof(IV) < 8 && (obj->via.i64 > 2147483647ll || obj->via.i64 < -2147483648ll)) { + char s[40]; + + snprintf(s, 40, "%"PRId64, obj->via.i64); + res = bigint_object_from_string(s); + } else { + res = newSViv(obj->via.i64); + } break; case MSGPACK_OBJECT_DOUBLE: res = newSVnv(obj->via.dec); diff -ruN ../Data-MessagePack-Stream-0.07/t/bug-bigint.t ./t/bug-bigint.t --- t/bug-bigint.t 1970-01-01 01:00:00.000000000 +0100 +++ t/bug-bigint.t 2014-08-18 12:48:40.000000000 +0200 @@ -0,0 +1,18 @@ +use Test::More; + +plan tests => 2; +use Data::MessagePack::Stream; + +my $stream = Data::MessagePack::Stream->new; +$stream->feed("\xCF\x00\x01\x56\x7C\xC1\xD6\xE4\xE2"); +while ($stream->next) { + my $data = $stream->data; + ok("376568804730082" eq $data, "bigint unsigned works"); +} + +$stream = Data::MessagePack::Stream->new; +$stream->feed("\xd3\xff\xfe\x7a\xd5\x18\x52\x6f\xfb"); +while ($stream->next) { + my $data = $stream->data; + ok("-427894298742789" eq $data, "bigint signed works"); +}