]> granicus.if.org Git - php/commitdiff
Merge branch 'PHP-7.2' into PHP-7.3
authorDmitry Stogov <dmitry@zend.com>
Fri, 9 Aug 2019 10:39:59 +0000 (13:39 +0300)
committerDmitry Stogov <dmitry@zend.com>
Fri, 9 Aug 2019 10:39:59 +0000 (13:39 +0300)
* PHP-7.2:
  Added asserts to catch GC errors when refcount goes below zero.

1  2 
Zend/zend_gc.c

diff --cc Zend/zend_gc.c
index 8b9ee176326aecda85188ee6d69ff439c54c860f,30ca4d0a2a89341e1768bd9eacf9d6fe9240e399..60fa7fdd1567402980e19cf9eab18fe2276a3cc3
@@@ -829,25 -507,20 +829,27 @@@ static void gc_mark_grey(zend_refcounte
                                while (zv != end) {
                                        if (Z_REFCOUNTED_P(zv)) {
                                                ref = Z_COUNTED_P(zv);
 -                                              GC_REFCOUNT(ref)--;
 -                                              gc_mark_grey(ref);
+                                               ZEND_ASSERT(GC_REFCOUNT(ref) > 0);
 +                                              GC_DELREF(ref);
 +                                              if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) {
 +                                                      GC_REF_SET_COLOR(ref, GC_GREY);
 +                                                      GC_STACK_PUSH(ref);
 +                                              }
                                        }
                                        zv++;
                                }
                                if (EXPECTED(!ht)) {
                                        ref = Z_COUNTED_P(zv);
 -                                      GC_REFCOUNT(ref)--;
 -                                      goto tail_call;
+                                       ZEND_ASSERT(GC_REFCOUNT(ref) > 0);
 +                                      GC_DELREF(ref);
 +                                      if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) {
 +                                              GC_REF_SET_COLOR(ref, GC_GREY);
 +                                              continue;
 +                                      }
 +                                      goto next;
                                }
                        } else {
 -                              return;
 +                              goto next;
                        }
                } else if (GC_TYPE(ref) == IS_ARRAY) {
                        if (((zend_array*)ref) == &EG(symbol_table)) {
                } else if (GC_TYPE(ref) == IS_REFERENCE) {
                        if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
                                ref = Z_COUNTED(((zend_reference*)ref)->val);
 -                              GC_REFCOUNT(ref)--;
 -                              goto tail_call;
+                               ZEND_ASSERT(GC_REFCOUNT(ref) > 0);
 +                              GC_DELREF(ref);
 +                              if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) {
 +                                      GC_REF_SET_COLOR(ref, GC_GREY);
 +                                      continue;
 +                              }
                        }
 -                      return;
 +                      goto next;
                } else {
 -                      return;
 +                      goto next;
                }
  
 -              if (!ht->nNumUsed) return;
 +              if (!ht->nNumUsed) goto next;
                p = ht->arData;
                end = p + ht->nNumUsed;
                while (1) {
                        }
                        if (Z_REFCOUNTED_P(zv)) {
                                ref = Z_COUNTED_P(zv);
 -                              GC_REFCOUNT(ref)--;
 -                              gc_mark_grey(ref);
+                               ZEND_ASSERT(GC_REFCOUNT(ref) > 0);
 +                              GC_DELREF(ref);
 +                              if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) {
 +                                      GC_REF_SET_COLOR(ref, GC_GREY);
 +                                      GC_STACK_PUSH(ref);
 +                              }
                        }
                        p++;
                }
                        zv = Z_INDIRECT_P(zv);
                }
                ref = Z_COUNTED_P(zv);
 -              GC_REFCOUNT(ref)--;
 -              goto tail_call;
+               ZEND_ASSERT(GC_REFCOUNT(ref) > 0);
 +              GC_DELREF(ref);
 +              if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) {
 +                      GC_REF_SET_COLOR(ref, GC_GREY);
 +                      continue;
 +              }
 +
 +next:
 +              ref = GC_STACK_POP();
 +      } while (ref);
 +}
 +
 +/* Two-Finger compaction algorithm */
 +static void gc_compact(void)
 +{
 +      if (GC_G(num_roots) + GC_FIRST_ROOT != GC_G(first_unused)) {
 +              if (GC_G(num_roots)) {
 +                      gc_root_buffer *free = GC_IDX2PTR(GC_FIRST_ROOT);
 +                      gc_root_buffer *scan = GC_IDX2PTR(GC_G(first_unused) - 1);
 +                      gc_root_buffer *end  = GC_IDX2PTR(GC_G(num_roots));
 +                      uint32_t idx;
 +                      zend_refcounted *p;
 +
 +                      while (free < scan) {
 +                              while (!GC_IS_UNUSED(free->ref)) {
 +                                      free++;
 +                              }
 +                              while (GC_IS_UNUSED(scan->ref)) {
 +                                      scan--;
 +                              }
 +                              if (scan > free) {
 +                                      p = scan->ref;
 +                                      free->ref = p;
 +                                      p = GC_GET_PTR(p);
 +                                      idx = gc_compress(GC_PTR2IDX(free));
 +                                      GC_REF_SET_INFO(p, idx | GC_REF_COLOR(p));
 +                                      free++;
 +                                      scan--;
 +                                      if (scan <= end) {
 +                                              break;
 +                                      }
 +                              }
 +                      }
 +              }
 +              GC_G(unused) = GC_INVALID;
 +              GC_G(first_unused) = GC_G(num_roots) + GC_FIRST_ROOT;
        }
  }