From 4e8bba937338521017bb4a3ac69dd3dfdb306d3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Schr=C3=B6der?= Date: Fri, 1 May 2020 11:54:58 +0200 Subject: [PATCH 1/2] Implemented attribute storage in file-based Opcache. --- ext/opcache/zend_file_cache.c | 72 +++++++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 11 deletions(-) diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index a5d661c7a544f..8e6dd30c93672 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -21,6 +21,7 @@ #include "zend_compile.h" #include "zend_vm.h" #include "zend_interfaces.h" +#include "zend_attributes.h" #include "php.h" #ifdef ZEND_WIN32 @@ -158,22 +159,22 @@ static int zend_file_cache_flock(int fd, int type) } \ } while (0) -#define SERIALIZE_ATTRIBUTES(attr) do { \ - if ((attr) && !IS_SERIALIZED(attr)) { \ +#define SERIALIZE_ATTRIBUTES(attributes) do { \ + if ((attributes) && !IS_SERIALIZED(attributes)) { \ HashTable *ht; \ - SERIALIZE_PTR(attr); \ - ht = (attr); \ + SERIALIZE_PTR(attributes); \ + ht = (attributes); \ UNSERIALIZE_PTR(ht); \ - zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval); \ + zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_attribute); \ } \ } while (0) -#define UNSERIALIZE_ATTRIBUTES(attr) do { \ - if ((attr) && !IS_UNSERIALIZED(attr)) { \ +#define UNSERIALIZE_ATTRIBUTES(attributes) do { \ + if ((attributes) && !IS_UNSERIALIZED(attributes)) { \ HashTable *ht; \ - UNSERIALIZE_PTR(attr); \ - ht = (attr); \ - zend_file_cache_unserialize_hash(ht, script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR); \ + UNSERIALIZE_PTR(attributes); \ + ht = (attributes); \ + zend_file_cache_unserialize_hash(ht, script, buf, zend_file_cache_unserialize_attribute, NULL); \ } \ } while (0) @@ -390,6 +391,33 @@ static void zend_file_cache_serialize_zval(zval *zv, } } +static void zend_file_cache_serialize_attribute(zval *zv, + zend_persistent_script *script, + zend_file_cache_metainfo *info, + void *buf) +{ + if (!IS_SERIALIZED(Z_PTR_P(zv))) { + zend_attribute *attr = Z_PTR_P(zv); + uint32_t i; + + SERIALIZE_PTR(Z_PTR_P(zv)); + attr = Z_PTR_P(zv); + UNSERIALIZE_PTR(attr); + + if (!IS_SERIALIZED(attr->name)) { + SERIALIZE_STR(attr->name); + } + + if (!IS_SERIALIZED(attr->lcname)) { + SERIALIZE_STR(attr->lcname); + } + + for (i = 0; i < attr->argc; i++) { + zend_file_cache_serialize_zval(&attr->argv[i], script, info, buf); + } + } +} + static void zend_file_cache_serialize_type( zend_type *type, zend_persistent_script *script, zend_file_cache_metainfo *info, void *buf) { @@ -613,7 +641,6 @@ static void zend_file_cache_serialize_prop_info(zval *zv, SERIALIZE_STR(prop->doc_comment); } SERIALIZE_ATTRIBUTES(prop->attributes); - zend_file_cache_serialize_type(&prop->type, script, info, buf); } } @@ -1118,6 +1145,29 @@ static void zend_file_cache_unserialize_zval(zval *zv, } } +static void zend_file_cache_unserialize_attribute(zval *zv, zend_persistent_script *script, void *buf) +{ + if (!IS_UNSERIALIZED(Z_PTR_P(zv))) { + zend_attribute *attr; + uint32_t i; + + UNSERIALIZE_PTR(Z_PTR_P(zv)); + attr = Z_PTR_P(zv); + + if (!IS_UNSERIALIZED(attr->name)) { + UNSERIALIZE_STR(attr->name); + } + + if (!IS_UNSERIALIZED(attr->lcname)) { + UNSERIALIZE_STR(attr->lcname); + } + + for (i = 0; i < attr->argc; i++) { + zend_file_cache_unserialize_zval(&attr->argv[i], script, buf); + } + } +} + static void zend_file_cache_unserialize_type( zend_type *type, zend_persistent_script *script, void *buf) { From 2468119c2d6f2da2545f437c11af7ef0e3df67f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Schr=C3=B6der?= Date: Fri, 1 May 2020 11:55:28 +0200 Subject: [PATCH 2/2] Fixed parameter offset bug. Refined test case to detect this. --- Zend/tests/attributes/001_placement.phpt | 19 +++++++++++++++++-- Zend/zend_compile.c | 2 +- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Zend/tests/attributes/001_placement.phpt b/Zend/tests/attributes/001_placement.phpt index a99500570a5df..02e6c27aa415c 100644 --- a/Zend/tests/attributes/001_placement.phpt +++ b/Zend/tests/attributes/001_placement.phpt @@ -43,68 +43,83 @@ $sources = [ ]; foreach ($sources as $r) { - foreach ($r->getAttributes() as $attr) { - var_dump($attr->getName(), $attr->getArguments()); + $attr = $r->getAttributes(); + var_dump(count($attr)); + + foreach ($attr as $a) { + var_dump($a->getName(), $a->getArguments()); } } ?> --EXPECT-- +int(1) string(2) "A1" array(1) { [0]=> int(1) } +int(1) string(2) "A1" array(1) { [0]=> int(2) } +int(1) string(2) "A1" array(1) { [0]=> int(2) } +int(1) string(2) "A1" array(1) { [0]=> int(3) } +int(1) string(2) "A1" array(1) { [0]=> int(3) } +int(1) string(2) "A1" array(1) { [0]=> int(4) } +int(1) string(2) "A1" array(1) { [0]=> int(5) } +int(1) string(2) "A1" array(1) { [0]=> int(6) } +int(1) string(2) "A1" array(1) { [0]=> int(7) } +int(1) string(2) "A1" array(1) { [0]=> int(8) } +int(1) string(2) "A1" array(1) { [0]=> int(9) } +int(1) string(2) "A1" array(1) { [0]=> diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 2ebf5131ccddd..66f6b313daa12 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5769,7 +5769,7 @@ static void zend_compile_attributes(HashTable *attributes, zend_ast *ast, uint32 ZEND_ASSERT(ast->kind == ZEND_AST_ATTRIBUTE_LIST); for (i = 0; i < list->children; i++) { - zend_attribute *attr = zend_compile_attribute(list->child[i], 0); + zend_attribute *attr = zend_compile_attribute(list->child[i], offset); // Validate internal attribute zend_attributes_internal_validator validator = zend_hash_find_ptr(&zend_attributes_internal_validators, attr->lcname);