Skip to content

gen_stub: Fix handling of escape sequences in generated C strings - #22273

Merged
NattyNarwhal merged 1 commit into
php:masterfrom
NattyNarwhal:gen-stub-string-escape
Jun 22, 2026
Merged

gen_stub: Fix handling of escape sequences in generated C strings#22273
NattyNarwhal merged 1 commit into
php:masterfrom
NattyNarwhal:gen-stub-string-escape

Conversation

@NattyNarwhal

@NattyNarwhalNattyNarwhal commented Jun 10, 2026

Copy link
Copy Markdown
Member

When handling sequences like this in a stub:

<?phpclass Whatever {
publicstaticstring$foobar1 = "CCC \n\r\t\v\e\f\\\$\"\101\x41\u{41} CCC";
publicstaticstring$foobar2 = 'CCC \n\r\t\v\e\f\\\$\"\101\x41\u{41} CCC';
}

...properly generate C headers that properly escape the string. Otherwise, the differing escaping rules and differences between PHP's single and double quoted strings could lead to mangled headers.

The output of these strings after the stub has been generated:

string(22) "BEGIN ��\$"AAA END"
string(43) "BEGIN \n\r\t\v\e\f\\\\$\"\101\x41\u{41} END"

And the generated arginfo:

zend_string*property_doubleQuoteEscaped_default_value_str=zend_string_init("BEGIN \n\r\t\v\x1b\f\\$\"AAA END", strlen("BEGIN \n\r\t\v\x1b\f\\$\"AAA END"), 1);
ppZVAL_STR(&property_doubleQuoteEscaped_default_value, property_doubleQuoteEscaped_default_value_str);
zend_string*property_doubleQuoteEscaped_name=zend_string_init("doubleQuoteEscaped", sizeof("doubleQuoteEscaped") -1, true);
zend_declare_typed_property(class_entry, property_doubleQuoteEscaped_name, &property_doubleQuoteEscaped_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING));
zend_string_release_ex(property_doubleQuoteEscaped_name, true);
zvalproperty_singleQuoteEscaped_default_value;
zend_string*property_singleQuoteEscaped_default_value_str=zend_string_init("BEGIN \\n\\r\\t\\v\\e\\f\\\\\\\\$\\\"\\101\\x41\\u{41} END", strlen("BEGIN \\n\\r\\t\\v\\e\\f\\\\\\\\$\\\"\\101\\x41\\u{41} END"), 1);
ZVAL_STR(&property_singleQuoteEscaped_default_value, property_singleQuoteEscaped_default_value_str);
zend_string*property_singleQuoteEscaped_name=zend_string_init("singleQuoteEscaped", sizeof("singleQuoteEscaped") -1, true);
zend_declare_typed_property(class_entry, property_singleQuoteEscaped_name, &property_singleQuoteEscaped_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING));
zend_string_release_ex(property_singleQuoteEscaped_name, true);

Note that the PHP escape sequence "$" will be handled in a special manner to avoid providing it to C, to avoid C compiler warnings.

Tests are included via the zend_test stub and a phpt file to ensure that the escape sequences match.

FixesGH-22169.

@TimWolla

Copy link
Copy Markdown
Member

I'm also unsure how best to make tests for gen_stub, so I haven't included any beyond mentioning how to test manually with this commit.

Add it to the ext/zend_test stub.

Comment threadext/zend_test/test.stub.php

@kocsismatekocsismate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but LGTM otherwise, thank you!

Comment threadext/zend_test/test.stub.php Outdated
Comment threadext/zend_test/test.stub.php Outdated
@NattyNarwhal
NattyNarwhalforce-pushed the gen-stub-string-escape branch from 8ac2225 to 3e50b9cCompareJune 13, 2026 22:17
@NattyNarwhal
NattyNarwhal marked this pull request as ready for review June 13, 2026 22:24
When handling sequences like this in a stub:
```php
<?php
class Whatever {
public static string $foobar1 = "CCC \n\r\t\v\e\f\\\$\"\101\x41\u{41} CCC";
public static string $foobar2 = 'CCC \n\r\t\v\e\f\\\$\"\101\x41\u{41} CCC';
}
```
...properly generate C headers that properly escape the string.
Otherwise, the differing escaping rules and differences between PHP's
single and double quoted strings could lead to mangled headers.
The output of these strings after the stub has been generated:
```
string(22) "BEGIN
��\$"AAA END"
string(43) "BEGIN \n\r\t\v\e\f\\\\$\"\101\x41\u{41} END"
```
And the generated arginfo:
```c
zval property_doubleQuoteEscaped_default_value;
zend_string *property_doubleQuoteEscaped_default_value_str = zend_string_init("BEGIN \n\r\t\v\x1b\f\\$\"AAA END", strlen("BEGIN \n\r\t\v\x1b\f\\$\"AAA END"), 1);
pp ZVAL_STR(&property_doubleQuoteEscaped_default_value, property_doubleQuoteEscaped_default_value_str);
zend_string *property_doubleQuoteEscaped_name = zend_string_init("doubleQuoteEscaped", sizeof("doubleQuoteEscaped") - 1, true);
zend_declare_typed_property(class_entry, property_doubleQuoteEscaped_name, &property_doubleQuoteEscaped_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING));
zend_string_release_ex(property_doubleQuoteEscaped_name, true);
zval property_singleQuoteEscaped_default_value;
zend_string *property_singleQuoteEscaped_default_value_str = zend_string_init("BEGIN \\n\\r\\t\\v\\e\\f\\\\\\\\$\\\"\\101\\x41\\u{41} END", strlen("BEGIN \\n\\r\\t\\v\\e\\f\\\\\\\\$\\\"\\101\\x41\\u{41} END"), 1);
ZVAL_STR(&property_singleQuoteEscaped_default_value, property_singleQuoteEscaped_default_value_str);
zend_string *property_singleQuoteEscaped_name = zend_string_init("singleQuoteEscaped", sizeof("singleQuoteEscaped") - 1, true);
zend_declare_typed_property(class_entry, property_singleQuoteEscaped_name, &property_singleQuoteEscaped_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING));
zend_string_release_ex(property_singleQuoteEscaped_name, true);
```
Note that the PHP escape sequence "\$" will be handled in a special
manner to avoid providing it to C, to avoid C compiler warnings.
Tests are included via the zend_test stub and a phpt file to ensure that
the escape sequences match.
FixesphpGH-22169.
@NattyNarwhal
NattyNarwhalforce-pushed the gen-stub-string-escape branch from 3e50b9c to debc17cCompareJune 13, 2026 22:25
@NattyNarwhal
NattyNarwhal merged commit e0113cd into php:masterJun 22, 2026
18 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gen_stub.php generated wrong C string

4 participants

@NattyNarwhal@TimWolla@mvorisek@kocsismate