--- CBOR-XS/XS.pm 2016/04/25 18:20:22 1.53 +++ CBOR-XS/XS.pm 2016/04/25 21:44:13 1.56 @@ -66,7 +66,7 @@ use common::sense; -our $VERSION = 1.41; +our $VERSION = 1.5; our @ISA = qw(Exporter); our @EXPORT = qw(encode_cbor decode_cbor); @@ -929,16 +929,16 @@ C method encodes "small" bigints into normal CBOR integers, and others into positive/negative CBOR bignums. -=item 4, 5 (decimal fraction/bigfloat) +=item 4, 5, 264, 265 (decimal fraction/bigfloat) Both decimal fractions and bigfloats are decoded into L objects. The corresponding C method I -encodes into a decimal fraction. +encodes into a decimal fraction (either tag 4 or 264). -CBOR cannot represent bigfloats with I large exponents - conversion -of such big float objects is undefined. +NaN and infinities are not encoded properly, as they cannot be represented +in CBOR. -Also, NaN and infinities are not encoded properly. +See L for more info. =item 21, 22, 23 (expected later JSON conversion) @@ -1004,6 +1004,33 @@ information you might want to make sure that exceptions thrown by CBOR::XS will not end up in front of untrusted eyes. + +=head1 BIGNUM SECURITY CONSIDERATIONS + +CBOR::XS provides a C method for both L and +L that tries to encode the number in the simplest possible +way, that is, either a CBOR integer, a CBOR bigint/decimal fraction (tag +4) or an arbitrary-exponent decimal fraction (tag 264). + +It will also understand base-2 bigfloat or arbitrary-exponent bigfloats +(tags 5 and 265), but it will never generate these on its own. + +Using the built-in L support, encoding and decoding +decimal fractions is generally fast. Decoding bigints can be slow for very +big numbers, and decoding bigfloats or arbitrary-exponent bigfloats can be +extremely slow (minutes, decades) for large exponents. + +Additionally, L can take advantage of other bignum +libraries, such as L, which cannot handle big +floats with large exponents, and might simply abort or crash your program, +due to their code quality. + +This can be a concern if you want to parse untrusted CBOR. If it is, you +need to disable decoding of tag 2 (bigint) and 3 (negative bigint) types, +which will also disable bigfloat support (to be sure, you can also disable +types 4, 5, 264 and 265). + + =head1 CBOR IMPLEMENTATION NOTES This section contains some random implementation notes. They do not @@ -1085,12 +1112,12 @@ 2 => sub { # pos bigint require Math::BigInt; - Math::BigInt->new ("0x" . unpack "H*", pop) + Math::BigInt->from_hex ("0x" . unpack "H*", pop) }, 3 => sub { # neg bigint require Math::BigInt; - -Math::BigInt->new ("0x" . unpack "H*", pop) + -Math::BigInt->from_hex ("0x" . unpack "H*", pop) }, 4 => sub { # decimal fraction, array @@ -1118,6 +1145,16 @@ # 34 # base64 rfc46484, utf-8 # 35 # regex pcre/ecma262, utf-8 # 36 # mime message rfc2045, utf-8 + + 264 => sub { # decimal fraction with arbitrary exponent + require Math::BigFloat; + Math::BigFloat->new ($_[1][1] . "E" . $_[1][0]) + }, + + 265 => sub { # bigfloat with arbitrary exponent + require Math::BigFloat; + scalar Math::BigFloat->new ($_[1][1]) * Math::BigFloat->new (2)->bpow ($_[1][0]) + }, ); sub CBOR::XS::default_filter { @@ -1131,7 +1168,7 @@ } sub Math::BigInt::TO_CBOR { - if ($_[0] >= -2147483648 && $_[0] <= 2147483647) { + if (-2147483648 <= $_[0] && $_[0] <= 2147483647) { $_[0]->numify } else { my $hex = substr $_[0]->as_hex, 2; @@ -1142,7 +1179,10 @@ sub Math::BigFloat::TO_CBOR { my ($m, $e) = $_[0]->parts; - tag 4, [$e->numify, $m] + + -9223372036854775808 <= $e && $e <= 18446744073709551615 + ? tag 4, [$e->numify, $m] + : tag 264, [$e, $m] } sub Time::Piece::TO_CBOR {