summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-05-19 10:13:25 +0200
committerNikita Popov <nikita.ppv@gmail.com>2020-05-20 11:22:50 +0200
commit4f47ba99f002d50e11c111b8625d81f79b2bf52f (patch)
tree52c359d89a0f44d8a1ddff520944c28441d8d87c
parentdb0cdcbb0a224f958870125a13bd5901fa6e8a0f (diff)
downloadphp-git-4f47ba99f002d50e11c111b8625d81f79b2bf52f.tar.gz
Fix bug #79603, by retrying on RTD key collision
This is a non-intrusive fix for 7.4, still trying to find a good solution for master. Closes GH-5597.
-rw-r--r--NEWS1
-rw-r--r--Zend/zend_compile.c34
2 files changed, 23 insertions, 12 deletions
diff --git a/NEWS b/NEWS
index 0e0a1e497d..29d1a22a4e 100644
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,7 @@ PHP NEWS
. Fixed bug #79588 (Boolean opcache settings ignore on/off values). (cmb)
. Fixed bug #79548 (Preloading segfault with inherited method using static
variable). (Nikita)
+ . Fixed bug #79603 (RTD collision with opcache). (Nikita)
- SimpleXML:
. Fixed bug #79528 (Different object of the same xml between 7.4.5 and
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 0f948e000b..c498f95347 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -5934,11 +5934,12 @@ static void zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_as
return;
}
- key = zend_build_runtime_definition_key(lcname, decl->start_lineno);
- if (!zend_hash_add_ptr(CG(function_table), key, op_array)) {
- zend_error_noreturn(E_ERROR,
- "Runtime definition key collision for function %s. This is a bug", ZSTR_VAL(name));
- }
+ /* Generate RTD keys until we find one that isn't in use yet. */
+ key = NULL;
+ do {
+ zend_tmp_string_release(key);
+ key = zend_build_runtime_definition_key(lcname, decl->start_lineno);
+ } while (!zend_hash_add_ptr(CG(function_table), key, op_array));
if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
opline = zend_emit_op_tmp(result, ZEND_DECLARE_LAMBDA_FUNCTION, NULL, NULL);
@@ -6404,8 +6405,15 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */
zend_register_seen_symbol(lcname, ZEND_SYMBOL_CLASS);
} else {
- name = zend_generate_anon_class_name(decl->start_lineno);
- lcname = zend_string_tolower(name);
+ /* Find an anon class name that is not in use yet. */
+ name = NULL;
+ lcname = NULL;
+ do {
+ zend_tmp_string_release(name);
+ zend_tmp_string_release(lcname);
+ name = zend_generate_anon_class_name(decl->start_lineno);
+ lcname = zend_string_tolower(name);
+ } while (zend_hash_exists(CG(class_table), lcname));
}
lcname = zend_new_interned_string(lcname);
@@ -6562,18 +6570,20 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */
opline->result_type = IS_VAR;
opline->result.var = get_temporary_variable();
if (!zend_hash_add_ptr(CG(class_table), lcname, ce)) {
+ /* We checked above that the class name is not used. This really shouldn't happen. */
zend_error_noreturn(E_ERROR,
"Runtime definition key collision for %s. This is a bug", ZSTR_VAL(name));
}
} else {
- zend_string *key = zend_build_runtime_definition_key(lcname, decl->start_lineno);
+ /* Generate RTD keys until we find one that isn't in use yet. */
+ zend_string *key = NULL;
+ do {
+ zend_tmp_string_release(key);
+ key = zend_build_runtime_definition_key(lcname, decl->start_lineno);
+ } while (!zend_hash_add_ptr(CG(class_table), key, ce));
/* RTD key is placed after lcname literal in op1 */
zend_add_literal_string(&key);
- if (!zend_hash_add_ptr(CG(class_table), key, ce)) {
- zend_error_noreturn(E_ERROR,
- "Runtime definition key collision for class %s. This is a bug", ZSTR_VAL(name));
- }
opline->opcode = ZEND_DECLARE_CLASS;
if (extends_ast && toplevel