]> granicus.if.org Git - php/commitdiff
Merge branch 'PHP-7.0' into PHP-7.1
authorXinchen Hui <laruence@gmail.com>
Mon, 13 Feb 2017 11:17:09 +0000 (19:17 +0800)
committerXinchen Hui <laruence@gmail.com>
Mon, 13 Feb 2017 11:17:09 +0000 (19:17 +0800)
* PHP-7.0:
  Fixed bug  #73989 (PHP 7.1 Segfaults within Symfony test suite)

1  2 
Zend/zend_gc.c

diff --cc Zend/zend_gc.c
index a125c44ae44d67e2850880183acaffa87f61a380,0b9ce8ccc5b6b1ba094f85d7be6c33738c663f4e..087f04bc3ff78121c3daa27db5e4bc04a53a853b
@@@ -714,27 -678,26 +728,25 @@@ static void gc_add_garbage(zend_refcoun
  #endif
        } else {
                /* If we don't have free slots in the buffer, allocate a new one and
-                * set it's address to GC_ROOT_BUFFER_MAX_ENTRIES that have special
+                * set it's address above GC_ROOT_BUFFER_MAX_ENTRIES that have special
                 * meaning.
                 */
-               if (!*additional_buffer || (*additional_buffer)->used == GC_NUM_ADDITIONAL_ENTRIES) {
+               if (!GC_G(additional_buffer) || GC_G(additional_buffer)->used == GC_NUM_ADDITIONAL_ENTRIES) {
                        gc_additional_buffer *new_buffer = emalloc(sizeof(gc_additional_buffer));
                        new_buffer->used = 0;
-                       new_buffer->next = *additional_buffer;
-                       *additional_buffer = new_buffer;
+                       new_buffer->next = GC_G(additional_buffer);
+                       GC_G(additional_buffer) = new_buffer;
                }
-               buf = (*additional_buffer)->buf + (*additional_buffer)->used;
-               (*additional_buffer)->used++;
+               buf = GC_G(additional_buffer)->buf + GC_G(additional_buffer)->used;
  #if 1
                /* optimization: color is already GC_BLACK (0) */
-               GC_INFO(ref) = GC_ROOT_BUFFER_MAX_ENTRIES;
+               GC_INFO(ref) = GC_ROOT_BUFFER_MAX_ENTRIES + GC_G(additional_buffer)->used;
  #else
-               GC_REF_SET_ADDRESS(ref, GC_ROOT_BUFFER_MAX_ENTRIES);
+               GC_REF_SET_ADDRESS(ref, GC_ROOT_BUFFER_MAX_ENTRIES) + GC_G(additional_buffer)->used;
  #endif
-               /* modify type to prevent indirect destruction */
-               GC_TYPE(ref) |= GC_FAKE_BUFFER_FLAG;
+               GC_G(additional_buffer)->used++;
        }
        if (buf) {
 -              GC_REFCOUNT(ref)++;
                buf->ref = ref;
                buf->next = GC_G(roots).next;
                buf->prev = &GC_G(roots);
@@@ -897,8 -864,9 +913,8 @@@ static int gc_collect_roots(uint32_t *f
  
        current = GC_G(roots).next;
        while (current != &GC_G(roots)) {
 -              GC_REFCOUNT(current->ref)++;
                if (GC_REF_GET_COLOR(current->ref) == GC_WHITE) {
-                       count += gc_collect_white(current->ref, flags, additional_buffer);
+                       count += gc_collect_white(current->ref, flags);
                }
                current = current->next;
        }
@@@ -934,12 -902,16 +950,15 @@@ static void gc_remove_nested_data_from_
  tail_call:
        if (root ||
            (GC_ADDRESS(GC_INFO(ref)) != 0 &&
-            GC_REF_GET_COLOR(ref) == GC_BLACK &&
-            GC_ADDRESS(GC_INFO(ref)) != GC_ROOT_BUFFER_MAX_ENTRIES)) {
+            GC_REF_GET_COLOR(ref) == GC_BLACK)) {
                GC_TRACE_REF(ref, "removing from buffer");
 -              GC_REFCOUNT(ref)--;
                if (root) {
+                       if (EXPECTED(GC_ADDRESS(GC_INFO(root->ref)) < GC_ROOT_BUFFER_MAX_ENTRIES)) {
+                               gc_remove_from_roots(root);
+                       } else {
+                               gc_remove_from_additional_roots(root);
+                       }
                        GC_INFO(ref) = 0;
-                       GC_REMOVE_FROM_ROOTS(root);
                        root = NULL;
                } else {
                        GC_REMOVE_FROM_BUFFER(ref);