mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Fix OSS-Fuzz #427814452
Pipe compilation uses a temporary znode with QM_ASSIGN to remove references. Assert compilation wants to look at the operand AST and convert it to a string. However the original AST is lost due to the temporary znode. To solve this we either have to handle this specially in pipe compilation [1], or store the AST anyway somehow. Special casing this either way is not worth the complexity in my opinion, especially as it looks like a dynamic call anyway due to the FCC syntax. [1] Prototype (incomplete) at https://gist.github.com/nielsdos/50dc71718639c3af05db84a4dea6eb71 shows this is not worthwhile in my opinion. Closes GH-18965. Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
This commit is contained in:
parent
f11ea2ae13
commit
8712f4bf19
4 changed files with 57 additions and 1 deletions
3
NEWS
3
NEWS
|
@ -2,6 +2,9 @@ PHP NEWS
|
||||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||
?? ??? ????, PHP 8.5.0alpha2
|
?? ??? ????, PHP 8.5.0alpha2
|
||||||
|
|
||||||
|
- Core:
|
||||||
|
. Fix OSS-Fuzz #427814452 (pipe compilation fails with assert). (nielsdos)
|
||||||
|
|
||||||
- DOM:
|
- DOM:
|
||||||
. Make cloning DOM node lists, maps, and collections fail. (nielsdos)
|
. Make cloning DOM node lists, maps, and collections fail. (nielsdos)
|
||||||
|
|
||||||
|
|
12
Zend/tests/pipe_operator/gh18965.phpt
Normal file
12
Zend/tests/pipe_operator/gh18965.phpt
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
--TEST--
|
||||||
|
GH-18965: ASSERT_CHECK avoids pipe lhs free
|
||||||
|
--INI--
|
||||||
|
zend.assertions=0
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
namespace Foo;
|
||||||
|
range(0, 10) |> assert(...);
|
||||||
|
echo "No leak\n";
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
No leak
|
26
Zend/tests/pipe_operator/oss_fuzz_427814452.phpt
Normal file
26
Zend/tests/pipe_operator/oss_fuzz_427814452.phpt
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
--TEST--
|
||||||
|
OSS-Fuzz #427814452
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
try {
|
||||||
|
false |> assert(...);
|
||||||
|
} catch (\AssertionError $e) {
|
||||||
|
echo $e::class, ": '", $e->getMessage(), "'\n";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
0 |> "assert"(...);
|
||||||
|
} catch (\AssertionError $e) {
|
||||||
|
echo $e::class, ": '", $e->getMessage(), "'\n";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
false |> ("a"."ssert")(...);
|
||||||
|
} catch (\AssertionError $e) {
|
||||||
|
echo $e::class, ": '", $e->getMessage(), "'\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
AssertionError: ''
|
||||||
|
AssertionError: ''
|
||||||
|
AssertionError: ''
|
|
@ -6426,6 +6426,20 @@ static bool can_match_use_jumptable(zend_ast_list *arms) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool zend_is_pipe_optimizable_callable_name(zend_ast *ast)
|
||||||
|
{
|
||||||
|
if (ast->kind == ZEND_AST_ZVAL && Z_TYPE_P(zend_ast_get_zval(ast)) == IS_STRING) {
|
||||||
|
/* Assert compilation adds a message operand, but this is incompatible with the
|
||||||
|
* pipe optimization that uses a temporary znode for the reference elimination.
|
||||||
|
* Therefore, disable the optimization for assert.
|
||||||
|
* Note that "assert" as a name is always treated as fully qualified. */
|
||||||
|
zend_string *str = zend_ast_get_str(ast);
|
||||||
|
return !zend_string_equals_literal_ci(str, "assert");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void zend_compile_pipe(znode *result, zend_ast *ast)
|
static void zend_compile_pipe(znode *result, zend_ast *ast)
|
||||||
{
|
{
|
||||||
zend_ast *operand_ast = ast->child[0];
|
zend_ast *operand_ast = ast->child[0];
|
||||||
|
@ -6453,7 +6467,8 @@ static void zend_compile_pipe(znode *result, zend_ast *ast)
|
||||||
|
|
||||||
/* Turn $foo |> bar(...) into bar($foo). */
|
/* Turn $foo |> bar(...) into bar($foo). */
|
||||||
if (callable_ast->kind == ZEND_AST_CALL
|
if (callable_ast->kind == ZEND_AST_CALL
|
||||||
&& callable_ast->child[1]->kind == ZEND_AST_CALLABLE_CONVERT) {
|
&& callable_ast->child[1]->kind == ZEND_AST_CALLABLE_CONVERT
|
||||||
|
&& zend_is_pipe_optimizable_callable_name(callable_ast->child[0])) {
|
||||||
fcall_ast = zend_ast_create(ZEND_AST_CALL,
|
fcall_ast = zend_ast_create(ZEND_AST_CALL,
|
||||||
callable_ast->child[0], arg_list_ast);
|
callable_ast->child[0], arg_list_ast);
|
||||||
/* Turn $foo |> bar::baz(...) into bar::baz($foo). */
|
/* Turn $foo |> bar::baz(...) into bar::baz($foo). */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue