Skip to content

Commit 78b64bd

Browse files
committed
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
2 parents c9db322 + c5159b3 commit 78b64bd

File tree

8 files changed

+114
-12
lines changed

8 files changed

+114
-12
lines changed

Zend/zend.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ ZEND_API char *(*zend_getenv)(char *name, size_t name_len);
8181
ZEND_API zend_string *(*zend_resolve_path)(const char *filename, size_t filename_len);
8282
ZEND_API int (*zend_post_startup_cb)(void) = NULL;
8383
ZEND_API void (*zend_post_shutdown_cb)(void) = NULL;
84+
ZEND_API int (*zend_preload_autoload)(zend_string *filename) = NULL;
8485

8586
void (*zend_on_timeout)(int seconds);
8687

Zend/zend.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,9 @@ extern ZEND_API zend_string *(*zend_resolve_path)(const char *filename, size_t f
292292
extern ZEND_API int (*zend_post_startup_cb)(void);
293293
extern ZEND_API void (*zend_post_shutdown_cb)(void);
294294

295+
/* Callback for loading of not preloaded part of the script */
296+
extern ZEND_API int (*zend_preload_autoload)(zend_string *filename);
297+
295298
ZEND_API ZEND_COLD void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
296299
ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
297300
/* If filename is NULL the default filename is used. */

Zend/zend_compile.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,11 +1125,21 @@ ZEND_API int do_bind_class(zval *lcname, zend_string *lc_parent_name) /* {{{ */
11251125
ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname));
11261126
if (ce) {
11271127
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));
1128+
return FAILURE;
11281129
} else {
1129-
ZEND_ASSERT(EG(current_execute_data)->func->op_array.fn_flags & ZEND_ACC_PRELOADED);
1130-
zend_error_noreturn(E_ERROR, "Class %s wasn't preloaded", Z_STRVAL_P(lcname));
1130+
do {
1131+
ZEND_ASSERT(EG(current_execute_data)->func->op_array.fn_flags & ZEND_ACC_PRELOADED);
1132+
if (zend_preload_autoload
1133+
&& zend_preload_autoload(EG(current_execute_data)->func->op_array.filename) == SUCCESS) {
1134+
zv = zend_hash_find_ex(EG(class_table), Z_STR_P(rtd_key), 1);
1135+
if (EXPECTED(zv != NULL)) {
1136+
break;
1137+
}
1138+
}
1139+
zend_error_noreturn(E_ERROR, "Class %s wasn't preloaded", Z_STRVAL_P(lcname));
1140+
return FAILURE;
1141+
} while (0);
11311142
}
1132-
return FAILURE;
11331143
}
11341144

11351145
/* Register the derived class */

Zend/zend_vm_def.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7157,8 +7157,17 @@ ZEND_VM_HANDLER(146, ZEND_DECLARE_ANON_CLASS, ANY, ANY, CACHE_SLOT)
71577157
zv = zend_hash_find_ex(EG(class_table), rtd_key, 1);
71587158
if (UNEXPECTED(zv == NULL)) {
71597159
SAVE_OPLINE();
7160-
ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_PRELOADED);
7161-
zend_error_noreturn(E_ERROR, "Anonymous class wasn't preloaded");
7160+
do {
7161+
ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_PRELOADED);
7162+
if (zend_preload_autoload
7163+
&& zend_preload_autoload(EX(func)->op_array.filename) == SUCCESS) {
7164+
zv = zend_hash_find_ex(EG(class_table), rtd_key, 1);
7165+
if (EXPECTED(zv != NULL)) {
7166+
break;
7167+
}
7168+
}
7169+
zend_error_noreturn(E_ERROR, "Anonymous class wasn't preloaded");
7170+
} while (0);
71627171
}
71637172
ZEND_ASSERT(zv != NULL);
71647173
ce = Z_CE_P(zv);

Zend/zend_vm_execute.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2412,8 +2412,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_CLASS_SPEC_HANDLE
24122412
zv = zend_hash_find_ex(EG(class_table), rtd_key, 1);
24132413
if (UNEXPECTED(zv == NULL)) {
24142414
SAVE_OPLINE();
2415-
ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_PRELOADED);
2416-
zend_error_noreturn(E_ERROR, "Anonymous class wasn't preloaded");
2415+
do {
2416+
ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_PRELOADED);
2417+
if (zend_preload_autoload
2418+
&& zend_preload_autoload(EX(func)->op_array.filename) == SUCCESS) {
2419+
zv = zend_hash_find_ex(EG(class_table), rtd_key, 1);
2420+
if (EXPECTED(zv != NULL)) {
2421+
break;
2422+
}
2423+
}
2424+
zend_error_noreturn(E_ERROR, "Anonymous class wasn't preloaded");
2425+
} while (0);
24172426
}
24182427
ZEND_ASSERT(zv != NULL);
24192428
ce = Z_CE_P(zv);

ext/opcache/ZendAccelerator.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4312,6 +4312,75 @@ static void preload_load(void)
43124312
}
43134313
}
43144314

4315+
static int preload_autoload(zend_string *filename)
4316+
{
4317+
zend_persistent_script *persistent_script;
4318+
zend_op_array *op_array;
4319+
zend_execute_data *old_execute_data;
4320+
zend_class_entry *old_fake_scope;
4321+
zend_bool do_bailout = 0;
4322+
int ret = SUCCESS;
4323+
4324+
if (zend_hash_exists(&EG(included_files), filename)) {
4325+
return FAILURE;
4326+
}
4327+
4328+
persistent_script = zend_accel_hash_find(&ZCSG(hash), filename);
4329+
if (!persistent_script) {
4330+
return FAILURE;
4331+
}
4332+
4333+
zend_hash_add_empty_element(&EG(included_files), filename);
4334+
4335+
if (persistent_script->ping_auto_globals_mask) {
4336+
zend_accel_set_auto_globals(persistent_script->ping_auto_globals_mask);
4337+
}
4338+
4339+
op_array = zend_accel_load_script(persistent_script, 1);
4340+
if (!op_array) {
4341+
return FAILURE;
4342+
}
4343+
4344+
/* Execute in global context */
4345+
old_execute_data = EG(current_execute_data);
4346+
EG(current_execute_data) = NULL;
4347+
old_fake_scope = EG(fake_scope);
4348+
EG(fake_scope) = NULL;
4349+
zend_exception_save();
4350+
4351+
zend_try {
4352+
zend_execute(op_array, NULL);
4353+
} zend_catch {
4354+
do_bailout = 1;
4355+
} zend_end_try();
4356+
4357+
if (EG(exception)) {
4358+
ret = FAILURE;
4359+
}
4360+
4361+
zend_exception_restore();
4362+
EG(fake_scope) = old_fake_scope;
4363+
EG(current_execute_data) = old_execute_data;
4364+
while (old_execute_data) {
4365+
if (old_execute_data->func && (ZEND_CALL_INFO(old_execute_data) & ZEND_CALL_HAS_SYMBOL_TABLE)) {
4366+
if (old_execute_data->symbol_table == &EG(symbol_table)) {
4367+
zend_attach_symbol_table(old_execute_data);
4368+
}
4369+
break;
4370+
}
4371+
old_execute_data = old_execute_data->prev_execute_data;
4372+
}
4373+
4374+
destroy_op_array(op_array);
4375+
efree_size(op_array, sizeof(zend_op_array));
4376+
4377+
if (do_bailout) {
4378+
zend_bailout();
4379+
}
4380+
4381+
return ret;
4382+
}
4383+
43154384
static int accel_preload(const char *config)
43164385
{
43174386
zend_file_handle file_handle;
@@ -4606,6 +4675,8 @@ static int accel_preload(const char *config)
46064675
HANDLE_UNBLOCK_INTERRUPTIONS();
46074676

46084677
zend_shared_alloc_destroy_xlat_table();
4678+
4679+
zend_preload_autoload = preload_autoload;
46094680
} else {
46104681
CG(map_ptr_last) = orig_map_ptr_last;
46114682
}

ext/opcache/tests/bug78937_1.phpt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,5 @@ var_dump(foo());
2020
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
2121

2222
Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
23-
24-
Fatal error: Anonymous class wasn't preloaded in %spreload_bug78937.inc on line 3
25-
23+
object(Bar@anonymous)#%d (0) {
24+
}

ext/opcache/tests/bug78937_4.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@ var_dump(new Foo);
2121
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
2222

2323
Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
24-
25-
Fatal error: Class foo wasn't preloaded in %spreload_bug78937.inc on line 6
24+
object(Foo)#%d (0) {
25+
}

0 commit comments

Comments
 (0)