ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/CBOR-XS/XS.pm
(Generate patch)

Comparing CBOR-XS/XS.pm (file contents):
Revision 1.52 by root, Mon Apr 25 18:17:17 2016 UTC vs.
Revision 1.60 by root, Tue Apr 26 16:26:24 2016 UTC

64 64
65package CBOR::XS; 65package CBOR::XS;
66 66
67use common::sense; 67use common::sense;
68 68
69our $VERSION = 1.41; 69our $VERSION = 1.5;
70our @ISA = qw(Exporter); 70our @ISA = qw(Exporter);
71 71
72our @EXPORT = qw(encode_cbor decode_cbor); 72our @EXPORT = qw(encode_cbor decode_cbor);
73 73
74use Exporter; 74use Exporter;
588 my $x = 3.1; # some variable containing a number 588 my $x = 3.1; # some variable containing a number
589 "$x"; # stringified 589 "$x"; # stringified
590 $x .= ""; # another, more awkward way to stringify 590 $x .= ""; # another, more awkward way to stringify
591 print $x; # perl does it for you, too, quite often 591 print $x; # perl does it for you, too, quite often
592 592
593You can force whether a string ie encoded as byte or text string by using 593You can force whether a string is encoded as byte or text string by using
594C<utf8::upgrade> and C<utf8::downgrade>): 594C<utf8::upgrade> and C<utf8::downgrade> (if C<text_strings> is disabled):
595 595
596 utf8::upgrade $x; # encode $x as text string 596 utf8::upgrade $x; # encode $x as text string
597 utf8::downgrade $x; # encode $x as byte string 597 utf8::downgrade $x; # encode $x as byte string
598 598
599Perl doesn't define what operations up- and downgrade strings, so if the 599Perl doesn't define what operations up- and downgrade strings, so if the
600difference between byte and text is important, you should up- or downgrade 600difference between byte and text is important, you should up- or downgrade
601your string as late as possible before encoding. 601your string as late as possible before encoding. You can also force the
602use of CBOR text strings by using C<text_keys> or C<text_strings>.
602 603
603You can force the type to be a CBOR number by numifying it: 604You can force the type to be a CBOR number by numifying it:
604 605
605 my $x = "3"; # some variable containing a string 606 my $x = "3"; # some variable containing a string
606 $x += 0; # numify it, ensuring it will be dumped as a number 607 $x += 0; # numify it, ensuring it will be dumped as a number
926 927
927These tags are decoded into L<Math::BigInt> objects. The corresponding 928These tags are decoded into L<Math::BigInt> objects. The corresponding
928C<Math::BigInt::TO_CBOR> method encodes "small" bigints into normal CBOR 929C<Math::BigInt::TO_CBOR> method encodes "small" bigints into normal CBOR
929integers, and others into positive/negative CBOR bignums. 930integers, and others into positive/negative CBOR bignums.
930 931
931=item 4, 5 (decimal fraction/bigfloat) 932=item 4, 5, 264, 265 (decimal fraction/bigfloat)
932 933
933Both decimal fractions and bigfloats are decoded into L<Math::BigFloat> 934Both decimal fractions and bigfloats are decoded into L<Math::BigFloat>
934objects. The corresponding C<Math::BigFloat::TO_CBOR> method I<always> 935objects. The corresponding C<Math::BigFloat::TO_CBOR> method I<always>
935encodes into a decimal fraction. 936encodes into a decimal fraction (either tag 4 or 264).
936 937
937CBOR cannot represent bigfloats with I<very> large exponents - conversion 938NaN and infinities are not encoded properly, as they cannot be represented
938of such big float objects is undefined. 939in CBOR.
939 940
940Also, NaN and infinities are not encoded properly. 941See L<BIGNUM SECURITY CONSIDERATIONS> for more info.
942
943=item 30 (rational numbers)
944
945These tags are decoded into L<Math::BigRat> objects. The corresponding
946C<Math::BigRat::TO_CBOR> method encodes rational numbers with denominator
947C<1> via their numerator only, i.e., they become normal integers or
948C<bignums>.
949
950See L<BIGNUM SECURITY CONSIDERATIONS> for more info.
941 951
942=item 21, 22, 23 (expected later JSON conversion) 952=item 21, 22, 23 (expected later JSON conversion)
943 953
944CBOR::XS is not a CBOR-to-JSON converter, and will simply ignore these 954CBOR::XS is not a CBOR-to-JSON converter, and will simply ignore these
945tags. 955tags.
1000 1010
1001Also keep in mind that CBOR::XS might leak contents of your Perl data 1011Also keep in mind that CBOR::XS might leak contents of your Perl data
1002structures in its error messages, so when you serialise sensitive 1012structures in its error messages, so when you serialise sensitive
1003information you might want to make sure that exceptions thrown by CBOR::XS 1013information you might want to make sure that exceptions thrown by CBOR::XS
1004will not end up in front of untrusted eyes. 1014will not end up in front of untrusted eyes.
1015
1016
1017=head1 BIGNUM SECURITY CONSIDERATIONS
1018
1019CBOR::XS provides a C<TO_CBOR> method for both L<Math::BigInt> and
1020L<Math::BigFloat> that tries to encode the number in the simplest possible
1021way, that is, either a CBOR integer, a CBOR bigint/decimal fraction (tag
10224) or an arbitrary-exponent decimal fraction (tag 264). Rational numbers
1023(L<Math::BigRat>, tag 30) can also contain bignums as members.
1024
1025CBOR::XS will also understand base-2 bigfloat or arbitrary-exponent
1026bigfloats (tags 5 and 265), but it will never generate these on its own.
1027
1028Using the built-in L<Math::BigInt::Calc> support, encoding and decoding
1029decimal fractions is generally fast. Decoding bigints can be slow for very
1030big numbers (tens of thousands of digits, something that could potentially
1031be caught by limiting the size of CBOR texts), and decoding bigfloats or
1032arbitrary-exponent bigfloats can be I<extremely> slow (minutes, decades)
1033for large exponents (roughly 40 bit and longer).
1034
1035Additionally, L<Math::BigInt> can take advantage of other bignum
1036libraries, such as L<Math::GMP>, which cannot handle big floats with large
1037exponents, and might simply abort or crash your program, due to their code
1038quality.
1039
1040This can be a concern if you want to parse untrusted CBOR. If it is, you
1041might want to disable decoding of tag 2 (bigint) and 3 (negative bigint)
1042types. You should also disable types 5 and 265, as these can be slow even
1043without bigints.
1044
1045Disabling bigints will also partially or fully disable types that rely on
1046them, e.g. rational numbers that use bignums.
1047
1005 1048
1006=head1 CBOR IMPLEMENTATION NOTES 1049=head1 CBOR IMPLEMENTATION NOTES
1007 1050
1008This section contains some random implementation notes. They do not 1051This section contains some random implementation notes. They do not
1009describe guaranteed behaviour, but merely behaviour as-is implemented 1052describe guaranteed behaviour, but merely behaviour as-is implemented
1095 4 => sub { # decimal fraction, array 1138 4 => sub { # decimal fraction, array
1096 require Math::BigFloat; 1139 require Math::BigFloat;
1097 Math::BigFloat->new ($_[1][1] . "E" . $_[1][0]) 1140 Math::BigFloat->new ($_[1][1] . "E" . $_[1][0])
1098 }, 1141 },
1099 1142
1143 264 => sub { # decimal fraction with arbitrary exponent
1144 require Math::BigFloat;
1145 Math::BigFloat->new ($_[1][1] . "E" . $_[1][0])
1146 },
1147
1100 5 => sub { # bigfloat, array 1148 5 => sub { # bigfloat, array
1101 require Math::BigFloat; 1149 require Math::BigFloat;
1102 scalar Math::BigFloat->new ($_[1][1]) * Math::BigFloat->new (2)->bpow ($_[1][0]) 1150 scalar Math::BigFloat->new ($_[1][1]) * Math::BigFloat->new (2)->bpow ($_[1][0])
1151 },
1152
1153 265 => sub { # bigfloat with arbitrary exponent
1154 require Math::BigFloat;
1155 scalar Math::BigFloat->new ($_[1][1]) * Math::BigFloat->new (2)->bpow ($_[1][0])
1156 },
1157
1158 30 => sub { # rational number
1159 require Math::BigRat;
1160 Math::BigRat->new ("$_[1][0]/$_[1][1]") # separate parameters only work in recent versons
1103 }, 1161 },
1104 1162
1105 21 => sub { pop }, # expected conversion to base64url encoding 1163 21 => sub { pop }, # expected conversion to base64url encoding
1106 22 => sub { pop }, # expected conversion to base64 encoding 1164 22 => sub { pop }, # expected conversion to base64 encoding
1107 23 => sub { pop }, # expected conversion to base16 encoding 1165 23 => sub { pop }, # expected conversion to base16 encoding
1128 utf8::upgrade $uri; 1186 utf8::upgrade $uri;
1129 tag 32, $uri 1187 tag 32, $uri
1130} 1188}
1131 1189
1132sub Math::BigInt::TO_CBOR { 1190sub Math::BigInt::TO_CBOR {
1133 if ($_[0] >= -2147483648 && $_[0] <= 2147483647) { 1191 if (-2147483648 <= $_[0] && $_[0] <= 2147483647) {
1134 $_[0]->numify 1192 $_[0]->numify
1135 } else { 1193 } else {
1136 my $hex = substr $_[0]->as_hex, 2; 1194 my $hex = substr $_[0]->as_hex, 2;
1137 $hex = "0$hex" if 1 & length $hex; # sigh 1195 $hex = "0$hex" if 1 & length $hex; # sigh
1138 tag $_[0] >= 0 ? 2 : 3, pack "H*", $hex 1196 tag $_[0] >= 0 ? 2 : 3, pack "H*", $hex
1139 } 1197 }
1140} 1198}
1141 1199
1142sub Math::BigFloat::TO_CBOR { 1200sub Math::BigFloat::TO_CBOR {
1143 my ($m, $e) = $_[0]->parts; 1201 my ($m, $e) = $_[0]->parts;
1202
1203 -9223372036854775808 <= $e && $e <= 18446744073709551615
1144 tag 4, [$e->numify, $m] 1204 ? tag 4, [$e->numify, $m]
1205 : tag 264, [$e, $m]
1206}
1207
1208sub Math::BigRat::TO_CBOR {
1209 my ($n, $d) = $_[0]->parts;
1210
1211 # older versions of BigRat need *1, as they not always return numbers
1212
1213 $d*1 == 1
1214 ? $n*1
1215 : tag 30, [$n*1, $d*1]
1145} 1216}
1146 1217
1147sub Time::Piece::TO_CBOR { 1218sub Time::Piece::TO_CBOR {
1148 tag 1, 0 + $_[0]->epoch 1219 tag 1, 0 + $_[0]->epoch
1149} 1220}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines