PHP解包的意外行为()

时间:2012-07-24 13:02:11

标签: php unpack

测试

$x = sprintf( "foo\x00bar\x00baz" );
$y = unpack( 'afoo/abar/abaz' , $x );
print_r( $y );
$x = sprintf( "foo\x00bar\x00baz" );
$y = unpack( 'a*foo/a*bar/a*baz' , $x );
print_r( $y );

结果

Array
(
    [foo] => f
    [bar] => o
    [baz] => o
)
Array
(
    [foo] => foobarbaz
    [bar] => 
    [baz] => 
)

请注意,NULL字节始终存在,您可以使用hexdump进行检查。

预期结果

Array
(
    [foo] => foo
    [bar] => bar
    [baz] => baz
)

注释

我知道我可以使用explode来获得类似的结果。我不是要求替代方案,我只是想了解a格式字符背后的逻辑(正如文档所说的那样“NUL-padded string”)。

所有这些都涉及“NULL”值?

1 个答案:

答案 0 :(得分:6)

原始答案

“所有这些都涉及”NULL“值?”

无处。

我很确定PHP pack()/ unpack()的文档需要更新。基本上,只要你看到它引用了一个以NULL结尾的字符串,那么该文档就是从代码的Perl版本中获取的,而不是对PHP中发生的事情的反映。

基本上Perl有C样式字符串,可以为空终止,以便您知道字符串结尾的位置。在PHP中,没有NULL字符的概念。 e.g。

$test1 = "Test".NULL."ing";
$test2 = "Testing";

if(strcmp($test1, $test2) == 0){
    echo "The strings are the same";
}
else{
    echo "They are different.";
}

将打印'字符串是相同的'。

顺便提一下:     “富\ x00bar \ x00baz”

可能没有做你认为它正在做的事情。它没有在foo + bar和bar + baz之间的字符串中放置'NULL'字符,因为没有NULL字符。相反,它将字符'0'放在大多数字符集中,但是没有特殊含义作为字符。

我知道你提到使用explode而不是unpack但是如果你知道字符串长度那么你可以使用:

unpack( 'a3foo/a3bar/a3baz' , $binarydata);

为了清晰起见添加

Cyrus写道:

  

“NULL byte”是指值为0的字节:

我不知道你在哪里得到字符串“foo \ x00bar \ x00baz”但是:

i)它必须来自支持由零表示的NULL字符的语言。如果你打电话,PHP不支持NULL字符     pack(“A * A * A *”,“foo”,“bar”,“baz”); 它不会生成带有零的字符串。

ii)unpack的PHP版本不支持NULL字符(因为PHP不支持NULL字符),并将十六进制值为0的字符视为另一个字符。 e.g。

function strToHex($string){
    $hex='';
    for ($i=0; $i < strlen($string); $i++)
    {
        $hex .= dechex(ord($string[$i]));
    }
    return $hex;
}

$binarydata = "foo\x00bar\x00baz";

echo "binarydata is ";

var_dump($binarydata);
$y = unpack( 'a3foo/a3bar/a3baz' , $binarydata);
var_dump( $y );

echo strToHex($y['foo'])."\r\n";
echo strToHex($y['bar'])."\r\n";
echo strToHex($y['baz'])."\r\n";

将输出:

binarydata is string(11) "foobarbaz"
array(3) {
  ["foo"]=>
  string(3) "foo"
  ["bar"]=>
  string(3) "ba"
  ["baz"]=>
  string(3) "rb"
}
666f6f
06261
72062

即。它提取前三个字符,值为0x66,0x6f,0x6f。然后它提取接下来的三个字符,即0x0,0x62,0x61。最后,它提取值0x72,0x0,0x62。