From: Dmitry Stogov Date: Wed, 1 Nov 2017 07:34:39 +0000 (+0300) Subject: Fixed string interning during constants substitution X-Git-Tag: php-7.3.0alpha1~1114^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e0924c52fc7c69b483b5416c609ce7f008584845;p=php Fixed string interning during constants substitution --- diff --git a/Zend/tests/class_constants_005.phpt b/Zend/tests/class_constants_005.phpt new file mode 100644 index 0000000000..de53c2c0ca --- /dev/null +++ b/Zend/tests/class_constants_005.phpt @@ -0,0 +1,12 @@ +--TEST-- +String interning during constants substitution +--INI-- +opcache.enable_cli=0 +--FILE-- + +--EXPECT-- +string(4) ".50." diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index 100d0a263b..bbb4824d1d 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -445,13 +445,21 @@ ZEND_API zend_constant* ZEND_FASTCALL zend_quick_get_constant(const zval *key, u static void* zend_hash_add_constant(HashTable *ht, zend_string *key, zend_constant *c) { - void *ret; - zend_constant *copy = pemalloc(sizeof(zend_constant), c->flags & CONST_PERSISTENT); - - memcpy(copy, c, sizeof(zend_constant)); - ret = zend_hash_add_ptr(ht, key, copy); - if (!ret) { - pefree(copy, c->flags & CONST_PERSISTENT); + zval *ret, tmp; + zend_constant *copy; + + ZVAL_PTR(&tmp, NULL); + ret = zend_hash_add(ht, key, &tmp); + if (EXPECTED(ret)) { + Z_PTR_P(ret) = copy = pemalloc(sizeof(zend_constant), c->flags & CONST_PERSISTENT); + memcpy(copy, c, sizeof(zend_constant)); + if (Z_TYPE(copy->value) == IS_STRING && !ZSTR_IS_INTERNED(Z_STR(copy->value))) { + SEPARATE_STRING(©->value); + Z_STR(copy->value) = zend_new_interned_string(Z_STR(copy->value)); + if (ZSTR_IS_INTERNED(Z_STR(copy->value))) { + Z_TYPE_FLAGS(copy->value) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE); + } + } } return ret; } @@ -466,9 +474,7 @@ ZEND_API int zend_register_constant(zend_constant *c) printf("Registering constant for module %d\n", c->module_number); #endif - if (c->module_number != PHP_USER_CONSTANT) { - c->name = zend_new_interned_string(c->name); - } + c->name = zend_new_interned_string(c->name); if (!(c->flags & CONST_CS)) { lowercase_name = zend_string_alloc(ZSTR_LEN(c->name), c->flags & CONST_PERSISTENT); diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 1d31489429..2a66077631 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -644,6 +644,9 @@ static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_int if (c->name) { c->name = new_interned_string(c->name); } + if (Z_TYPE(c->value) == IS_STRING) { + Z_STR(c->value) = new_interned_string(Z_STR(c->value)); + } } ZEND_HASH_FOREACH_END(); /* auto globals hash keys and names */