]> granicus.if.org Git - php/commitdiff
pack() with new "Z" more in line with Perl.
authorGustavo André dos Santos Lopes <cataphract@php.net>
Tue, 17 Apr 2012 21:18:48 +0000 (22:18 +0100)
committerGustavo André dos Santos Lopes <cataphract@php.net>
Tue, 17 Apr 2012 21:21:32 +0000 (22:21 +0100)
Made pack() with "Z" force NUL termination, even if it mean truncating input
to less than the number of characters specified and if the number of
characters is "*", the output will be one byte larger than the input.

Improved tests.

ext/standard/pack.c
ext/standard/tests/strings/bug61038.phpt
ext/standard/tests/strings/pack_A.phpt [new file with mode: 0644]
ext/standard/tests/strings/pack_Z.phpt [new file with mode: 0644]

index c2fa28f6dd5baeb22392fe995bcb37e126b1d961..3cd6ee7c50324bc581b697fc592e6d976164508c 100644 (file)
@@ -187,6 +187,12 @@ PHP_FUNCTION(pack)
                                        }
                                        convert_to_string_ex(argv[currentarg]);
                                        arg = Z_STRLEN_PP(argv[currentarg]);
+                                       if (code == 'Z') {
+                                               /* add one because Z is always NUL-terminated:
+                                                * pack("Z*", "aa") === "aa\0"
+                                                * pack("Z2", "aa") === "a\0" */
+                                               arg++;
+                                       }
                                }
 
                                currentarg++;
@@ -317,7 +323,8 @@ PHP_FUNCTION(pack)
                switch ((int) code) {
                        case 'a': 
                        case 'A': 
-                       case 'Z': 
+                       case 'Z': {
+                               int arg_cp = (code != 'Z') ? arg : MAX(0, arg - 1);
                                memset(&output[outputpos], (code == 'a' || code == 'Z') ? '\0' : ' ', arg);
                                val = argv[currentarg++];
                                if (Z_ISREF_PP(val)) {
@@ -325,9 +332,10 @@ PHP_FUNCTION(pack)
                                }
                                convert_to_string_ex(val);
                                memcpy(&output[outputpos], Z_STRVAL_PP(val),
-                                          (Z_STRLEN_PP(val) < arg) ? Z_STRLEN_PP(val) : arg);
+                                          (Z_STRLEN_PP(val) < arg_cp) ? Z_STRLEN_PP(val) : arg_cp);
                                outputpos += arg;
                                break;
+                       }
 
                        case 'h': 
                        case 'H': {
index 10fcef83a7deb3e6caf1a1d9effd102f96392e0b..7130804fa415c03afb14aa273ee6dc0ebdf5bd33 100644 (file)
@@ -1,37 +1,26 @@
 --TEST--
-BugFix #61038
+Bug #61038: unpack("a5", "str\0\0") does not work as expected
 --FILE--
 <?php
-       var_dump(unpack("Z4", pack("Z4", "foo")));
-       var_dump(unpack("a4", pack("a4", "foo")));
-       var_dump(unpack("A4", pack("A4", "foo")));
-       var_dump(unpack("a9", pack("a*", "foo\x00bar\x00 ")));
-       var_dump(unpack("A9", pack("a*", "foo\x00bar\x00 ")));
-       var_dump(unpack("Z9", pack("a*", "foo\x00bar\x00 ")));
+var_dump(unpack("a4", "str\0\0"));
+var_dump(unpack("a5", "str\0\0"));
+var_dump(unpack("a6", "str\0\0"));
+var_dump(unpack("a*", "str\0\0"));
 ?>
 --EXPECTF--
 array(1) {
   [1]=>
-  string(3) "foo"
+  string(4) "str%c"
 }
 array(1) {
   [1]=>
-  string(4) "foo%c"
-}
-array(1) {
-  [1]=>
-  string(3) "foo"
-}
-array(1) {
-  [1]=>
-  string(9) "foo%cbar%c "
-}
-array(1) {
-  [1]=>
-  string(7) "foo%cbar"
+  string(5) "str%c%c"
 }
+
+Warning: unpack(): Type a: not enough input, need 6, have 5 in %s on line %d
+bool(false)
 array(1) {
   [1]=>
-  string(3) "foo"
+  string(5) "str%c%c"
 }
 
diff --git a/ext/standard/tests/strings/pack_A.phpt b/ext/standard/tests/strings/pack_A.phpt
new file mode 100644 (file)
index 0000000..59fc22e
--- /dev/null
@@ -0,0 +1,25 @@
+--TEST--
+pack()/unpack(): "A" modifier
+--FILE--
+<?php
+var_dump(
+       pack("A5", "foo "),
+       pack("A4", "fooo"),
+       pack("A4", "foo"),
+       unpack("A*", "foo\0\rbar\0 \t\r\n"),
+       unpack("A4", "foo\0\rbar\0 \t\r\n")
+);
+?>
+--EXPECTF--
+string(5) "foo  "
+string(4) "fooo"
+string(4) "foo "
+array(1) {
+  [1]=>
+  string(8) "foo%c%cbar"
+}
+array(1) {
+  [1]=>
+  string(3) "foo"
+}
+
diff --git a/ext/standard/tests/strings/pack_Z.phpt b/ext/standard/tests/strings/pack_Z.phpt
new file mode 100644 (file)
index 0000000..8a2ee67
--- /dev/null
@@ -0,0 +1,27 @@
+--TEST--
+pack()/unpack(): "Z" format
+--FILE--
+<?php
+var_dump(
+       pack("Z0", "f"),
+    pack("Z5", "foo\0"),
+    pack("Z4", "fooo"),
+    pack("Z4", "foo"),
+       pack("Z*", "foo"),
+    unpack("Z*", "foo\0\rbar\0 \t\r\n"),
+    unpack("Z9", "foo\0\rbar\0 \t\r\n")
+);
+--EXPECTF--
+string(0) ""
+string(5) "foo%c%c"
+string(4) "foo%c"
+string(4) "foo%c"
+string(4) "foo%c"
+array(1) {
+  [1]=>
+  string(3) "foo"
+}
+array(1) {
+  [1]=>
+  string(3) "foo"
+}