Skip to content

Commit 6ab30dc

Browse files
committed
fix(opcache, reflection): plug two memory leaks in generics persistence and reflection cleanup
Signed-off-by: azjezz <azjezz@protonmail.com>
1 parent 1487315 commit 6ab30dc

3 files changed

Lines changed: 45 additions & 14 deletions

File tree

ext/opcache/zend_persist.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -438,14 +438,27 @@ static zend_generic_parameter_list *zend_persist_generic_parameter_list(zend_gen
438438

439439
static HashTable *zend_persist_generic_type_table_ht(HashTable *ht)
440440
{
441-
zval *v;
442441
zend_hash_persist(ht);
443-
ZEND_HASH_FOREACH_VAL(ht, v) {
444-
zend_type *boxed = Z_PTR_P(v);
445-
zend_type *copy = zend_shared_memdup_put_free(boxed, sizeof(zend_type));
446-
zend_persist_type(copy);
447-
ZVAL_PTR(v, copy);
448-
} ZEND_HASH_FOREACH_END();
442+
if (HT_IS_PACKED(ht)) {
443+
zval *v;
444+
ZEND_HASH_PACKED_FOREACH_VAL(ht, v) {
445+
zend_type *boxed = Z_PTR_P(v);
446+
zend_type *copy = zend_shared_memdup_put_free(boxed, sizeof(zend_type));
447+
zend_persist_type(copy);
448+
Z_PTR_P(v) = copy;
449+
} ZEND_HASH_FOREACH_END();
450+
} else {
451+
Bucket *p;
452+
ZEND_HASH_MAP_FOREACH_BUCKET(ht, p) {
453+
if (p->key) {
454+
zend_accel_store_interned_string(p->key);
455+
}
456+
zend_type *boxed = Z_PTR(p->val);
457+
zend_type *copy = zend_shared_memdup_put_free(boxed, sizeof(zend_type));
458+
zend_persist_type(copy);
459+
Z_PTR(p->val) = copy;
460+
} ZEND_HASH_FOREACH_END();
461+
}
449462
HashTable *ptr = zend_shared_memdup_put_free(ht, sizeof(HashTable));
450463
GC_SET_REFCOUNT(ptr, 2);
451464
GC_TYPE_INFO(ptr) = GC_ARRAY | ((IS_ARRAY_IMMUTABLE|GC_NOT_COLLECTABLE) << GC_FLAGS_SHIFT);

ext/opcache/zend_persist_calc.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -257,12 +257,23 @@ static void zend_persist_generic_parameter_list_calc(zend_generic_parameter_list
257257

258258
static void zend_persist_generic_type_table_ht_calc(HashTable *ht)
259259
{
260-
zval *v;
261260
zend_hash_persist_calc(ht);
262-
ZEND_HASH_FOREACH_VAL(ht, v) {
263-
ADD_SIZE(sizeof(zend_type));
264-
zend_persist_type_calc((zend_type *) Z_PTR_P(v));
265-
} ZEND_HASH_FOREACH_END();
261+
if (HT_IS_PACKED(ht)) {
262+
zval *v;
263+
ZEND_HASH_PACKED_FOREACH_VAL(ht, v) {
264+
ADD_SIZE(sizeof(zend_type));
265+
zend_persist_type_calc((zend_type *) Z_PTR_P(v));
266+
} ZEND_HASH_FOREACH_END();
267+
} else {
268+
Bucket *p;
269+
ZEND_HASH_MAP_FOREACH_BUCKET(ht, p) {
270+
if (p->key) {
271+
ADD_INTERNED_STRING(p->key);
272+
}
273+
ADD_SIZE(sizeof(zend_type));
274+
zend_persist_type_calc((zend_type *) Z_PTR(p->val));
275+
} ZEND_HASH_FOREACH_END();
276+
}
266277
ADD_SIZE(sizeof(HashTable));
267278
}
268279

ext/reflection/php_reflection.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,8 @@ typedef enum {
179179
REF_TYPE_TYPE,
180180
REF_TYPE_PROPERTY,
181181
REF_TYPE_CLASS_CONSTANT,
182-
REF_TYPE_ATTRIBUTE
182+
REF_TYPE_ATTRIBUTE,
183+
REF_TYPE_GENERIC_PARAMETER
183184
} reflection_type_t;
184185

185186
/* Struct for reflection objects */
@@ -281,6 +282,12 @@ static void reflection_free_objects_storage(zend_object *object) /* {{{ */
281282
efree(intern->ptr);
282283
break;
283284
}
285+
case REF_TYPE_GENERIC_PARAMETER: {
286+
generic_parameter_reference *ref = intern->ptr;
287+
zval_ptr_dtor(&ref->declaring);
288+
efree(ref);
289+
break;
290+
}
284291
case REF_TYPE_GENERATOR:
285292
case REF_TYPE_FIBER:
286293
case REF_TYPE_CLASS_CONSTANT:
@@ -8290,7 +8297,7 @@ static void reflection_generic_type_parameter_factory(
82908297
reference->index = index;
82918298
ZVAL_COPY(&reference->declaring, declaring);
82928299
intern->ptr = reference;
8293-
intern->ref_type = REF_TYPE_OTHER;
8300+
intern->ref_type = REF_TYPE_GENERIC_PARAMETER;
82948301

82958302
ZVAL_STR_COPY(reflection_prop_name(object), param->name);
82968303
}

0 commit comments

Comments
 (0)