[RFC] Convert exit (and die) from language constructs to functions (#13483)

RFC: https://wiki.php.net/rfc/exit-as-function
This commit is contained in:
Gina Peter Banyard 2024-08-14 12:44:12 +01:00 committed by GitHub
parent 02177848e4
commit a79c70f574
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
51 changed files with 1839 additions and 1342 deletions

View file

@ -868,7 +868,6 @@ optimize_const_unary_op:
break; break;
case ZEND_RETURN: case ZEND_RETURN:
case ZEND_EXIT:
if (opline->op1_type == IS_TMP_VAR) { if (opline->op1_type == IS_TMP_VAR) {
src = VAR_SOURCE(opline->op1); src = VAR_SOURCE(opline->op1);
if (src && src->opcode == ZEND_QM_ASSIGN) { if (src && src->opcode == ZEND_QM_ASSIGN) {
@ -1221,8 +1220,7 @@ static void zend_jmp_optimization(zend_basic_block *block, zend_op_array *op_arr
target = op_array->opcodes + target_block->start; target = op_array->opcodes + target_block->start;
if ((target->opcode == ZEND_RETURN || if ((target->opcode == ZEND_RETURN ||
target->opcode == ZEND_RETURN_BY_REF || target->opcode == ZEND_RETURN_BY_REF ||
target->opcode == ZEND_GENERATOR_RETURN || target->opcode == ZEND_GENERATOR_RETURN) &&
target->opcode == ZEND_EXIT) &&
!(op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) { !(op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) {
/* JMP L, L: RETURN to immediate RETURN */ /* JMP L, L: RETURN to immediate RETURN */
*last_op = *target; *last_op = *target;

View file

@ -331,7 +331,6 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
case ZEND_RETURN: case ZEND_RETURN:
case ZEND_RETURN_BY_REF: case ZEND_RETURN_BY_REF:
case ZEND_GENERATOR_RETURN: case ZEND_GENERATOR_RETURN:
case ZEND_EXIT:
case ZEND_THROW: case ZEND_THROW:
case ZEND_MATCH_ERROR: case ZEND_MATCH_ERROR:
case ZEND_CATCH: case ZEND_CATCH:

View file

@ -88,8 +88,7 @@ void zend_optimizer_pass3(zend_op_array *op_array, zend_optimizer_ctx *ctx)
MAKE_NOP(opline); MAKE_NOP(opline);
} else if ((target->opcode == ZEND_RETURN || } else if ((target->opcode == ZEND_RETURN ||
target->opcode == ZEND_RETURN_BY_REF || target->opcode == ZEND_RETURN_BY_REF ||
target->opcode == ZEND_GENERATOR_RETURN || target->opcode == ZEND_GENERATOR_RETURN) &&
target->opcode == ZEND_EXIT) &&
!(op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) { !(op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) {
/* JMP L, L: RETURN to immediate RETURN */ /* JMP L, L: RETURN to immediate RETURN */
*opline = *target; *opline = *target;

View file

@ -162,10 +162,6 @@ ZEND_API void zend_analyze_calls(zend_arena **arena, zend_script *script, uint32
call_info->send_unpack = 1; call_info->send_unpack = 1;
} }
break; break;
case ZEND_EXIT:
/* In this case the DO_CALL opcode may have been dropped
* and caller_call_opline will be NULL. */
break;
} }
opline++; opline++;
} }

View file

@ -302,7 +302,6 @@ ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array,
} }
break; break;
case ZEND_MATCH_ERROR: case ZEND_MATCH_ERROR:
case ZEND_EXIT:
case ZEND_THROW: case ZEND_THROW:
/* Don't treat THROW as terminator if it's used in expression context, /* Don't treat THROW as terminator if it's used in expression context,
* as we may lose live ranges when eliminating unreachable code. */ * as we may lose live ranges when eliminating unreachable code. */
@ -506,7 +505,6 @@ ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array,
case ZEND_RETURN: case ZEND_RETURN:
case ZEND_RETURN_BY_REF: case ZEND_RETURN_BY_REF:
case ZEND_GENERATOR_RETURN: case ZEND_GENERATOR_RETURN:
case ZEND_EXIT:
case ZEND_THROW: case ZEND_THROW:
case ZEND_MATCH_ERROR: case ZEND_MATCH_ERROR:
case ZEND_VERIFY_NEVER_TYPE: case ZEND_VERIFY_NEVER_TYPE:

View file

@ -6,6 +6,9 @@ function skipFunction($function): bool {
|| $function === 'readline' || $function === 'readline'
|| $function === 'readline_read_history' || $function === 'readline_read_history'
|| $function === 'readline_write_history' || $function === 'readline_write_history'
/* terminates script */
|| $function === 'exit'
|| $function === 'die'
/* intentionally violate invariants */ /* intentionally violate invariants */
|| $function === 'zend_create_unterminated_string' || $function === 'zend_create_unterminated_string'
|| $function === 'zend_test_array_return' || $function === 'zend_test_array_return'

View file

@ -1,13 +0,0 @@
--TEST--
Bug #79777: String cast exception during die should be handled gracefully
--FILE--
<?php
die(new stdClass);
?>
--EXPECTF--
Fatal error: Uncaught Error: Object of class stdClass could not be converted to string in %s:%d
Stack trace:
#0 {main}
thrown in %s on line %d

View file

@ -0,0 +1,16 @@
--TEST--
Printing AST of die "constant" via assert
--INI--
zend.assertions=1
--FILE--
<?php
try {
assert(0 && die);
} catch (Throwable $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}
?>
--EXPECT--
AssertionError: assert(0 && \exit())

View file

@ -0,0 +1,16 @@
--TEST--
Printing AST of die function via assert
--INI--
zend.assertions=1
--FILE--
<?php
try {
assert(0 && die());
} catch (Throwable $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}
?>
--EXPECT--
AssertionError: assert(0 && \exit())

View file

@ -0,0 +1,16 @@
--TEST--
Printing AST of exit "constant" via assert
--INI--
zend.assertions=1
--FILE--
<?php
try {
assert(0 && exit);
} catch (Throwable $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}
?>
--EXPECT--
AssertionError: assert(0 && \exit())

View file

@ -0,0 +1,16 @@
--TEST--
Printing AST of exit function via assert
--INI--
zend.assertions=1
--FILE--
<?php
try {
assert(0 && exit());
} catch (Throwable $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}
?>
--EXPECT--
AssertionError: assert(0 && \exit())

View file

@ -0,0 +1,37 @@
--TEST--
Can define die and exit as class methods, constants and property
--FILE--
<?php
class Foo {
public $exit;
public $die;
const die = 5;
const exit = 10;
public function exit() {
return 20;
}
public function die() {
return 15;
}
}
var_dump(Foo::die);
var_dump(Foo::exit);
$o = new Foo();
var_dump($o->exit);
var_dump($o->die);
var_dump($o->exit());
var_dump($o->die());
?>
--EXPECT--
int(5)
int(10)
NULL
NULL
int(20)
int(15)

View file

@ -0,0 +1,12 @@
--TEST--
Attempting to define die constant
--FILE--
<?php
const die = 5;
var_dump(die);
?>
--EXPECTF--
Parse error: syntax error, unexpected token "exit", expecting identifier in %s on line %d

View file

@ -0,0 +1,14 @@
--TEST--
Attempting to define die constant in a namespace
--FILE--
<?php
namespace Foo;
const die = 5;
var_dump(die);
?>
--EXPECTF--
Parse error: syntax error, unexpected token "exit", expecting identifier in %s on line %d

View file

@ -0,0 +1,10 @@
--TEST--
Attempting to define die() function
--FILE--
<?php
function die() { }
?>
--EXPECTF--
Parse error: syntax error, unexpected token "exit", expecting "(" in %s on line %d

View file

@ -0,0 +1,14 @@
--TEST--
Attempting to define die() function in a namespace
--FILE--
<?php
namespace Foo;
function die() { }
var_dump(die());
?>
--EXPECTF--
Parse error: syntax error, unexpected token "exit", expecting "(" in %s on line %d

View file

@ -0,0 +1,12 @@
--TEST--
Attempting to define exit constant
--FILE--
<?php
const exit = 5;
var_dump(exit);
?>
--EXPECTF--
Parse error: syntax error, unexpected token "exit", expecting identifier in %s on line %d

View file

@ -0,0 +1,14 @@
--TEST--
Attempting to define exit constant in a namespace
--FILE--
<?php
namespace Foo;
const exit = 5;
var_dump(exit);
?>
--EXPECTF--
Parse error: syntax error, unexpected token "exit", expecting identifier in %s on line %d

View file

@ -0,0 +1,10 @@
--TEST--
Attempting to define exit() function
--FILE--
<?php
function exit() { }
?>
--EXPECTF--
Parse error: syntax error, unexpected token "exit", expecting "(" in %s on line %d

View file

@ -0,0 +1,12 @@
--TEST--
Attempting to define exit() function in a namespace
--FILE--
<?php
namespace Foo;
function exit() { }
?>
--EXPECTF--
Parse error: syntax error, unexpected token "exit", expecting "(" in %s on line %d

View file

@ -0,0 +1,14 @@
--TEST--
Attempting to define a goto label called die
--FILE--
<?php
echo "Before\n";
echo "In between\n";
die:
echo "After\n";
?>
--EXPECTF--
Parse error: syntax error, unexpected token ":" in %s on line %d

View file

@ -0,0 +1,14 @@
--TEST--
Attempting to define a goto label called die and jump to it
--FILE--
<?php
echo "Before\n";
goto die;
echo "In between\n";
die:
echo "After\n";
?>
--EXPECTF--
Parse error: syntax error, unexpected token "exit", expecting identifier in %s on line %d

View file

@ -0,0 +1,14 @@
--TEST--
Attempting to define a goto label called exit
--FILE--
<?php
echo "Before\n";
echo "In between\n";
exit:
echo "After\n";
?>
--EXPECTF--
Parse error: syntax error, unexpected token ":" in %s on line %d

View file

@ -0,0 +1,14 @@
--TEST--
Attempting to define a goto label called exit and jump to it
--FILE--
<?php
echo "Before\n";
goto exit;
echo "In between\n";
exit:
echo "After\n";
?>
--EXPECTF--
Parse error: syntax error, unexpected token "exit", expecting identifier in %s on line %d

View file

@ -0,0 +1,14 @@
--TEST--
Bug #79777: String cast exception during die should be handled gracefully
--FILE--
<?php
try {
die(new stdClass);
} catch (TypeError $e) {
echo $e->getMessage(), PHP_EOL;
}
?>
--EXPECT--
exit(): Argument #1 ($code) must be of type string|int, stdClass given

View file

@ -0,0 +1,12 @@
--TEST--
Using disable_functions INI to remove die
--INI--
disable_functions=die
--FILE--
<?php
die();
?>
--EXPECT--
Warning: Cannot disable function die() in Unknown on line 0

View file

@ -0,0 +1,12 @@
--TEST--
Using disable_functions INI to remove exit
--INI--
disable_functions=exit
--FILE--
<?php
exit();
?>
--EXPECT--
Warning: Cannot disable function exit() in Unknown on line 0

View file

@ -0,0 +1,42 @@
--TEST--
exit() as function
--FILE--
<?php
function foo(callable $fn) {
var_dump($fn);
}
$values = [
'exit',
'die',
exit(...),
die(...),
];
foreach ($values as $value) {
foo($value);
}
?>
--EXPECT--
string(4) "exit"
string(3) "die"
object(Closure)#1 (2) {
["function"]=>
string(4) "exit"
["parameter"]=>
array(1) {
["$code"]=>
string(10) "<optional>"
}
}
object(Closure)#2 (2) {
["function"]=>
string(4) "exit"
["parameter"]=>
array(1) {
["$code"]=>
string(10) "<optional>"
}
}

View file

@ -0,0 +1,46 @@
--TEST--
Using exit/die as a statement/constant
--FILE--
<?php
const FILE_PATH = __DIR__ . '/exit_statements.php';
const FILE_CONTENT = <<<'TEMPLATE'
<?php
echo "Before FUNCTION";
try {
FUNCTION;
} catch (\Throwable $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}
TEMPLATE;
$php = getenv('TEST_PHP_EXECUTABLE_ESCAPED');
$command = $php . ' ' . escapeshellarg(FILE_PATH);
foreach (['exit', 'die'] as $value) {
echo 'Using ', $value, ' as value:', PHP_EOL;
$output = [];
$content = str_replace('FUNCTION', $value, FILE_CONTENT);
file_put_contents(FILE_PATH, $content);
exec($command, $output, $exit_status);
echo 'Exit status is: ', $exit_status, PHP_EOL,
'Output is:', PHP_EOL, join($output), PHP_EOL;
}
?>
--CLEAN--
<?php
const FILE_PATH = __DIR__ . '/exit_statements.php';
@unlink(FILE_PATH);
?>
--EXPECT--
Using exit as value:
Exit status is: 0
Output is:
Before exit
Using die as value:
Exit status is: 0
Output is:
Before die

View file

@ -0,0 +1,23 @@
--TEST--
Throwing output buffer with exit("Message")
--FILE--
<?php
ob_start(function ($text) {
fwrite(STDOUT, "Handler: " . $text);
throw new Exception('test');
}, chunk_size: 10);
try {
exit("Hello world!\n");
} catch (Throwable $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}
echo "After?\n";
?>
--EXPECT--
Handler: Hello world!
Hello world!
Exception: test
After?

View file

@ -0,0 +1,183 @@
--TEST--
exit(false);
--FILE--
<?php
function zend_test_var_export($value) {
if ($value === PHP_INT_MIN) {
return "PHP_INT_MIN";
}
if ($value === PHP_INT_MAX) {
return "PHP_INT_MAX";
}
if (is_array($value)) {
return "[]";
}
if (is_resource($value)) {
return "STDERR";
}
if ($value instanceof stdClass) {
return "new stdClass()";
}
return var_export($value, true);
}
$values = [
null,
false,
true,
0,
1,
20,
10.0,
15.5,
"Hello world",
[],
STDERR,
new stdClass(),
];
const FILE_PATH = __DIR__ . '/exit_values_test.php';
const FILE_CONTENT = <<<'TEMPLATE'
<?php
try {
exit(VALUE);
} catch (\Throwable $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}
TEMPLATE;
$php = getenv('TEST_PHP_EXECUTABLE_ESCAPED');
$command = $php . ' ' . escapeshellarg(FILE_PATH);
foreach ([FILE_CONTENT, str_replace('exit', 'die', FILE_CONTENT)] as $code) {
foreach ($values as $value) {
echo 'Using ', zend_test_var_export($value), ' as value:', PHP_EOL;
$output = [];
$content = str_replace('VALUE', zend_test_var_export($value), $code);
file_put_contents(FILE_PATH, $content);
exec($command, $output, $exit_status);
echo 'Exit status is: ', $exit_status, PHP_EOL,
'Output is:', PHP_EOL, join($output), PHP_EOL;
}
echo 'As a statement:', PHP_EOL;
$output = [];
$content = str_replace('(VALUE)', '', $code);
exec($command, $output, $exit_status);
echo 'Exit status is: ', $exit_status, PHP_EOL,
'Output is:', PHP_EOL, join($output), PHP_EOL;
}
?>
--CLEAN--
<?php
const FILE_PATH = __DIR__ . '/exit_values_test.php';
@unlink(FILE_PATH);
?>
--EXPECTF--
Using NULL as value:
Exit status is: 0
Output is:
Deprecated: exit(): Passing null to parameter #1 ($code) of type string|int is deprecated in %s on line %d
Using false as value:
Exit status is: 0
Output is:
Using true as value:
Exit status is: 1
Output is:
Using 0 as value:
Exit status is: 0
Output is:
Using 1 as value:
Exit status is: 1
Output is:
Using 20 as value:
Exit status is: 20
Output is:
Using 10.0 as value:
Exit status is: 10
Output is:
Using 15.5 as value:
Exit status is: 15
Output is:
Deprecated: Implicit conversion from float 15.5 to int loses precision in %s on line %d
Using 'Hello world' as value:
Exit status is: 0
Output is:
Hello world
Using [] as value:
Exit status is: 0
Output is:
TypeError: exit(): Argument #1 ($code) must be of type string|int, array given
Using STDERR as value:
Exit status is: 0
Output is:
TypeError: exit(): Argument #1 ($code) must be of type string|int, resource given
Using new stdClass() as value:
Exit status is: 0
Output is:
TypeError: exit(): Argument #1 ($code) must be of type string|int, stdClass given
As a statement:
Exit status is: 0
Output is:
TypeError: exit(): Argument #1 ($code) must be of type string|int, stdClass given
Using NULL as value:
Exit status is: 0
Output is:
Deprecated: exit(): Passing null to parameter #1 ($code) of type string|int is deprecated in %s on line %d
Using false as value:
Exit status is: 0
Output is:
Using true as value:
Exit status is: 1
Output is:
Using 0 as value:
Exit status is: 0
Output is:
Using 1 as value:
Exit status is: 1
Output is:
Using 20 as value:
Exit status is: 20
Output is:
Using 10.0 as value:
Exit status is: 10
Output is:
Using 15.5 as value:
Exit status is: 15
Output is:
Deprecated: Implicit conversion from float 15.5 to int loses precision in %s on line %d
Using 'Hello world' as value:
Exit status is: 0
Output is:
Hello world
Using [] as value:
Exit status is: 0
Output is:
TypeError: exit(): Argument #1 ($code) must be of type string|int, array given
Using STDERR as value:
Exit status is: 0
Output is:
TypeError: exit(): Argument #1 ($code) must be of type string|int, resource given
Using new stdClass() as value:
Exit status is: 0
Output is:
TypeError: exit(): Argument #1 ($code) must be of type string|int, stdClass given
As a statement:
Exit status is: 0
Output is:
TypeError: exit(): Argument #1 ($code) must be of type string|int, stdClass given

View file

@ -3605,6 +3605,13 @@ ZEND_API zend_result zend_set_hash_symbol(zval *symbol, const char *name, size_t
static void zend_disable_function(const char *function_name, size_t function_name_length) static void zend_disable_function(const char *function_name, size_t function_name_length)
{ {
if (UNEXPECTED(
(function_name_length == strlen("exit") && !memcmp(function_name, "exit", strlen("exit")))
|| (function_name_length == strlen("die") && !memcmp(function_name, "die", strlen("die")))
)) {
zend_error(E_WARNING, "Cannot disable function %s()", function_name);
return;
}
zend_hash_str_del(CG(function_table), function_name, function_name_length); zend_hash_str_del(CG(function_table), function_name, function_name_length);
} }

View file

@ -69,6 +69,33 @@ zend_result zend_startup_builtin_functions(void) /* {{{ */
} }
/* }}} */ /* }}} */
ZEND_FUNCTION(exit)
{
zend_string *str = NULL;
zend_long code = 0;
ZEND_PARSE_PARAMETERS_START(0, 1)
Z_PARAM_OPTIONAL
Z_PARAM_STR_OR_LONG(str, code)
ZEND_PARSE_PARAMETERS_END();
if (str) {
size_t len = ZSTR_LEN(str);
if (len != 0) {
/* An exception might be emitted by an output handler */
zend_write(ZSTR_VAL(str), len);
if (EG(exception)) {
RETURN_THROWS();
}
}
} else {
EG(exit_status) = code;
}
ZEND_ASSERT(!EG(exception));
zend_throw_unwind_exit();
}
/* {{{ Get the version of the Zend Engine */ /* {{{ Get the version of the Zend Engine */
ZEND_FUNCTION(zend_version) ZEND_FUNCTION(zend_version)
{ {

View file

@ -7,6 +7,11 @@ class stdClass
{ {
} }
function exit(string|int $code = 0): never {}
/** @alias exit */
function die(string|int $code = 0): never {}
/** @refcount 1 */ /** @refcount 1 */
function zend_version(): string {} function zend_version(): string {}

View file

@ -1,5 +1,11 @@
/* This is a generated file, edit the .stub.php file instead. /* This is a generated file, edit the .stub.php file instead.
* Stub hash: c3bec3b17079456ef17e5c992995dcfbe62c6fe0 */ * Stub hash: a6d7e59d6b7875ddc28ce828ae240c7dfd852023 */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_exit, 0, 0, IS_NEVER, 0)
ZEND_ARG_TYPE_MASK(0, code, MAY_BE_STRING|MAY_BE_LONG, "0")
ZEND_END_ARG_INFO()
#define arginfo_die arginfo_exit
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_version, 0, 0, IS_STRING, 0) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_version, 0, 0, IS_STRING, 0)
ZEND_END_ARG_INFO() ZEND_END_ARG_INFO()
@ -232,6 +238,7 @@ static const zend_frameless_function_info frameless_function_infos_class_exists[
{ 0 }, { 0 },
}; };
ZEND_FUNCTION(exit);
ZEND_FUNCTION(zend_version); ZEND_FUNCTION(zend_version);
ZEND_FUNCTION(func_num_args); ZEND_FUNCTION(func_num_args);
ZEND_FUNCTION(func_get_arg); ZEND_FUNCTION(func_get_arg);
@ -292,6 +299,8 @@ ZEND_FUNCTION(gc_disable);
ZEND_FUNCTION(gc_status); ZEND_FUNCTION(gc_status);
static const zend_function_entry ext_functions[] = { static const zend_function_entry ext_functions[] = {
ZEND_FE(exit, arginfo_exit)
ZEND_RAW_FENTRY("die", zif_exit, arginfo_die, 0, NULL, NULL)
ZEND_FE(zend_version, arginfo_zend_version) ZEND_FE(zend_version, arginfo_zend_version)
ZEND_FE(func_num_args, arginfo_func_num_args) ZEND_FE(func_num_args, arginfo_func_num_args)
ZEND_FE(func_get_arg, arginfo_func_get_arg) ZEND_FE(func_get_arg, arginfo_func_get_arg)

View file

@ -10376,27 +10376,6 @@ static void zend_compile_print(znode *result, zend_ast *ast) /* {{{ */
} }
/* }}} */ /* }}} */
static void zend_compile_exit(znode *result, zend_ast *ast) /* {{{ */
{
zend_ast *expr_ast = ast->child[0];
znode expr_node;
if (expr_ast) {
zend_compile_expr(&expr_node, expr_ast);
} else {
expr_node.op_type = IS_UNUSED;
}
zend_op *opline = zend_emit_op(NULL, ZEND_EXIT, &expr_node, NULL);
if (result) {
/* Mark this as an "expression throw" for opcache. */
opline->extended_value = ZEND_THROW_IS_EXPR;
result->op_type = IS_CONST;
ZVAL_TRUE(&result->u.constant);
}
}
/* }}} */
static void zend_compile_yield(znode *result, zend_ast *ast) /* {{{ */ static void zend_compile_yield(znode *result, zend_ast *ast) /* {{{ */
{ {
zend_ast *value_ast = ast->child[0]; zend_ast *value_ast = ast->child[0];
@ -11366,7 +11345,6 @@ static void zend_compile_stmt(zend_ast *ast) /* {{{ */
zend_compile_halt_compiler(ast); zend_compile_halt_compiler(ast);
break; break;
case ZEND_AST_THROW: case ZEND_AST_THROW:
case ZEND_AST_EXIT:
zend_compile_expr(NULL, ast); zend_compile_expr(NULL, ast);
break; break;
default: default:
@ -11469,9 +11447,6 @@ static void zend_compile_expr_inner(znode *result, zend_ast *ast) /* {{{ */
case ZEND_AST_PRINT: case ZEND_AST_PRINT:
zend_compile_print(result, ast); zend_compile_print(result, ast);
return; return;
case ZEND_AST_EXIT:
zend_compile_exit(result, ast);
return;
case ZEND_AST_YIELD: case ZEND_AST_YIELD:
zend_compile_yield(result, ast); zend_compile_yield(result, ast);
return; return;

View file

@ -258,7 +258,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%type <ast> absolute_trait_method_reference trait_method_reference property echo_expr %type <ast> absolute_trait_method_reference trait_method_reference property echo_expr
%type <ast> new_dereferenceable new_non_dereferenceable anonymous_class class_name class_name_reference simple_variable %type <ast> new_dereferenceable new_non_dereferenceable anonymous_class class_name class_name_reference simple_variable
%type <ast> internal_functions_in_yacc %type <ast> internal_functions_in_yacc
%type <ast> exit_expr scalar backticks_expr lexical_var function_call member_name property_name %type <ast> scalar backticks_expr lexical_var function_call member_name property_name
%type <ast> variable_class_name dereferenceable_scalar constant class_constant %type <ast> variable_class_name dereferenceable_scalar constant class_constant
%type <ast> fully_dereferenceable array_object_dereferenceable %type <ast> fully_dereferenceable array_object_dereferenceable
%type <ast> callable_expr callable_variable static_member new_variable %type <ast> callable_expr callable_variable static_member new_variable
@ -1304,7 +1304,11 @@ expr:
| T_OBJECT_CAST expr { $$ = zend_ast_create_cast(IS_OBJECT, $2); } | T_OBJECT_CAST expr { $$ = zend_ast_create_cast(IS_OBJECT, $2); }
| T_BOOL_CAST expr { $$ = zend_ast_create_cast(_IS_BOOL, $2); } | T_BOOL_CAST expr { $$ = zend_ast_create_cast(_IS_BOOL, $2); }
| T_UNSET_CAST expr { $$ = zend_ast_create_cast(IS_NULL, $2); } | T_UNSET_CAST expr { $$ = zend_ast_create_cast(IS_NULL, $2); }
| T_EXIT exit_expr { $$ = zend_ast_create(ZEND_AST_EXIT, $2); } | T_EXIT ctor_arguments {
zend_ast *name = zend_ast_create_zval_from_str(ZSTR_KNOWN(ZEND_STR_EXIT));
name->attr = ZEND_NAME_FQ;
$$ = zend_ast_create(ZEND_AST_CALL, name, $2);
}
| '@' expr { $$ = zend_ast_create(ZEND_AST_SILENCE, $2); } | '@' expr { $$ = zend_ast_create(ZEND_AST_SILENCE, $2); }
| scalar { $$ = $1; } | scalar { $$ = $1; }
| '`' backticks_expr '`' { $$ = zend_ast_create(ZEND_AST_SHELL_EXEC, $2); } | '`' backticks_expr '`' { $$ = zend_ast_create(ZEND_AST_SHELL_EXEC, $2); }
@ -1407,11 +1411,6 @@ class_name_reference:
| '(' expr ')' { $$ = $2; } | '(' expr ')' { $$ = $2; }
; ;
exit_expr:
%empty { $$ = NULL; }
| '(' optional_expr ')' { $$ = $2; }
;
backticks_expr: backticks_expr:
%empty %empty
{ $$ = zend_ast_create_zval_from_str(ZSTR_EMPTY_ALLOC()); } { $$ = zend_ast_create_zval_from_str(ZSTR_EMPTY_ALLOC()); }

View file

@ -572,6 +572,7 @@ EMPTY_SWITCH_DEFAULT_CASE()
_(ZEND_STR_ARGS, "args") \ _(ZEND_STR_ARGS, "args") \
_(ZEND_STR_UNKNOWN, "unknown") \ _(ZEND_STR_UNKNOWN, "unknown") \
_(ZEND_STR_UNKNOWN_CAPITALIZED, "Unknown") \ _(ZEND_STR_UNKNOWN_CAPITALIZED, "Unknown") \
_(ZEND_STR_EXIT, "exit") \
_(ZEND_STR_EVAL, "eval") \ _(ZEND_STR_EVAL, "eval") \
_(ZEND_STR_INCLUDE, "include") \ _(ZEND_STR_INCLUDE, "include") \
_(ZEND_STR_REQUIRE, "require") \ _(ZEND_STR_REQUIRE, "require") \

View file

@ -7610,38 +7610,6 @@ ZEND_VM_C_LABEL(array_key_exists_array):
ZEND_VM_SMART_BRANCH(result, 1); ZEND_VM_SMART_BRANCH(result, 1);
} }
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
ZEND_VM_COLD_HANDLER(79, ZEND_EXIT, ANY, ANY)
{
USE_OPLINE
SAVE_OPLINE();
if (OP1_TYPE != IS_UNUSED) {
zval *ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
do {
if (Z_TYPE_P(ptr) == IS_LONG) {
EG(exit_status) = Z_LVAL_P(ptr);
} else {
if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(ptr)) {
ptr = Z_REFVAL_P(ptr);
if (Z_TYPE_P(ptr) == IS_LONG) {
EG(exit_status) = Z_LVAL_P(ptr);
break;
}
}
zend_print_zval(ptr, 0);
}
} while (0);
FREE_OP1();
}
if (!EG(exception)) {
zend_throw_unwind_exit();
}
HANDLE_EXCEPTION();
}
ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY) ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY)
{ {
USE_OPLINE USE_OPLINE

429
Zend/zend_vm_execute.h generated
View file

@ -3013,37 +3013,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC
ZEND_VM_SMART_BRANCH(result, 1); ZEND_VM_SMART_BRANCH(result, 1);
} }
static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXIT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
SAVE_OPLINE();
if (opline->op1_type != IS_UNUSED) {
zval *ptr = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R);
do {
if (Z_TYPE_P(ptr) == IS_LONG) {
EG(exit_status) = Z_LVAL_P(ptr);
} else {
if ((opline->op1_type & (IS_VAR|IS_CV)) && Z_ISREF_P(ptr)) {
ptr = Z_REFVAL_P(ptr);
if (Z_TYPE_P(ptr) == IS_LONG) {
EG(exit_status) = Z_LVAL_P(ptr);
break;
}
}
zend_print_zval(ptr, 0);
}
} while (0);
FREE_OP(opline->op1_type, opline->op1.var);
}
if (!EG(exception)) {
zend_throw_unwind_exit();
}
HANDLE_EXCEPTION();
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{ {
USE_OPLINE USE_OPLINE
@ -7930,7 +7899,6 @@ array_key_exists_array:
ZEND_VM_SMART_BRANCH(result, 1); ZEND_VM_SMART_BRANCH(result, 1);
} }
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{ {
USE_OPLINE USE_OPLINE
@ -10307,7 +10275,6 @@ array_key_exists_array:
ZEND_VM_SMART_BRANCH(result, 1); ZEND_VM_SMART_BRANCH(result, 1);
} }
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{ {
USE_OPLINE USE_OPLINE
@ -12788,7 +12755,6 @@ array_key_exists_array:
ZEND_VM_SMART_BRANCH(result, 1); ZEND_VM_SMART_BRANCH(result, 1);
} }
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{ {
USE_OPLINE USE_OPLINE
@ -16950,7 +16916,6 @@ array_key_exists_array:
ZEND_VM_SMART_BRANCH(result, 1); ZEND_VM_SMART_BRANCH(result, 1);
} }
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{ {
USE_OPLINE USE_OPLINE
@ -18417,7 +18382,6 @@ array_key_exists_array:
ZEND_VM_SMART_BRANCH(result, 1); ZEND_VM_SMART_BRANCH(result, 1);
} }
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{ {
USE_OPLINE USE_OPLINE
@ -19824,7 +19788,6 @@ array_key_exists_array:
ZEND_VM_SMART_BRANCH(result, 1); ZEND_VM_SMART_BRANCH(result, 1);
} }
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{ {
USE_OPLINE USE_OPLINE
@ -45235,7 +45198,6 @@ array_key_exists_array:
ZEND_VM_SMART_BRANCH(result, 1); ZEND_VM_SMART_BRANCH(result, 1);
} }
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{ {
USE_OPLINE USE_OPLINE
@ -48963,7 +48925,6 @@ array_key_exists_array:
ZEND_VM_SMART_BRANCH(result, 1); ZEND_VM_SMART_BRANCH(result, 1);
} }
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{ {
USE_OPLINE USE_OPLINE
@ -54527,7 +54488,6 @@ array_key_exists_array:
ZEND_VM_SMART_BRANCH(result, 1); ZEND_VM_SMART_BRANCH(result, 1);
} }
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{ {
USE_OPLINE USE_OPLINE
@ -56322,7 +56282,6 @@ ZEND_API void execute_ex(zend_execute_data *ex)
(void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL,
(void*)&&ZEND_FE_RESET_R_SPEC_CV_LABEL, (void*)&&ZEND_FE_RESET_R_SPEC_CV_LABEL,
(void*)&&ZEND_FE_FETCH_R_SPEC_VAR_LABEL, (void*)&&ZEND_FE_FETCH_R_SPEC_VAR_LABEL,
(void*)&&ZEND_EXIT_SPEC_LABEL,
(void*)&&ZEND_FETCH_R_SPEC_CONST_UNUSED_LABEL, (void*)&&ZEND_FETCH_R_SPEC_CONST_UNUSED_LABEL,
(void*)&&ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_LABEL, (void*)&&ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_LABEL,
(void*)&&ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_LABEL, (void*)&&ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_LABEL,
@ -58572,11 +58531,6 @@ zend_leave_helper_SPEC_LABEL:
ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
VM_TRACE_OP_END(ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC) VM_TRACE_OP_END(ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC)
HYBRID_BREAK(); HYBRID_BREAK();
HYBRID_CASE(ZEND_EXIT_SPEC):
VM_TRACE(ZEND_EXIT_SPEC)
ZEND_EXIT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
VM_TRACE_OP_END(ZEND_EXIT_SPEC)
HYBRID_BREAK();
HYBRID_CASE(ZEND_BEGIN_SILENCE_SPEC): HYBRID_CASE(ZEND_BEGIN_SILENCE_SPEC):
VM_TRACE(ZEND_BEGIN_SILENCE_SPEC) VM_TRACE(ZEND_BEGIN_SILENCE_SPEC)
ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@ -65515,7 +65469,6 @@ void zend_vm_init(void)
ZEND_NULL_HANDLER, ZEND_NULL_HANDLER,
ZEND_FE_RESET_R_SPEC_CV_HANDLER, ZEND_FE_RESET_R_SPEC_CV_HANDLER,
ZEND_FE_FETCH_R_SPEC_VAR_HANDLER, ZEND_FE_FETCH_R_SPEC_VAR_HANDLER,
ZEND_EXIT_SPEC_HANDLER,
ZEND_FETCH_R_SPEC_CONST_UNUSED_HANDLER, ZEND_FETCH_R_SPEC_CONST_UNUSED_HANDLER,
ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER,
ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER,
@ -67460,7 +67413,7 @@ void zend_vm_init(void)
1255, 1255,
1256 | SPEC_RULE_OP1, 1256 | SPEC_RULE_OP1,
1261 | SPEC_RULE_OP1, 1261 | SPEC_RULE_OP1,
3487, 3486,
1266 | SPEC_RULE_OP1, 1266 | SPEC_RULE_OP1,
1271 | SPEC_RULE_OP1, 1271 | SPEC_RULE_OP1,
1276 | SPEC_RULE_OP2, 1276 | SPEC_RULE_OP2,
@ -67494,100 +67447,101 @@ void zend_vm_init(void)
1559 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1559 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1584 | SPEC_RULE_OP1, 1584 | SPEC_RULE_OP1,
1589, 1589,
1590, 3486,
1591 | SPEC_RULE_OP1, 1590 | SPEC_RULE_OP1,
1596 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1595 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1621 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1620 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1646 | SPEC_RULE_OP1, 1645 | SPEC_RULE_OP1,
1651 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1650 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1676 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1675 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1701 | SPEC_RULE_OP1, 1700 | SPEC_RULE_OP1,
1706 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1705 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1731 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1730 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1756 | SPEC_RULE_OP1, 1755 | SPEC_RULE_OP1,
1761 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1760 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1786 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1785 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1811 | SPEC_RULE_OP1, 1810 | SPEC_RULE_OP1,
1816 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1815 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1841 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1840 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1866 | SPEC_RULE_OP1, 1865 | SPEC_RULE_OP1,
1871 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1870 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1896 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1895 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1921 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1920 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1946, 1945,
1947 | SPEC_RULE_OP2 | SPEC_RULE_QUICK_ARG, 1946 | SPEC_RULE_OP2 | SPEC_RULE_QUICK_ARG,
1956,
1957, 1957,
1958, 1958,
1959, 1959,
1960, 1960,
1961, 1961 | SPEC_RULE_OP2,
1962 | SPEC_RULE_OP2, 1966,
1967, 1967 | SPEC_RULE_OP1,
1968 | SPEC_RULE_OP1, 1972 | SPEC_RULE_OP2,
1973 | SPEC_RULE_OP2, 1977 | SPEC_RULE_OP1,
1978 | SPEC_RULE_OP1, 1982 | SPEC_RULE_OP1 | SPEC_RULE_OBSERVER,
1983 | SPEC_RULE_OP1 | SPEC_RULE_OBSERVER, 1992 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1993 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2017 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2018 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2042 | SPEC_RULE_OP1,
2043 | SPEC_RULE_OP1, 2047 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2048 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2072 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_QUICK_ARG,
2073 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_QUICK_ARG, 2122 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2123 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2147 | SPEC_RULE_OP2,
2148 | SPEC_RULE_OP2, 2152,
2153, 2153 | SPEC_RULE_OP1,
2154 | SPEC_RULE_OP1, 2158 | SPEC_RULE_OP1,
2159 | SPEC_RULE_OP1, 2163,
2164, 2164 | SPEC_RULE_OP1,
2165 | SPEC_RULE_OP1, 2169 | SPEC_RULE_OP1,
2170 | SPEC_RULE_OP1, 2174 | SPEC_RULE_OP1,
2175 | SPEC_RULE_OP1, 2179,
2180, 2180,
2181, 2181 | SPEC_RULE_OP2,
2182 | SPEC_RULE_OP2, 2186 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER,
2187 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER, 2190 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER,
2191 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER, 2194 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER,
2195 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER, 2198 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2199 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2198 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2199 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2223 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2224 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2223 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2224 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2248 | SPEC_RULE_OP1,
2249 | SPEC_RULE_OP1, 2253,
2254, 2254 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2255 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2279,
2280, 2280 | SPEC_RULE_OP1,
2281 | SPEC_RULE_OP1, 2285,
2286, 2286,
2287, 2287,
2288, 2288,
2289, 2289,
2290, 2290,
2291, 2291,
2292, 2292 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2293 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2317,
2318, 2318,
2319, 2319,
2320, 2320 | SPEC_RULE_OP1,
2321 | SPEC_RULE_OP1, 2325,
2326, 2326 | SPEC_RULE_ISSET,
2327 | SPEC_RULE_ISSET, 2328 | SPEC_RULE_OP2,
2329 | SPEC_RULE_OP2, 2333,
2334, 2334 | SPEC_RULE_OP1,
2335 | SPEC_RULE_OP1, 2339 | SPEC_RULE_OBSERVER,
2340 | SPEC_RULE_OBSERVER, 2341,
2342, 2342 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2343 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2367 | SPEC_RULE_OP1 | SPEC_RULE_OBSERVER,
2368 | SPEC_RULE_OP1 | SPEC_RULE_OBSERVER, 2377,
2378, 2378,
2379, 2379,
2380, 2380,
2381, 2381 | SPEC_RULE_OP1,
2382 | SPEC_RULE_OP1, 2386,
2387, 2387,
2388, 2388 | SPEC_RULE_OP1,
2389 | SPEC_RULE_OP1, 2393 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2394 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2418,
2419, 2419 | SPEC_RULE_OP1,
2420 | SPEC_RULE_OP1, 2424,
2425, 2425,
2426, 2426,
2427, 2427,
@ -67595,82 +67549,81 @@ void zend_vm_init(void)
2429, 2429,
2430, 2430,
2431, 2431,
2432, 2432 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2433 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2457,
2458, 2458,
2459, 2459,
2460, 2460 | SPEC_RULE_OP2,
2461 | SPEC_RULE_OP2, 2465,
2466, 2466 | SPEC_RULE_OP1,
2467 | SPEC_RULE_OP1, 2471 | SPEC_RULE_OP1,
2472 | SPEC_RULE_OP1, 2476 | SPEC_RULE_OP1,
2477 | SPEC_RULE_OP1, 2481 | SPEC_RULE_OP1,
2482 | SPEC_RULE_OP1, 2486 | SPEC_RULE_OP1,
2487 | SPEC_RULE_OP1, 2491,
2492, 2492 | SPEC_RULE_OP1,
2493 | SPEC_RULE_OP1, 2497 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2498 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2522 | SPEC_RULE_OP1,
2523 | SPEC_RULE_OP1, 2527 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2528 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2552 | SPEC_RULE_OP1,
2553 | SPEC_RULE_OP1, 2557 | SPEC_RULE_OP1,
2558 | SPEC_RULE_OP1, 2562,
2563, 2563,
2564, 2564,
2565, 2565,
2566, 2566,
2567, 2567 | SPEC_RULE_OBSERVER,
2568 | SPEC_RULE_OBSERVER, 2569 | SPEC_RULE_OBSERVER,
2570 | SPEC_RULE_OBSERVER, 2571 | SPEC_RULE_OBSERVER,
2572 | SPEC_RULE_OBSERVER, 2573 | SPEC_RULE_OBSERVER,
2574 | SPEC_RULE_OBSERVER, 2575,
2576, 2576,
2577, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487, 3486,
3487,
}; };
#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)
zend_opcode_handler_funcs = labels; zend_opcode_handler_funcs = labels;
@ -67843,7 +67796,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 2586 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; spec = 2585 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
if (op->op1_type < op->op2_type) { if (op->op1_type < op->op2_type) {
zend_swap_operands(op); zend_swap_operands(op);
} }
@ -67851,7 +67804,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 2611 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; spec = 2610 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
if (op->op1_type < op->op2_type) { if (op->op1_type < op->op2_type) {
zend_swap_operands(op); zend_swap_operands(op);
} }
@ -67859,7 +67812,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 2636 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; spec = 2635 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
if (op->op1_type < op->op2_type) { if (op->op1_type < op->op2_type) {
zend_swap_operands(op); zend_swap_operands(op);
} }
@ -67870,17 +67823,17 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 2661 | SPEC_RULE_OP1 | SPEC_RULE_OP2; spec = 2660 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
} else if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) { } else if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 2686 | SPEC_RULE_OP1 | SPEC_RULE_OP2; spec = 2685 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 2711 | SPEC_RULE_OP1 | SPEC_RULE_OP2; spec = 2710 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
} }
break; break;
case ZEND_MUL: case ZEND_MUL:
@ -67891,17 +67844,17 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 2736 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; spec = 2735 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
} else if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) { } else if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 2761 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; spec = 2760 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 2786 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; spec = 2785 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
} }
break; break;
case ZEND_IS_IDENTICAL: case ZEND_IS_IDENTICAL:
@ -67912,14 +67865,14 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 2811 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; spec = 2810 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 2886 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; spec = 2885 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
} else if (op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF))) { } else if (op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF))) {
spec = 3111 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; spec = 3110 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
} }
break; break;
case ZEND_IS_NOT_IDENTICAL: case ZEND_IS_NOT_IDENTICAL:
@ -67930,14 +67883,14 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 2961 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; spec = 2960 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 3036 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; spec = 3035 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
} else if (op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF))) { } else if (op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF))) {
spec = 3116 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; spec = 3115 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
} }
break; break;
case ZEND_IS_EQUAL: case ZEND_IS_EQUAL:
@ -67948,12 +67901,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 2811 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; spec = 2810 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 2886 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; spec = 2885 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
} }
break; break;
case ZEND_IS_NOT_EQUAL: case ZEND_IS_NOT_EQUAL:
@ -67964,12 +67917,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 2961 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; spec = 2960 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 3036 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; spec = 3035 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
} }
break; break;
case ZEND_IS_SMALLER: case ZEND_IS_SMALLER:
@ -67977,12 +67930,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 3121 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; spec = 3120 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 3196 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; spec = 3195 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
} }
break; break;
case ZEND_IS_SMALLER_OR_EQUAL: case ZEND_IS_SMALLER_OR_EQUAL:
@ -67990,79 +67943,79 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 3271 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; spec = 3270 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 3346 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; spec = 3345 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
} }
break; break;
case ZEND_QM_ASSIGN: case ZEND_QM_ASSIGN:
if (op1_info == MAY_BE_LONG) { if (op1_info == MAY_BE_LONG) {
spec = 3433 | SPEC_RULE_OP1; spec = 3432 | SPEC_RULE_OP1;
} else if (op1_info == MAY_BE_DOUBLE) { } else if (op1_info == MAY_BE_DOUBLE) {
spec = 3438 | SPEC_RULE_OP1; spec = 3437 | SPEC_RULE_OP1;
} else if ((op->op1_type == IS_CONST) ? !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1)) : (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE))))) { } else if ((op->op1_type == IS_CONST) ? !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1)) : (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE))))) {
spec = 3443 | SPEC_RULE_OP1; spec = 3442 | SPEC_RULE_OP1;
} }
break; break;
case ZEND_PRE_INC: case ZEND_PRE_INC:
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
spec = 3421 | SPEC_RULE_RETVAL; spec = 3420 | SPEC_RULE_RETVAL;
} else if (op1_info == MAY_BE_LONG) { } else if (op1_info == MAY_BE_LONG) {
spec = 3423 | SPEC_RULE_RETVAL; spec = 3422 | SPEC_RULE_RETVAL;
} }
break; break;
case ZEND_PRE_DEC: case ZEND_PRE_DEC:
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
spec = 3425 | SPEC_RULE_RETVAL; spec = 3424 | SPEC_RULE_RETVAL;
} else if (op1_info == MAY_BE_LONG) { } else if (op1_info == MAY_BE_LONG) {
spec = 3427 | SPEC_RULE_RETVAL; spec = 3426 | SPEC_RULE_RETVAL;
} }
break; break;
case ZEND_POST_INC: case ZEND_POST_INC:
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
spec = 3429; spec = 3428;
} else if (op1_info == MAY_BE_LONG) { } else if (op1_info == MAY_BE_LONG) {
spec = 3430; spec = 3429;
} }
break; break;
case ZEND_POST_DEC: case ZEND_POST_DEC:
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
spec = 3431; spec = 3430;
} else if (op1_info == MAY_BE_LONG) { } else if (op1_info == MAY_BE_LONG) {
spec = 3432; spec = 3431;
} }
break; break;
case ZEND_JMP: case ZEND_JMP:
if (OP_JMP_ADDR(op, op->op1) > op) { if (OP_JMP_ADDR(op, op->op1) > op) {
spec = 2585; spec = 2584;
} }
break; break;
case ZEND_INIT_FCALL: case ZEND_INIT_FCALL:
if (Z_EXTRA_P(RT_CONSTANT(op, op->op2)) != 0) { if (Z_EXTRA_P(RT_CONSTANT(op, op->op2)) != 0) {
spec = 2578; spec = 2577;
} }
break; break;
case ZEND_RECV: case ZEND_RECV:
if (op->op2.num == MAY_BE_ANY) { if (op->op2.num == MAY_BE_ANY) {
spec = 2579; spec = 2578;
} }
break; break;
case ZEND_SEND_VAL: case ZEND_SEND_VAL:
if (op->op1_type == IS_CONST && op->op2_type == IS_UNUSED && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) { if (op->op1_type == IS_CONST && op->op2_type == IS_UNUSED && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) {
spec = 3483; spec = 3482;
} }
break; break;
case ZEND_SEND_VAR_EX: case ZEND_SEND_VAR_EX:
if (op->op2_type == IS_UNUSED && op->op2.num <= MAX_ARG_FLAG_NUM && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) { if (op->op2_type == IS_UNUSED && op->op2.num <= MAX_ARG_FLAG_NUM && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) {
spec = 3478 | SPEC_RULE_OP1; spec = 3477 | SPEC_RULE_OP1;
} }
break; break;
case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_R:
if (op->op2_type == IS_CV && (op1_info & (MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY) { if (op->op2_type == IS_CV && (op1_info & (MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY) {
spec = 3485 | SPEC_RULE_RETVAL; spec = 3484 | SPEC_RULE_RETVAL;
} }
break; break;
case ZEND_FETCH_DIM_R: case ZEND_FETCH_DIM_R:
@ -68070,22 +68023,22 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break; break;
} }
spec = 3448 | SPEC_RULE_OP1 | SPEC_RULE_OP2; spec = 3447 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
} }
break; break;
case ZEND_SEND_VAL_EX: case ZEND_SEND_VAL_EX:
if (op->op2_type == IS_UNUSED && op->op2.num <= MAX_ARG_FLAG_NUM && op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) { if (op->op2_type == IS_UNUSED && op->op2.num <= MAX_ARG_FLAG_NUM && op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) {
spec = 3484; spec = 3483;
} }
break; break;
case ZEND_SEND_VAR: case ZEND_SEND_VAR:
if (op->op2_type == IS_UNUSED && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) { if (op->op2_type == IS_UNUSED && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) {
spec = 3473 | SPEC_RULE_OP1; spec = 3472 | SPEC_RULE_OP1;
} }
break; break;
case ZEND_COUNT: case ZEND_COUNT:
if ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == MAY_BE_ARRAY) { if ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == MAY_BE_ARRAY) {
spec = 2580 | SPEC_RULE_OP1; spec = 2579 | SPEC_RULE_OP1;
} }
break; break;
case ZEND_BW_OR: case ZEND_BW_OR:

1935
Zend/zend_vm_handlers.h generated

File diff suppressed because it is too large Load diff

View file

@ -102,7 +102,7 @@ static const char *zend_vm_opcodes_names[210] = {
"ZEND_UNSET_OBJ", "ZEND_UNSET_OBJ",
"ZEND_FE_RESET_R", "ZEND_FE_RESET_R",
"ZEND_FE_FETCH_R", "ZEND_FE_FETCH_R",
"ZEND_EXIT", NULL,
"ZEND_FETCH_R", "ZEND_FETCH_R",
"ZEND_FETCH_DIM_R", "ZEND_FETCH_DIM_R",
"ZEND_FETCH_OBJ_R", "ZEND_FETCH_OBJ_R",

View file

@ -161,7 +161,6 @@ END_EXTERN_C()
#define ZEND_UNSET_OBJ 76 #define ZEND_UNSET_OBJ 76
#define ZEND_FE_RESET_R 77 #define ZEND_FE_RESET_R 77
#define ZEND_FE_FETCH_R 78 #define ZEND_FE_FETCH_R 78
#define ZEND_EXIT 79
#define ZEND_FETCH_R 80 #define ZEND_FETCH_R 80
#define ZEND_FETCH_DIM_R 81 #define ZEND_FETCH_DIM_R 81
#define ZEND_FETCH_OBJ_R 82 #define ZEND_FETCH_OBJ_R 82

View file

@ -83,9 +83,15 @@ function processStubFile(string $stubFile, Context $context, bool $includeOnly =
} }
} }
/* As exit() and die() are proper token/keywords an need to hack-around */
$hasSpecialExitAsFunctionHandling = str_ends_with($stubFile, 'zend_builtin_functions.stub.php');
if (!$fileInfo = $context->parsedFiles[$stubFile] ?? null) { if (!$fileInfo = $context->parsedFiles[$stubFile] ?? null) {
initPhpParser(); initPhpParser();
$fileInfo = parseStubFile($stubCode ?? file_get_contents($stubFile)); $stubContent = $stubCode ?? file_get_contents($stubFile);
if ($hasSpecialExitAsFunctionHandling) {
$stubContent = str_replace(['exit', 'die'], ['exit_dummy', 'die_dummy'], $stubContent);
}
$fileInfo = parseStubFile($stubContent);
$context->parsedFiles[$stubFile] = $fileInfo; $context->parsedFiles[$stubFile] = $fileInfo;
foreach ($fileInfo->dependencies as $dependency) { foreach ($fileInfo->dependencies as $dependency) {
@ -118,6 +124,9 @@ function processStubFile(string $stubFile, Context $context, bool $includeOnly =
$context->allConstInfos, $context->allConstInfos,
$stubHash $stubHash
); );
if ($hasSpecialExitAsFunctionHandling) {
$arginfoCode = str_replace(['exit_dummy', 'die_dummy'], ['exit', 'die'], $arginfoCode);
}
if (($context->forceRegeneration || $stubHash !== $oldStubHash) && file_put_contents($arginfoFile, $arginfoCode)) { if (($context->forceRegeneration || $stubHash !== $oldStubHash) && file_put_contents($arginfoFile, $arginfoCode)) {
echo "Saved $arginfoFile\n"; echo "Saved $arginfoFile\n";
} }

View file

@ -2557,7 +2557,6 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
case ZEND_GENERATOR_RETURN: case ZEND_GENERATOR_RETURN:
case ZEND_RETURN_BY_REF: case ZEND_RETURN_BY_REF:
case ZEND_RETURN: case ZEND_RETURN:
case ZEND_EXIT:
case ZEND_MATCH_ERROR: case ZEND_MATCH_ERROR:
/* switch through trampoline */ /* switch through trampoline */
case ZEND_YIELD: case ZEND_YIELD:
@ -3470,7 +3469,6 @@ ZEND_EXT_API int zend_jit_check_support(void)
/* JIT has no effect on these opcodes */ /* JIT has no effect on these opcodes */
case ZEND_BEGIN_SILENCE: case ZEND_BEGIN_SILENCE:
case ZEND_END_SILENCE: case ZEND_END_SILENCE:
case ZEND_EXIT:
break; break;
default: default:
if (zend_get_user_opcode_handler(i) != NULL) { if (zend_get_user_opcode_handler(i) != NULL) {

View file

@ -16450,8 +16450,7 @@ static int zend_jit_trace_handler(zend_jit_ctx *jit, const zend_op_array *op_arr
} else { } else {
ir_GUARD(ir_GE(ref, ir_CONST_I32(0)), jit_STUB_ADDR(jit, jit_stub_trace_halt)); ir_GUARD(ir_GE(ref, ir_CONST_I32(0)), jit_STUB_ADDR(jit, jit_stub_trace_halt));
} }
} else if (opline->opcode == ZEND_EXIT || } else if (opline->opcode == ZEND_GENERATOR_RETURN ||
opline->opcode == ZEND_GENERATOR_RETURN ||
opline->opcode == ZEND_YIELD || opline->opcode == ZEND_YIELD ||
opline->opcode == ZEND_YIELD_FROM) { opline->opcode == ZEND_YIELD_FROM) {
ir_IJMP(jit_STUB_ADDR(jit, jit_stub_trace_halt)); ir_IJMP(jit_STUB_ADDR(jit, jit_stub_trace_halt));

View file

@ -314,7 +314,6 @@ static int zend_jit_trace_may_exit(const zend_op_array *op_array, const zend_op
case ZEND_FAST_RET: case ZEND_FAST_RET:
case ZEND_GENERATOR_CREATE: case ZEND_GENERATOR_CREATE:
case ZEND_GENERATOR_RETURN: case ZEND_GENERATOR_RETURN:
case ZEND_EXIT:
case ZEND_YIELD: case ZEND_YIELD:
case ZEND_YIELD_FROM: case ZEND_YIELD_FROM:
case ZEND_INCLUDE_OR_EVAL: case ZEND_INCLUDE_OR_EVAL:

View file

@ -9,7 +9,7 @@ opcache.jit=function
zend_test.observer.enabled=1 zend_test.observer.enabled=1
zend_test.observer.show_output=1 zend_test.observer.show_output=1
zend_test.observer.observe_all=1 zend_test.observer.observe_all=1
zend_test.observer.show_opcode_in_user_handler=ZEND_EXIT, ZEND_BEGIN_SILENCE, ZEND_END_SILENCE zend_test.observer.show_opcode_in_user_handler=ZEND_BEGIN_SILENCE, ZEND_END_SILENCE
--EXTENSIONS-- --EXTENSIONS--
opcache opcache
zend_test zend_test
@ -27,6 +27,9 @@ exit(@test());
<file '%s'> <file '%s'>
<!-- opcode: 'ZEND_BEGIN_SILENCE' in user handler --> <!-- opcode: 'ZEND_BEGIN_SILENCE' in user handler -->
<!-- opcode: 'ZEND_END_SILENCE' in user handler --> <!-- opcode: 'ZEND_END_SILENCE' in user handler -->
<!-- opcode: 'ZEND_EXIT' in user handler --> <!-- init exit() -->
<exit>
<!-- Exception: UnwindExit -->
</exit>
<!-- Exception: UnwindExit --> <!-- Exception: UnwindExit -->
</file '%s'> </file '%s'>

View file

@ -23,9 +23,9 @@ try {
echo $e->getMessage(), "\n"; echo $e->getMessage(), "\n";
} }
// using language construct 'exit' as 'callback' // using language construct 'isset' as 'callback'
try { try {
var_dump( array_filter($input, 'exit') ); var_dump( array_filter($input, 'isset') );
} catch (TypeError $e) { } catch (TypeError $e) {
echo $e->getMessage(), "\n"; echo $e->getMessage(), "\n";
} }
@ -63,5 +63,5 @@ array(6) {
int(1000) int(1000)
} }
array_filter(): Argument #2 ($callback) must be a valid callback or null, function "echo" not found or invalid function name array_filter(): Argument #2 ($callback) must be a valid callback or null, function "echo" not found or invalid function name
array_filter(): Argument #2 ($callback) must be a valid callback or null, function "exit" not found or invalid function name array_filter(): Argument #2 ($callback) must be a valid callback or null, function "isset" not found or invalid function name
Done Done

View file

@ -2,32 +2,24 @@
Test array_map() function : usage variations - failing built-in functions & language constructs Test array_map() function : usage variations - failing built-in functions & language constructs
--FILE-- --FILE--
<?php <?php
/*
* Test array_map() by passing non-permmited built-in functions and language constructs i.e.
* echo(), array(), empty(), eval(), exit(), isset(), list(), print()
*/
echo "*** Testing array_map() : non-permmited built-in functions ***\n"; $arg = [1, 2];
// array to be passed as arguments
$arr1 = array(1, 2);
// built-in functions & language constructs // built-in functions & language constructs
$callback_names = array( $callbacks = [
/*1*/ 'echo', 'echo',
'array', 'array',
'empty', 'empty',
/*4*/ 'eval', 'eval',
'exit', 'isset',
'isset', 'list',
'list', 'print',
/*8*/ 'print' ];
);
for($count = 0; $count < count($callback_names); $count++) foreach($callbacks as $callback)
{ {
echo "-- Iteration ".($count + 1)." --\n";
try { try {
var_dump( array_map($callback_names[$count], $arr1) ); var_dump( array_map($callback, $arg) );
} catch (TypeError $e) { } catch (TypeError $e) {
echo $e->getMessage(), "\n"; echo $e->getMessage(), "\n";
} }
@ -36,21 +28,11 @@ for($count = 0; $count < count($callback_names); $count++)
echo "Done"; echo "Done";
?> ?>
--EXPECT-- --EXPECT--
*** Testing array_map() : non-permmited built-in functions ***
-- Iteration 1 --
array_map(): Argument #1 ($callback) must be a valid callback or null, function "echo" not found or invalid function name array_map(): Argument #1 ($callback) must be a valid callback or null, function "echo" not found or invalid function name
-- Iteration 2 --
array_map(): Argument #1 ($callback) must be a valid callback or null, function "array" not found or invalid function name array_map(): Argument #1 ($callback) must be a valid callback or null, function "array" not found or invalid function name
-- Iteration 3 --
array_map(): Argument #1 ($callback) must be a valid callback or null, function "empty" not found or invalid function name array_map(): Argument #1 ($callback) must be a valid callback or null, function "empty" not found or invalid function name
-- Iteration 4 --
array_map(): Argument #1 ($callback) must be a valid callback or null, function "eval" not found or invalid function name array_map(): Argument #1 ($callback) must be a valid callback or null, function "eval" not found or invalid function name
-- Iteration 5 --
array_map(): Argument #1 ($callback) must be a valid callback or null, function "exit" not found or invalid function name
-- Iteration 6 --
array_map(): Argument #1 ($callback) must be a valid callback or null, function "isset" not found or invalid function name array_map(): Argument #1 ($callback) must be a valid callback or null, function "isset" not found or invalid function name
-- Iteration 7 --
array_map(): Argument #1 ($callback) must be a valid callback or null, function "list" not found or invalid function name array_map(): Argument #1 ($callback) must be a valid callback or null, function "list" not found or invalid function name
-- Iteration 8 --
array_map(): Argument #1 ($callback) must be a valid callback or null, function "print" not found or invalid function name array_map(): Argument #1 ($callback) must be a valid callback or null, function "print" not found or invalid function name
Done Done

View file

@ -608,7 +608,6 @@ int phpdbg_skip_line_helper(void) /* {{{ */ {
|| opline->opcode == ZEND_RETURN || opline->opcode == ZEND_RETURN
|| opline->opcode == ZEND_FAST_RET || opline->opcode == ZEND_FAST_RET
|| opline->opcode == ZEND_GENERATOR_RETURN || opline->opcode == ZEND_GENERATOR_RETURN
|| opline->opcode == ZEND_EXIT
|| opline->opcode == ZEND_YIELD || opline->opcode == ZEND_YIELD
|| opline->opcode == ZEND_YIELD_FROM || opline->opcode == ZEND_YIELD_FROM
) { ) {
@ -652,7 +651,6 @@ static void phpdbg_seek_to_end(void) /* {{{ */ {
case ZEND_RETURN: case ZEND_RETURN:
case ZEND_FAST_RET: case ZEND_FAST_RET:
case ZEND_GENERATOR_RETURN: case ZEND_GENERATOR_RETURN:
case ZEND_EXIT:
case ZEND_YIELD: case ZEND_YIELD:
case ZEND_YIELD_FROM: case ZEND_YIELD_FROM:
zend_hash_index_update_ptr(&PHPDBG_G(seek), (zend_ulong) opline, (void *) opline); zend_hash_index_update_ptr(&PHPDBG_G(seek), (zend_ulong) opline, (void *) opline);