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