[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;
case ZEND_RETURN:
case ZEND_EXIT:
if (opline->op1_type == IS_TMP_VAR) {
src = VAR_SOURCE(opline->op1);
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;
if ((target->opcode == ZEND_RETURN ||
target->opcode == ZEND_RETURN_BY_REF ||
target->opcode == ZEND_GENERATOR_RETURN ||
target->opcode == ZEND_EXIT) &&
target->opcode == ZEND_GENERATOR_RETURN) &&
!(op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) {
/* JMP L, L: RETURN to immediate RETURN */
*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_BY_REF:
case ZEND_GENERATOR_RETURN:
case ZEND_EXIT:
case ZEND_THROW:
case ZEND_MATCH_ERROR:
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);
} else if ((target->opcode == ZEND_RETURN ||
target->opcode == ZEND_RETURN_BY_REF ||
target->opcode == ZEND_GENERATOR_RETURN ||
target->opcode == ZEND_EXIT) &&
target->opcode == ZEND_GENERATOR_RETURN) &&
!(op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) {
/* JMP L, L: RETURN to immediate RETURN */
*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;
}
break;
case ZEND_EXIT:
/* In this case the DO_CALL opcode may have been dropped
* and caller_call_opline will be NULL. */
break;
}
opline++;
}

View File

@ -302,7 +302,6 @@ ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array,
}
break;
case ZEND_MATCH_ERROR:
case ZEND_EXIT:
case ZEND_THROW:
/* Don't treat THROW as terminator if it's used in expression context,
* 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_BY_REF:
case ZEND_GENERATOR_RETURN:
case ZEND_EXIT:
case ZEND_THROW:
case ZEND_MATCH_ERROR:
case ZEND_VERIFY_NEVER_TYPE:

View File

@ -6,6 +6,9 @@ function skipFunction($function): bool {
|| $function === 'readline'
|| $function === 'readline_read_history'
|| $function === 'readline_write_history'
/* terminates script */
|| $function === 'exit'
|| $function === 'die'
/* intentionally violate invariants */
|| $function === 'zend_create_unterminated_string'
|| $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)
{
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);
}

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 */
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 */
function zend_version(): string {}

View File

@ -1,5 +1,11 @@
/* 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_END_ARG_INFO()
@ -232,6 +238,7 @@ static const zend_frameless_function_info frameless_function_infos_class_exists[
{ 0 },
};
ZEND_FUNCTION(exit);
ZEND_FUNCTION(zend_version);
ZEND_FUNCTION(func_num_args);
ZEND_FUNCTION(func_get_arg);
@ -292,6 +299,8 @@ ZEND_FUNCTION(gc_disable);
ZEND_FUNCTION(gc_status);
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(func_num_args, arginfo_func_num_args)
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) /* {{{ */
{
zend_ast *value_ast = ast->child[0];
@ -11366,7 +11345,6 @@ static void zend_compile_stmt(zend_ast *ast) /* {{{ */
zend_compile_halt_compiler(ast);
break;
case ZEND_AST_THROW:
case ZEND_AST_EXIT:
zend_compile_expr(NULL, ast);
break;
default:
@ -11469,9 +11447,6 @@ static void zend_compile_expr_inner(znode *result, zend_ast *ast) /* {{{ */
case ZEND_AST_PRINT:
zend_compile_print(result, ast);
return;
case ZEND_AST_EXIT:
zend_compile_exit(result, ast);
return;
case ZEND_AST_YIELD:
zend_compile_yield(result, ast);
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> new_dereferenceable new_non_dereferenceable anonymous_class class_name class_name_reference simple_variable
%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> fully_dereferenceable array_object_dereferenceable
%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_BOOL_CAST expr { $$ = zend_ast_create_cast(_IS_BOOL, $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); }
| scalar { $$ = $1; }
| '`' backticks_expr '`' { $$ = zend_ast_create(ZEND_AST_SHELL_EXEC, $2); }
@ -1407,11 +1411,6 @@ class_name_reference:
| '(' expr ')' { $$ = $2; }
;
exit_expr:
%empty { $$ = NULL; }
| '(' optional_expr ')' { $$ = $2; }
;
backticks_expr:
%empty
{ $$ = 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_UNKNOWN, "unknown") \
_(ZEND_STR_UNKNOWN_CAPITALIZED, "Unknown") \
_(ZEND_STR_EXIT, "exit") \
_(ZEND_STR_EVAL, "eval") \
_(ZEND_STR_INCLUDE, "include") \
_(ZEND_STR_REQUIRE, "require") \

View File

@ -7610,38 +7610,6 @@ ZEND_VM_C_LABEL(array_key_exists_array):
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)
{
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);
}
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)
{
USE_OPLINE
@ -7930,7 +7899,6 @@ array_key_exists_array:
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)
{
USE_OPLINE
@ -10307,7 +10275,6 @@ array_key_exists_array:
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)
{
USE_OPLINE
@ -12788,7 +12755,6 @@ array_key_exists_array:
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)
{
USE_OPLINE
@ -16950,7 +16916,6 @@ array_key_exists_array:
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)
{
USE_OPLINE
@ -18417,7 +18382,6 @@ array_key_exists_array:
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)
{
USE_OPLINE
@ -19824,7 +19788,6 @@ array_key_exists_array:
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)
{
USE_OPLINE
@ -45235,7 +45198,6 @@ array_key_exists_array:
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)
{
USE_OPLINE
@ -48963,7 +48925,6 @@ array_key_exists_array:
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)
{
USE_OPLINE
@ -54527,7 +54488,6 @@ array_key_exists_array:
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)
{
USE_OPLINE
@ -56322,7 +56282,6 @@ ZEND_API void execute_ex(zend_execute_data *ex)
(void*)&&ZEND_NULL_LABEL,
(void*)&&ZEND_FE_RESET_R_SPEC_CV_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_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);
VM_TRACE_OP_END(ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC)
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):
VM_TRACE(ZEND_BEGIN_SILENCE_SPEC)
ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@ -65515,7 +65469,6 @@ void zend_vm_init(void)
ZEND_NULL_HANDLER,
ZEND_FE_RESET_R_SPEC_CV_HANDLER,
ZEND_FE_FETCH_R_SPEC_VAR_HANDLER,
ZEND_EXIT_SPEC_HANDLER,
ZEND_FETCH_R_SPEC_CONST_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,
1256 | SPEC_RULE_OP1,
1261 | SPEC_RULE_OP1,
3487,
3486,
1266 | SPEC_RULE_OP1,
1271 | SPEC_RULE_OP1,
1276 | SPEC_RULE_OP2,
@ -67494,100 +67447,101 @@ void zend_vm_init(void)
1559 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1584 | SPEC_RULE_OP1,
1589,
1590,
1591 | SPEC_RULE_OP1,
1596 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1621 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1646 | SPEC_RULE_OP1,
1651 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1676 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1701 | SPEC_RULE_OP1,
1706 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1731 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1756 | SPEC_RULE_OP1,
1761 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1786 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1811 | SPEC_RULE_OP1,
1816 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1841 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1866 | SPEC_RULE_OP1,
1871 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1896 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1921 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1946,
1947 | SPEC_RULE_OP2 | SPEC_RULE_QUICK_ARG,
3486,
1590 | SPEC_RULE_OP1,
1595 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1620 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1645 | SPEC_RULE_OP1,
1650 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1675 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1700 | SPEC_RULE_OP1,
1705 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1730 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1755 | SPEC_RULE_OP1,
1760 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1785 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1810 | SPEC_RULE_OP1,
1815 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1840 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1865 | SPEC_RULE_OP1,
1870 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1895 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1920 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1945,
1946 | SPEC_RULE_OP2 | SPEC_RULE_QUICK_ARG,
1956,
1957,
1958,
1959,
1960,
1961,
1962 | SPEC_RULE_OP2,
1967,
1968 | SPEC_RULE_OP1,
1973 | SPEC_RULE_OP2,
1978 | SPEC_RULE_OP1,
1983 | SPEC_RULE_OP1 | SPEC_RULE_OBSERVER,
1993 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2018 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2043 | SPEC_RULE_OP1,
2048 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2073 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_QUICK_ARG,
2123 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2148 | SPEC_RULE_OP2,
2153,
2154 | SPEC_RULE_OP1,
2159 | SPEC_RULE_OP1,
2164,
2165 | SPEC_RULE_OP1,
2170 | SPEC_RULE_OP1,
2175 | SPEC_RULE_OP1,
1961 | SPEC_RULE_OP2,
1966,
1967 | SPEC_RULE_OP1,
1972 | SPEC_RULE_OP2,
1977 | SPEC_RULE_OP1,
1982 | SPEC_RULE_OP1 | SPEC_RULE_OBSERVER,
1992 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2017 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2042 | SPEC_RULE_OP1,
2047 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2072 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_QUICK_ARG,
2122 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2147 | SPEC_RULE_OP2,
2152,
2153 | SPEC_RULE_OP1,
2158 | SPEC_RULE_OP1,
2163,
2164 | SPEC_RULE_OP1,
2169 | SPEC_RULE_OP1,
2174 | SPEC_RULE_OP1,
2179,
2180,
2181,
2182 | SPEC_RULE_OP2,
2187 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER,
2191 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER,
2195 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER,
2199 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2199 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2224 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2224 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2249 | SPEC_RULE_OP1,
2254,
2255 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2280,
2281 | SPEC_RULE_OP1,
2181 | SPEC_RULE_OP2,
2186 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER,
2190 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER,
2194 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER,
2198 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2198 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2223 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2223 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2248 | SPEC_RULE_OP1,
2253,
2254 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2279,
2280 | SPEC_RULE_OP1,
2285,
2286,
2287,
2288,
2289,
2290,
2291,
2292,
2293 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2292 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2317,
2318,
2319,
2320,
2321 | SPEC_RULE_OP1,
2326,
2327 | SPEC_RULE_ISSET,
2329 | SPEC_RULE_OP2,
2334,
2335 | SPEC_RULE_OP1,
2340 | SPEC_RULE_OBSERVER,
2342,
2343 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2368 | SPEC_RULE_OP1 | SPEC_RULE_OBSERVER,
2320 | SPEC_RULE_OP1,
2325,
2326 | SPEC_RULE_ISSET,
2328 | SPEC_RULE_OP2,
2333,
2334 | SPEC_RULE_OP1,
2339 | SPEC_RULE_OBSERVER,
2341,
2342 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2367 | SPEC_RULE_OP1 | SPEC_RULE_OBSERVER,
2377,
2378,
2379,
2380,
2381,
2382 | SPEC_RULE_OP1,
2381 | SPEC_RULE_OP1,
2386,
2387,
2388,
2389 | SPEC_RULE_OP1,
2394 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2419,
2420 | SPEC_RULE_OP1,
2388 | SPEC_RULE_OP1,
2393 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2418,
2419 | SPEC_RULE_OP1,
2424,
2425,
2426,
2427,
@ -67595,82 +67549,81 @@ void zend_vm_init(void)
2429,
2430,
2431,
2432,
2433 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2432 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2457,
2458,
2459,
2460,
2461 | SPEC_RULE_OP2,
2466,
2467 | SPEC_RULE_OP1,
2472 | SPEC_RULE_OP1,
2477 | SPEC_RULE_OP1,
2482 | SPEC_RULE_OP1,
2487 | SPEC_RULE_OP1,
2492,
2493 | SPEC_RULE_OP1,
2498 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2523 | SPEC_RULE_OP1,
2528 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2553 | SPEC_RULE_OP1,
2558 | SPEC_RULE_OP1,
2460 | SPEC_RULE_OP2,
2465,
2466 | SPEC_RULE_OP1,
2471 | SPEC_RULE_OP1,
2476 | SPEC_RULE_OP1,
2481 | SPEC_RULE_OP1,
2486 | SPEC_RULE_OP1,
2491,
2492 | SPEC_RULE_OP1,
2497 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2522 | SPEC_RULE_OP1,
2527 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2552 | SPEC_RULE_OP1,
2557 | SPEC_RULE_OP1,
2562,
2563,
2564,
2565,
2566,
2567,
2568 | SPEC_RULE_OBSERVER,
2570 | SPEC_RULE_OBSERVER,
2572 | SPEC_RULE_OBSERVER,
2574 | SPEC_RULE_OBSERVER,
2567 | SPEC_RULE_OBSERVER,
2569 | SPEC_RULE_OBSERVER,
2571 | SPEC_RULE_OBSERVER,
2573 | SPEC_RULE_OBSERVER,
2575,
2576,
2577,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3487,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
3486,
};
#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
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) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 2711 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
spec = 2710 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
}
break;
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) {
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) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
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) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 2786 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
spec = 2785 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
}
break;
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) {
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) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
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))) {
spec = 3111 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
spec = 3110 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
}
break;
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) {
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) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
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))) {
spec = 3116 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
spec = 3115 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
}
break;
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) {
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) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
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;
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) {
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) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
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;
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) {
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) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
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;
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) {
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) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
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;
case ZEND_QM_ASSIGN:
if (op1_info == MAY_BE_LONG) {
spec = 3433 | SPEC_RULE_OP1;
spec = 3432 | SPEC_RULE_OP1;
} 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))))) {
spec = 3443 | SPEC_RULE_OP1;
spec = 3442 | SPEC_RULE_OP1;
}
break;
case ZEND_PRE_INC:
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) {
spec = 3423 | SPEC_RULE_RETVAL;
spec = 3422 | SPEC_RULE_RETVAL;
}
break;
case ZEND_PRE_DEC:
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) {
spec = 3427 | SPEC_RULE_RETVAL;
spec = 3426 | SPEC_RULE_RETVAL;
}
break;
case ZEND_POST_INC:
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
spec = 3429;
spec = 3428;
} else if (op1_info == MAY_BE_LONG) {
spec = 3430;
spec = 3429;
}
break;
case ZEND_POST_DEC:
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
spec = 3431;
spec = 3430;
} else if (op1_info == MAY_BE_LONG) {
spec = 3432;
spec = 3431;
}
break;
case ZEND_JMP:
if (OP_JMP_ADDR(op, op->op1) > op) {
spec = 2585;
spec = 2584;
}
break;
case ZEND_INIT_FCALL:
if (Z_EXTRA_P(RT_CONSTANT(op, op->op2)) != 0) {
spec = 2578;
spec = 2577;
}
break;
case ZEND_RECV:
if (op->op2.num == MAY_BE_ANY) {
spec = 2579;
spec = 2578;
}
break;
case ZEND_SEND_VAL:
if (op->op1_type == IS_CONST && op->op2_type == IS_UNUSED && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) {
spec = 3483;
spec = 3482;
}
break;
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) {
spec = 3478 | SPEC_RULE_OP1;
spec = 3477 | SPEC_RULE_OP1;
}
break;
case ZEND_FE_FETCH_R:
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;
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) {
break;
}
spec = 3448 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
spec = 3447 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
}
break;
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))) {
spec = 3484;
spec = 3483;
}
break;
case ZEND_SEND_VAR:
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;
case ZEND_COUNT:
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;
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_FE_RESET_R",
"ZEND_FE_FETCH_R",
"ZEND_EXIT",
NULL,
"ZEND_FETCH_R",
"ZEND_FETCH_DIM_R",
"ZEND_FETCH_OBJ_R",

View File

@ -161,7 +161,6 @@ END_EXTERN_C()
#define ZEND_UNSET_OBJ 76
#define ZEND_FE_RESET_R 77
#define ZEND_FE_FETCH_R 78
#define ZEND_EXIT 79
#define ZEND_FETCH_R 80
#define ZEND_FETCH_DIM_R 81
#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) {
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;
foreach ($fileInfo->dependencies as $dependency) {
@ -118,6 +124,9 @@ function processStubFile(string $stubFile, Context $context, bool $includeOnly =
$context->allConstInfos,
$stubHash
);
if ($hasSpecialExitAsFunctionHandling) {
$arginfoCode = str_replace(['exit_dummy', 'die_dummy'], ['exit', 'die'], $arginfoCode);
}
if (($context->forceRegeneration || $stubHash !== $oldStubHash) && file_put_contents($arginfoFile, $arginfoCode)) {
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_RETURN_BY_REF:
case ZEND_RETURN:
case ZEND_EXIT:
case ZEND_MATCH_ERROR:
/* switch through trampoline */
case ZEND_YIELD:
@ -3470,7 +3469,6 @@ ZEND_EXT_API int zend_jit_check_support(void)
/* JIT has no effect on these opcodes */
case ZEND_BEGIN_SILENCE:
case ZEND_END_SILENCE:
case ZEND_EXIT:
break;
default:
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 {
ir_GUARD(ir_GE(ref, ir_CONST_I32(0)), jit_STUB_ADDR(jit, jit_stub_trace_halt));
}
} else if (opline->opcode == ZEND_EXIT ||
opline->opcode == ZEND_GENERATOR_RETURN ||
} else if (opline->opcode == ZEND_GENERATOR_RETURN ||
opline->opcode == ZEND_YIELD ||
opline->opcode == ZEND_YIELD_FROM) {
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_GENERATOR_CREATE:
case ZEND_GENERATOR_RETURN:
case ZEND_EXIT:
case ZEND_YIELD:
case ZEND_YIELD_FROM:
case ZEND_INCLUDE_OR_EVAL:

View File

@ -9,7 +9,7 @@ opcache.jit=function
zend_test.observer.enabled=1
zend_test.observer.show_output=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--
opcache
zend_test
@ -27,6 +27,9 @@ exit(@test());
<file '%s'>
<!-- opcode: 'ZEND_BEGIN_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 -->
</file '%s'>

View File

@ -23,9 +23,9 @@ try {
echo $e->getMessage(), "\n";
}
// using language construct 'exit' as 'callback'
// using language construct 'isset' as 'callback'
try {
var_dump( array_filter($input, 'exit') );
var_dump( array_filter($input, 'isset') );
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
@ -63,5 +63,5 @@ array(6) {
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 "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

View File

@ -2,32 +2,24 @@
Test array_map() function : usage variations - failing built-in functions & language constructs
--FILE--
<?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";
// array to be passed as arguments
$arr1 = array(1, 2);
$arg = [1, 2];
// built-in functions & language constructs
$callback_names = array(
/*1*/ 'echo',
'array',
'empty',
/*4*/ 'eval',
'exit',
'isset',
'list',
/*8*/ 'print'
);
for($count = 0; $count < count($callback_names); $count++)
$callbacks = [
'echo',
'array',
'empty',
'eval',
'isset',
'list',
'print',
];
foreach($callbacks as $callback)
{
echo "-- Iteration ".($count + 1)." --\n";
try {
var_dump( array_map($callback_names[$count], $arr1) );
var_dump( array_map($callback, $arg) );
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
@ -36,21 +28,11 @@ for($count = 0; $count < count($callback_names); $count++)
echo "Done";
?>
--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
-- Iteration 2 --
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
-- Iteration 4 --
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
-- Iteration 7 --
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
Done

View File

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