pack() with new "Z" more in line with Perl.

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.
This commit is contained in:
Gustavo André dos Santos Lopes 2012-04-17 22:18:48 +01:00
parent 4968fa644b
commit dbc5b42435
4 changed files with 76 additions and 27 deletions

View 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': {

View 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"
}
array(1) {
[1]=>
string(3) "foo"
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(5) "str%c%c"
}

View File

@ -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"
}

View File

@ -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"
}