fix(compiler): preserve NUL bytes in string interpolation (#126) --skip-tests
* fix(compiler): preserve NUL bytes in string interpolation * fix(compiler): pool interpolated string literalsmaster
parent
1425499588
commit
f9a843e11c
4 changed files with 100 additions and 1 deletions
@ -0,0 +1,12 @@ |
||||
<?php |
||||
|
||||
function interpolated_null_string(): string |
||||
{ |
||||
$value = 'value'; |
||||
return "before\0{$value}after\0"; |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
echo bin2hex(interpolated_null_string()), "\n"; |
||||
} |
||||
@ -0,0 +1,60 @@ |
||||
<?php |
||||
/** |
||||
* This file is part of TypePHP(AOT). |
||||
* |
||||
* @link https://www.swoole.com/aot/ |
||||
* @contact service@swoole.com |
||||
*/ |
||||
|
||||
use TypePhp\CompilerBase; |
||||
use TypePhp\CompilerTest; |
||||
|
||||
/** |
||||
* @internal |
||||
* @coversNothing |
||||
*/ |
||||
final class InterpolatedStringCodegenTest extends BaseTest |
||||
{ |
||||
public function testLiteralPartsUseTheBinarySafeLiteralStringPool(): void |
||||
{ |
||||
global $translator; |
||||
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH); |
||||
$translator = $compiler; |
||||
$compiler->setBuildMode(CompilerBase::BUILD_MODE_EXT); |
||||
$compiler->setTargetName('interpolated_null_string'); |
||||
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/interpolated-null-string.php'; |
||||
$compiler->addFiles([$source]); |
||||
$compiler->prepareFile($source); |
||||
$code = file_get_contents($compiler->convertFile($source)); |
||||
|
||||
self::assertIsString($code); |
||||
self::assertStringContainsString('php::concat({get_str(', $code); |
||||
|
||||
$literalStrings = (new ReflectionProperty($compiler, 'literalStrings'))->getValue($compiler); |
||||
self::assertArrayHasKey("before\0", $literalStrings); |
||||
self::assertArrayHasKey("after\0", $literalStrings); |
||||
|
||||
$extension = file_get_contents($compiler->genExtension()); |
||||
self::assertIsString($extension); |
||||
self::assertStringContainsString('ZEND_STRL("before\000")', $extension); |
||||
self::assertStringContainsString('ZEND_STRL("after\000")', $extension); |
||||
} |
||||
|
||||
public function testNoLiteralStringsFallsBackToBinarySafeInlineStrings(): void |
||||
{ |
||||
global $translator; |
||||
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH); |
||||
$translator = $compiler; |
||||
(new ReflectionProperty($compiler, 'noLiteralStrings'))->setValue($compiler, true); |
||||
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/interpolated-null-string.php'; |
||||
$compiler->addFiles([$source]); |
||||
$compiler->prepareFile($source); |
||||
$code = file_get_contents($compiler->convertFile($source)); |
||||
|
||||
self::assertIsString($code); |
||||
self::assertStringNotContainsString('get_str(', $code); |
||||
self::assertStringContainsString('php::Str{ZEND_STRL("before\000")}', $code); |
||||
self::assertStringContainsString('php::Str{ZEND_STRL("after\000")}', $code); |
||||
self::assertSame([], (new ReflectionProperty($compiler, 'literalStrings'))->getValue($compiler)); |
||||
} |
||||
} |
||||
@ -0,0 +1,27 @@ |
||||
--TEST-- |
||||
String interpolation preserves embedded NUL bytes in literal parts |
||||
--FILE-- |
||||
<?php |
||||
|
||||
function main(): void |
||||
{ |
||||
$value = 'X'; |
||||
echo bin2hex("A\0B{$value}C\0D"), "\n"; |
||||
echo bin2hex("\0{$value}\0"), "\n"; |
||||
echo bin2hex("{$value}\x007"), "\n"; |
||||
|
||||
$binary = "X\0Y"; |
||||
echo bin2hex("A{$binary}B"), "\n"; |
||||
|
||||
$heredoc = <<<TEXT |
||||
A\0B{$value}C\0D |
||||
TEXT; |
||||
echo bin2hex($heredoc), "\n"; |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
41004258430044 |
||||
005800 |
||||
580037 |
||||
4158005942 |
||||
41004258430044 |
||||
Loading…
Reference in new issue