feat(compiler): add support for embedded NUL bytes in string literals

- Replace noLiteralString handling with getInlineString method
- Add getInlineString function to generate PHP strings without literal table
- Use ZEND_STRL to preserve string length with embedded NULs
- Update scalar parsing to use getInlineString for noLiteralString case
- Add test case for embedded null string handling
- Remove skip condition for trim tests related to embedded nulls
pull/17/head
韩天峰 2 months ago
parent b6cc597725
commit fd085c10d0
  1. 15
      src/CompilerBase.php
  2. 22
      tests/aot/basic/embedded-null-string.phpt
  3. 2
      tests/std/strings/trim.phpt

@ -1312,12 +1312,23 @@ class CompilerBase implements PropertyAccessContext
protected function getLiteralString(string $string): string
{
if ($this->noLiteralStrings) {
return '"' . $this->escapeString($string) . '"';
return $this->getInlineString($string);
}
$index = $this->literalStrings[$string] ?? $this->addLiteralString($string);
return self::LITERAL_STRINGS . '[' . $index . ']';
}
/**
* Generates a PHP string value without adding it to the literal-string table.
*
* A C++ string literal may contain an embedded NUL, but passing it as a
* const char* would truncate it at that byte. ZEND_STRL preserves its length.
*/
protected function getInlineString(string $string): string
{
return self::TYPE_STR . '{ZEND_STRL(' . $this->genCharPtr($string, true) . ')}';
}
protected function parseScalar(Node\Scalar $expr): string
{
$type = $expr->getType();
@ -1338,7 +1349,7 @@ class CompilerBase implements PropertyAccessContext
}
return $this->parseScalarFloat($expr);
case 'Scalar_String':
return $expr->hasAttribute('noLiteralString') ? $this->genCharPtr($expr->value, true) : $this->getLiteralString($expr->value);
return $expr->hasAttribute('noLiteralString') ? $this->getInlineString($expr->value) : $this->getLiteralString($expr->value);
default:
abort($expr);
break;

@ -0,0 +1,22 @@
--TEST--
Embedded NUL bytes in string literals
--FILE--
<?php
function main(): void
{
$value = "hello \0 world";
var_dump(strlen($value));
var_dump(bin2hex($value));
var_dump($value === "hello \0 world");
var_dump($value . "!" === "hello \0 world!");
var_dump(eval('return "A\\0B";') === "A\0B");
}
?>
--EXPECT--
int(13)
string(26) "68656c6c6f200020776f726c64"
bool(true)
bool(true)
bool(true)

@ -2,7 +2,7 @@
trim(), rtrim() and ltrim() functions
--SKIPIF--
<?php
echo 'skip C++ string literals do not support embedded null bytes (\\0)';
echo 'skip trim() does not yet handle form-feed whitespace';
?>
--FILE--
<?php

Loading…
Cancel
Save