Skip to content

Commit

Permalink
pack() with new "Z" more in line with Perl.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
cataphract committed Apr 17, 2012
1 parent 4968fa6 commit dbc5b42
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 24 deletions.
12 changes: 10 additions & 2 deletions ext/standard/pack.c
Expand Up @@ -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++;
Expand Down Expand Up @@ -317,17 +323,19 @@ 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)) {
SEPARATE_ZVAL(val);
}
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': {
Expand Down
33 changes: 11 additions & 22 deletions ext/standard/tests/strings/bug61038.phpt
@@ -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"
}

25 changes: 25 additions & 0 deletions ext/standard/tests/strings/pack_A.phpt
@@ -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"
}

27 changes: 27 additions & 0 deletions ext/standard/tests/strings/pack_Z.phpt
@@ -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"
}

0 comments on commit dbc5b42

Please sign in to comment.