|
|
e117a54 |
From aee0279a5d6c3c12063e2c5488b35e88ccd13c54 Mon Sep 17 00:00:00 2001
|
|
|
e117a54 |
From: Tony Cook <tony@develop-help.com>
|
|
|
e117a54 |
Date: Fri, 23 Apr 2010 19:28:35 +1000
|
|
|
e117a54 |
Subject: [PATCH] RT#73814 - unpack() didn't handle scalar context correctly for %32H and %32u
|
|
|
e117a54 |
|
|
|
e117a54 |
split() would crash because the third item on the stack wasn't the
|
|
|
e117a54 |
regular expression it expected. unpack("%2H", ...) would return both
|
|
|
e117a54 |
the unpacked result and the checksum on the stack, similarly for
|
|
|
e117a54 |
unpack("%2u", ...).
|
|
|
e117a54 |
---
|
|
|
e117a54 |
pp_pack.c | 33 +++++++++++++++++++++------------
|
|
|
e117a54 |
t/op/pack.t | 10 +++++++++-
|
|
|
e117a54 |
2 files changed, 30 insertions(+), 13 deletions(-)
|
|
|
e117a54 |
|
|
|
e117a54 |
diff --git a/pp_pack.c b/pp_pack.c
|
|
|
e117a54 |
index 0670548..0ae8afd 100644
|
|
|
e117a54 |
--- a/pp_pack.c
|
|
|
e117a54 |
+++ b/pp_pack.c
|
|
|
e117a54 |
@@ -1562,9 +1562,11 @@ S_unpack_rec(pTHX_ tempsym_t* symptr, const char *s, const char *strbeg, const c
|
|
|
e117a54 |
/* Preliminary length estimate, acceptable for utf8 too */
|
|
|
e117a54 |
if (howlen == e_star || len > (strend - s) * 2)
|
|
|
e117a54 |
len = (strend - s) * 2;
|
|
|
e117a54 |
- sv = sv_2mortal(newSV(len ? len : 1));
|
|
|
e117a54 |
- SvPOK_on(sv);
|
|
|
e117a54 |
- str = SvPVX(sv);
|
|
|
e117a54 |
+ if (!checksum) {
|
|
|
e117a54 |
+ sv = sv_2mortal(newSV(len ? len : 1));
|
|
|
e117a54 |
+ SvPOK_on(sv);
|
|
|
e117a54 |
+ str = SvPVX(sv);
|
|
|
e117a54 |
+ }
|
|
|
e117a54 |
if (datumtype == 'h') {
|
|
|
e117a54 |
U8 bits = 0;
|
|
|
e117a54 |
I32 ai32 = len;
|
|
|
e117a54 |
@@ -1574,7 +1576,8 @@ S_unpack_rec(pTHX_ tempsym_t* symptr, const char *s, const char *strbeg, const c
|
|
|
e117a54 |
if (s >= strend) break;
|
|
|
e117a54 |
bits = uni_to_byte(aTHX_ &s, strend, datumtype);
|
|
|
e117a54 |
} else bits = * (U8 *) s++;
|
|
|
e117a54 |
- *str++ = PL_hexdigit[bits & 15];
|
|
|
e117a54 |
+ if (!checksum)
|
|
|
e117a54 |
+ *str++ = PL_hexdigit[bits & 15];
|
|
|
e117a54 |
}
|
|
|
e117a54 |
} else {
|
|
|
e117a54 |
U8 bits = 0;
|
|
|
e117a54 |
@@ -1585,12 +1588,15 @@ S_unpack_rec(pTHX_ tempsym_t* symptr, const char *s, const char *strbeg, const c
|
|
|
e117a54 |
if (s >= strend) break;
|
|
|
e117a54 |
bits = uni_to_byte(aTHX_ &s, strend, datumtype);
|
|
|
e117a54 |
} else bits = *(U8 *) s++;
|
|
|
e117a54 |
- *str++ = PL_hexdigit[(bits >> 4) & 15];
|
|
|
e117a54 |
+ if (!checksum)
|
|
|
e117a54 |
+ *str++ = PL_hexdigit[(bits >> 4) & 15];
|
|
|
e117a54 |
}
|
|
|
e117a54 |
}
|
|
|
e117a54 |
- *str = '\0';
|
|
|
e117a54 |
- SvCUR_set(sv, str - SvPVX_const(sv));
|
|
|
e117a54 |
- XPUSHs(sv);
|
|
|
e117a54 |
+ if (!checksum) {
|
|
|
e117a54 |
+ *str = '\0';
|
|
|
e117a54 |
+ SvCUR_set(sv, str - SvPVX_const(sv));
|
|
|
e117a54 |
+ XPUSHs(sv);
|
|
|
e117a54 |
+ }
|
|
|
e117a54 |
break;
|
|
|
e117a54 |
}
|
|
|
e117a54 |
case 'C':
|
|
|
e117a54 |
@@ -2123,7 +2129,7 @@ S_unpack_rec(pTHX_ tempsym_t* symptr, const char *s, const char *strbeg, const c
|
|
|
e117a54 |
break;
|
|
|
e117a54 |
#endif
|
|
|
e117a54 |
case 'u':
|
|
|
e117a54 |
- {
|
|
|
e117a54 |
+ if (!checksum) {
|
|
|
e117a54 |
const STRLEN l = (STRLEN) (strend - s) * 3 / 4;
|
|
|
e117a54 |
sv = sv_2mortal(newSV(l));
|
|
|
e117a54 |
if (l) SvPOK_on(sv);
|
|
|
e117a54 |
@@ -2141,7 +2147,8 @@ S_unpack_rec(pTHX_ tempsym_t* symptr, const char *s, const char *strbeg, const c
|
|
|
e117a54 |
hunk[0] = (char)((a << 2) | (b >> 4));
|
|
|
e117a54 |
hunk[1] = (char)((b << 4) | (c >> 2));
|
|
|
e117a54 |
hunk[2] = (char)((c << 6) | d);
|
|
|
e117a54 |
- sv_catpvn(sv, hunk, (len > 3) ? 3 : len);
|
|
|
e117a54 |
+ if (!checksum)
|
|
|
e117a54 |
+ sv_catpvn(sv, hunk, (len > 3) ? 3 : len);
|
|
|
e117a54 |
len -= 3;
|
|
|
e117a54 |
}
|
|
|
e117a54 |
if (s < strend) {
|
|
|
e117a54 |
@@ -2182,7 +2189,8 @@ S_unpack_rec(pTHX_ tempsym_t* symptr, const char *s, const char *strbeg, const c
|
|
|
e117a54 |
hunk[0] = (char)((a << 2) | (b >> 4));
|
|
|
e117a54 |
hunk[1] = (char)((b << 4) | (c >> 2));
|
|
|
e117a54 |
hunk[2] = (char)((c << 6) | d);
|
|
|
e117a54 |
- sv_catpvn(sv, hunk, (len > 3) ? 3 : len);
|
|
|
e117a54 |
+ if (!checksum)
|
|
|
e117a54 |
+ sv_catpvn(sv, hunk, (len > 3) ? 3 : len);
|
|
|
e117a54 |
len -= 3;
|
|
|
e117a54 |
}
|
|
|
e117a54 |
if (*s == '\n')
|
|
|
e117a54 |
@@ -2192,7 +2200,8 @@ S_unpack_rec(pTHX_ tempsym_t* symptr, const char *s, const char *strbeg, const c
|
|
|
e117a54 |
s += 2;
|
|
|
e117a54 |
}
|
|
|
e117a54 |
}
|
|
|
e117a54 |
- XPUSHs(sv);
|
|
|
e117a54 |
+ if (!checksum)
|
|
|
e117a54 |
+ XPUSHs(sv);
|
|
|
e117a54 |
break;
|
|
|
e117a54 |
}
|
|
|
e117a54 |
|
|
|
e117a54 |
diff --git a/t/op/pack.t b/t/op/pack.t
|
|
|
e117a54 |
index 4b5f9a5..5775caf 100644
|
|
|
e117a54 |
--- a/t/op/pack.t
|
|
|
e117a54 |
+++ b/t/op/pack.t
|
|
|
e117a54 |
@@ -12,7 +12,7 @@ my $no_endianness = $] > 5.009 ? '' :
|
|
|
e117a54 |
my $no_signedness = $] > 5.009 ? '' :
|
|
|
e117a54 |
"Signed/unsigned pack modifiers not available on this perl";
|
|
|
e117a54 |
|
|
|
e117a54 |
-plan tests => 14697;
|
|
|
e117a54 |
+plan tests => 14699;
|
|
|
e117a54 |
|
|
|
e117a54 |
use strict;
|
|
|
e117a54 |
use warnings qw(FATAL all);
|
|
|
e117a54 |
@@ -1985,3 +1985,11 @@ is(unpack('c'), 65, "one-arg unpack (change #18751)"); # defaulting to $_
|
|
|
e117a54 |
my ($v) = split //, unpack ('(B)*', 'ab');
|
|
|
e117a54 |
is($v, 0); # Doesn't SEGV :-)
|
|
|
e117a54 |
}
|
|
|
e117a54 |
+{
|
|
|
e117a54 |
+ #73814
|
|
|
e117a54 |
+ my $x = runperl( prog => 'print split( /,/, unpack(q(%2H*), q(hello world))), qq(\n)' );
|
|
|
e117a54 |
+ is($x, "0\n", "split /a/, unpack('%2H*'...) didn't crash");
|
|
|
e117a54 |
+
|
|
|
e117a54 |
+ my $y = runperl( prog => 'print split( /,/, unpack(q(%32u*), q(#,3,Q)), qq(\n)), qq(\n)' );
|
|
|
e117a54 |
+ is($y, "0\n", "split /a/, unpack('%32u*'...) didn't crash");
|
|
|
e117a54 |
+}
|
|
|
e117a54 |
--
|
|
|
e117a54 |
1.5.6.5
|
|
|
e117a54 |
|