]> granicus.if.org Git - php/commitdiff
We don't need to dup zend_class_constant here.
authorXinchen Hui <laruence@gmail.com>
Fri, 22 Jan 2016 03:22:37 +0000 (11:22 +0800)
committerXinchen Hui <laruence@gmail.com>
Fri, 22 Jan 2016 03:22:37 +0000 (11:22 +0800)
quote why the internal class is still using duplication:
```
for internal classes, the zend_class_constant is malloc-ed. we need to
free it.

if (const->ce == ce) {
zval_ptr_dtor(&const->value);
free(const)
}
so, if two classes share one const, and it(parent class) was freed
before, this read(in child class, const->ce) is invalid..

and destroy_zend_class is called via zend_hash_destroy(class_table).
which is not in reverse order... so, parent classes are dtor first.

if we want this work, we should change that order.
```

Zend/zend_inheritance.c
Zend/zend_opcode.c

index 2226f6013dcd1aab69591d00ad94181653acaffc..e3ef6a699187d66ab30f1d73b639d8473a4e4656 100644 (file)
@@ -724,15 +724,15 @@ static void do_inherit_class_constant(zend_string *name, zend_class_constant *pa
                if (Z_CONSTANT(parent_const->value)) {
                        ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
                }
-               if (Z_REFCOUNTED(parent_const->value)) {
-                       Z_ADDREF(parent_const->value);
-               }
                if (ce->type & ZEND_INTERNAL_CLASS) {
+                       if (Z_REFCOUNTED(parent_const->value)) {
+                               Z_ADDREF(parent_const->value);
+                       }
                        c = pemalloc(sizeof(zend_class_constant), 1);
+                       memcpy(c, parent_const, sizeof(zend_class_constant));
                } else {
-                       c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
+                       c = parent_const;
                }
-               memcpy(c, parent_const, sizeof(zend_class_constant));
                _zend_hash_append_ptr(&ce->constants_table, name, c);
        }
 }
@@ -934,18 +934,18 @@ static void do_inherit_iface_constant(zend_string *name, zend_class_constant *c,
 {
        if (do_inherit_constant_check(&ce->constants_table, c, name, iface)) {
                zend_class_constant *ct;
-               if (Z_REFCOUNTED(c->value)) {
-                       Z_ADDREF(c->value);
-               }
                if (Z_CONSTANT(c->value)) {
                        ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
                }
                if (ce->type & ZEND_INTERNAL_CLASS) {
+                       if (Z_REFCOUNTED(c->value)) {
+                               Z_ADDREF(c->value);
+                       }
                        ct = pemalloc(sizeof(zend_class_constant), 1);
+                       memcpy(ct, c, sizeof(zend_class_constant));
                } else {
-                       ct = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
+                       ct = c;
                }
-               memcpy(ct, c, sizeof(zend_class_constant));
                zend_hash_update_ptr(&ce->constants_table, name, ct);
        }
 }
index cff294854ce2846a66cee368b14231f2072e032b..8b55037794d9ae036a75b099c5b7da89bf799fb0 100644 (file)
@@ -291,9 +291,11 @@ ZEND_API void destroy_zend_class(zval *zv)
                                zend_class_constant *c;
 
                                ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
-                                       zval_ptr_dtor(&c->value);
-                                       if (c->doc_comment && c->ce == ce) {
-                                               zend_string_release(c->doc_comment);
+                                       if (c->ce == ce) {
+                                               zval_ptr_dtor(&c->value);
+                                               if (c->doc_comment) {
+                                                       zend_string_release(c->doc_comment);
+                                               }
                                        }
                                } ZEND_HASH_FOREACH_END();
                                zend_hash_destroy(&ce->constants_table);