mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Merge branch 'PHP-7.4'
* PHP-7.4: Check asserts early identation fix Call global code of preloaded script in global context Avoid "Anonymous class wasn't preloaded" error by lazely loading of not preloaded part of a preloaded script
This commit is contained in:
commit
78b64bd4ed
8 changed files with 114 additions and 12 deletions
|
@ -81,6 +81,7 @@ ZEND_API char *(*zend_getenv)(char *name, size_t name_len);
|
|||
ZEND_API zend_string *(*zend_resolve_path)(const char *filename, size_t filename_len);
|
||||
ZEND_API int (*zend_post_startup_cb)(void) = NULL;
|
||||
ZEND_API void (*zend_post_shutdown_cb)(void) = NULL;
|
||||
ZEND_API int (*zend_preload_autoload)(zend_string *filename) = NULL;
|
||||
|
||||
void (*zend_on_timeout)(int seconds);
|
||||
|
||||
|
|
|
@ -292,6 +292,9 @@ extern ZEND_API zend_string *(*zend_resolve_path)(const char *filename, size_t f
|
|||
extern ZEND_API int (*zend_post_startup_cb)(void);
|
||||
extern ZEND_API void (*zend_post_shutdown_cb)(void);
|
||||
|
||||
/* Callback for loading of not preloaded part of the script */
|
||||
extern ZEND_API int (*zend_preload_autoload)(zend_string *filename);
|
||||
|
||||
ZEND_API ZEND_COLD void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
|
||||
ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
|
||||
/* If filename is NULL the default filename is used. */
|
||||
|
|
|
@ -1125,11 +1125,21 @@ ZEND_API int do_bind_class(zval *lcname, zend_string *lc_parent_name) /* {{{ */
|
|||
ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname));
|
||||
if (ce) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
|
||||
return FAILURE;
|
||||
} else {
|
||||
ZEND_ASSERT(EG(current_execute_data)->func->op_array.fn_flags & ZEND_ACC_PRELOADED);
|
||||
zend_error_noreturn(E_ERROR, "Class %s wasn't preloaded", Z_STRVAL_P(lcname));
|
||||
do {
|
||||
ZEND_ASSERT(EG(current_execute_data)->func->op_array.fn_flags & ZEND_ACC_PRELOADED);
|
||||
if (zend_preload_autoload
|
||||
&& zend_preload_autoload(EG(current_execute_data)->func->op_array.filename) == SUCCESS) {
|
||||
zv = zend_hash_find_ex(EG(class_table), Z_STR_P(rtd_key), 1);
|
||||
if (EXPECTED(zv != NULL)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
zend_error_noreturn(E_ERROR, "Class %s wasn't preloaded", Z_STRVAL_P(lcname));
|
||||
return FAILURE;
|
||||
} while (0);
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* Register the derived class */
|
||||
|
|
|
@ -7157,8 +7157,17 @@ ZEND_VM_HANDLER(146, ZEND_DECLARE_ANON_CLASS, ANY, ANY, CACHE_SLOT)
|
|||
zv = zend_hash_find_ex(EG(class_table), rtd_key, 1);
|
||||
if (UNEXPECTED(zv == NULL)) {
|
||||
SAVE_OPLINE();
|
||||
ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_PRELOADED);
|
||||
zend_error_noreturn(E_ERROR, "Anonymous class wasn't preloaded");
|
||||
do {
|
||||
ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_PRELOADED);
|
||||
if (zend_preload_autoload
|
||||
&& zend_preload_autoload(EX(func)->op_array.filename) == SUCCESS) {
|
||||
zv = zend_hash_find_ex(EG(class_table), rtd_key, 1);
|
||||
if (EXPECTED(zv != NULL)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
zend_error_noreturn(E_ERROR, "Anonymous class wasn't preloaded");
|
||||
} while (0);
|
||||
}
|
||||
ZEND_ASSERT(zv != NULL);
|
||||
ce = Z_CE_P(zv);
|
||||
|
|
|
@ -2412,8 +2412,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_CLASS_SPEC_HANDLE
|
|||
zv = zend_hash_find_ex(EG(class_table), rtd_key, 1);
|
||||
if (UNEXPECTED(zv == NULL)) {
|
||||
SAVE_OPLINE();
|
||||
ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_PRELOADED);
|
||||
zend_error_noreturn(E_ERROR, "Anonymous class wasn't preloaded");
|
||||
do {
|
||||
ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_PRELOADED);
|
||||
if (zend_preload_autoload
|
||||
&& zend_preload_autoload(EX(func)->op_array.filename) == SUCCESS) {
|
||||
zv = zend_hash_find_ex(EG(class_table), rtd_key, 1);
|
||||
if (EXPECTED(zv != NULL)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
zend_error_noreturn(E_ERROR, "Anonymous class wasn't preloaded");
|
||||
} while (0);
|
||||
}
|
||||
ZEND_ASSERT(zv != NULL);
|
||||
ce = Z_CE_P(zv);
|
||||
|
|
|
@ -4312,6 +4312,75 @@ static void preload_load(void)
|
|||
}
|
||||
}
|
||||
|
||||
static int preload_autoload(zend_string *filename)
|
||||
{
|
||||
zend_persistent_script *persistent_script;
|
||||
zend_op_array *op_array;
|
||||
zend_execute_data *old_execute_data;
|
||||
zend_class_entry *old_fake_scope;
|
||||
zend_bool do_bailout = 0;
|
||||
int ret = SUCCESS;
|
||||
|
||||
if (zend_hash_exists(&EG(included_files), filename)) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
persistent_script = zend_accel_hash_find(&ZCSG(hash), filename);
|
||||
if (!persistent_script) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
zend_hash_add_empty_element(&EG(included_files), filename);
|
||||
|
||||
if (persistent_script->ping_auto_globals_mask) {
|
||||
zend_accel_set_auto_globals(persistent_script->ping_auto_globals_mask);
|
||||
}
|
||||
|
||||
op_array = zend_accel_load_script(persistent_script, 1);
|
||||
if (!op_array) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* Execute in global context */
|
||||
old_execute_data = EG(current_execute_data);
|
||||
EG(current_execute_data) = NULL;
|
||||
old_fake_scope = EG(fake_scope);
|
||||
EG(fake_scope) = NULL;
|
||||
zend_exception_save();
|
||||
|
||||
zend_try {
|
||||
zend_execute(op_array, NULL);
|
||||
} zend_catch {
|
||||
do_bailout = 1;
|
||||
} zend_end_try();
|
||||
|
||||
if (EG(exception)) {
|
||||
ret = FAILURE;
|
||||
}
|
||||
|
||||
zend_exception_restore();
|
||||
EG(fake_scope) = old_fake_scope;
|
||||
EG(current_execute_data) = old_execute_data;
|
||||
while (old_execute_data) {
|
||||
if (old_execute_data->func && (ZEND_CALL_INFO(old_execute_data) & ZEND_CALL_HAS_SYMBOL_TABLE)) {
|
||||
if (old_execute_data->symbol_table == &EG(symbol_table)) {
|
||||
zend_attach_symbol_table(old_execute_data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
old_execute_data = old_execute_data->prev_execute_data;
|
||||
}
|
||||
|
||||
destroy_op_array(op_array);
|
||||
efree_size(op_array, sizeof(zend_op_array));
|
||||
|
||||
if (do_bailout) {
|
||||
zend_bailout();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int accel_preload(const char *config)
|
||||
{
|
||||
zend_file_handle file_handle;
|
||||
|
@ -4606,6 +4675,8 @@ static int accel_preload(const char *config)
|
|||
HANDLE_UNBLOCK_INTERRUPTIONS();
|
||||
|
||||
zend_shared_alloc_destroy_xlat_table();
|
||||
|
||||
zend_preload_autoload = preload_autoload;
|
||||
} else {
|
||||
CG(map_ptr_last) = orig_map_ptr_last;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,5 @@ var_dump(foo());
|
|||
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
|
||||
|
||||
Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
|
||||
|
||||
Fatal error: Anonymous class wasn't preloaded in %spreload_bug78937.inc on line 3
|
||||
|
||||
object(Bar@anonymous)#%d (0) {
|
||||
}
|
||||
|
|
|
@ -21,5 +21,5 @@ var_dump(new Foo);
|
|||
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
|
||||
|
||||
Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
|
||||
|
||||
Fatal error: Class foo wasn't preloaded in %spreload_bug78937.inc on line 6
|
||||
object(Foo)#%d (0) {
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue