Re: encoding neutral unpack
Ton Hospel [Sat, 29 Jan 2005 13:24:55 +0000 (13:24 +0000)]
From: perl5-porters[at]ton.iguana.be (Ton Hospel)
Message-ID: <ctg2r7$j0e$4[at]post.home.lunix>

Ensure that with the C format, unpack checksums
don't get overflowed. (plus a regression test)

p4raw-id: //depot/perl@23922

pp_pack.c
t/op/pack.t

index cb3dd89..97e0a06 100644 (file)
--- a/pp_pack.c
+++ b/pp_pack.c
@@ -1183,7 +1183,10 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
              uchar_checksum:
                while (len-- > 0) {
                    auint = *s++ & 255;
-                   cuv += auint;
+                   if (checksum > bits_in_uv)
+                       cdouble += (NV)auint;
+                   else
+                       cuv += auint;
                }
            }
            else {
@@ -1703,7 +1706,7 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
        if (checksum) {
            if (strchr("fFdD", TYPE_NO_MODIFIERS(datumtype)) ||
              (checksum > bits_in_uv &&
-              strchr("csSiIlLnNUvVqQjJ", TYPE_NO_MODIFIERS(datumtype))) ) {
+              strchr("cCsSiIlLnNUvVqQjJ", TYPE_NO_MODIFIERS(datumtype))) ) {
                NV trouble;
 
                 adouble = (NV) (1 << (checksum & 15));
index d30ae94..3fc4cfd 100755 (executable)
@@ -12,7 +12,7 @@ my $no_endianness = $] > 5.009 ? '' :
 my $no_signedness = $] > 5.009 ? '' :
   "Signed/unsigned pack modifiers not available on this perl";
 
-plan tests => 13856;
+plan tests => 13857;
 
 use strict;
 use warnings;
@@ -1498,4 +1498,7 @@ is(unpack('c'), 65, "one-arg unpack (change #18751)"); # defaulting to $_
     my (@x) = unpack("b10a", "abcd");
     my (@y) = unpack("%b10a", "abcd");
     is($x[1], $y[1], "checksum advance ok");
+
+    # verify that the checksum is not overflowed with C0
+    is(unpack("C0%128U", "abcd"), unpack("U0%128U", "abcd"), "checksum not overflowed");
 }