diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2020-06-12 10:33:39 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2020-06-12 10:33:39 +0200 |
commit | 0949214ab3f4e60b202282a7ca72a0dd2b93032b (patch) | |
tree | 25d0a7b0db9e0fc9a2470e40db809758ac37a4e0 | |
parent | ece375052b4b6b12e2d5af077d92ca7e26dd8286 (diff) | |
download | php-git-0949214ab3f4e60b202282a7ca72a0dd2b93032b.tar.gz |
Fix null pointer UB in GC
This is just plain stupid: In C, it is not permitted to add zero
to a null pointer. In C++, it is permitted.
-rw-r--r-- | Zend/zend_gc.c | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c index 1daf1d9214..805db23858 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -704,15 +704,17 @@ tail_call: zval *zv, *end; ht = obj->handlers->get_gc(obj, &zv, &n); - end = zv + n; if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_BLACK))) { ht = NULL; if (!n) goto next; + end = zv + n; while (!Z_REFCOUNTED_P(--end)) { if (zv == end) goto next; } } else { GC_REF_SET_BLACK(ht); + if (!n) goto handle_ht; + end = zv + n; } while (zv != end) { if (Z_REFCOUNTED_P(zv)) { @@ -757,6 +759,7 @@ tail_call: goto next; } +handle_ht: if (!ht->nNumUsed) goto next; p = ht->arData; end = p + ht->nNumUsed; @@ -822,15 +825,17 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack) zval *zv, *end; ht = obj->handlers->get_gc(obj, &zv, &n); - end = zv + n; if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_GREY))) { ht = NULL; if (!n) goto next; + end = zv + n; while (!Z_REFCOUNTED_P(--end)) { if (zv == end) goto next; } } else { GC_REF_SET_COLOR(ht, GC_GREY); + if (!n) goto handle_ht; + end = zv + n; } while (zv != end) { if (Z_REFCOUNTED_P(zv)) { @@ -876,6 +881,7 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack) goto next; } +handle_ht: if (!ht->nNumUsed) goto next; p = ht->arData; end = p + ht->nNumUsed; @@ -1006,15 +1012,17 @@ tail_call: zval *zv, *end; ht = obj->handlers->get_gc(obj, &zv, &n); - end = zv + n; if (EXPECTED(!ht) || UNEXPECTED(!GC_REF_CHECK_COLOR(ht, GC_GREY))) { ht = NULL; if (!n) goto next; + end = zv + n; while (!Z_REFCOUNTED_P(--end)) { if (zv == end) goto next; } } else { GC_REF_SET_COLOR(ht, GC_WHITE); + if (!n) goto handle_ht; + end = zv + n; } while (zv != end) { if (Z_REFCOUNTED_P(zv)) { @@ -1057,6 +1065,7 @@ tail_call: goto next; } +handle_ht: if (!ht->nNumUsed) goto next; p = ht->arData; end = p + ht->nNumUsed; @@ -1176,15 +1185,17 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta *flags |= GC_HAS_DESTRUCTORS; } ht = obj->handlers->get_gc(obj, &zv, &n); - end = zv + n; if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_BLACK))) { ht = NULL; if (!n) goto next; + end = zv + n; while (!Z_REFCOUNTED_P(--end)) { if (zv == end) goto next; } } else { GC_REF_SET_BLACK(ht); + if (!n) goto handle_ht; + end = zv + n; } while (zv != end) { if (Z_REFCOUNTED_P(zv)) { @@ -1229,6 +1240,7 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta goto next; } +handle_ht: if (!ht->nNumUsed) goto next; p = ht->arData; end = p + ht->nNumUsed; @@ -1351,12 +1363,15 @@ tail_call: zval *zv, *end; ht = obj->handlers->get_gc(obj, &zv, &n); - end = zv + n; if (EXPECTED(!ht)) { if (!n) return count; + end = zv + n; while (!Z_REFCOUNTED_P(--end)) { if (zv == end) return count; } + } else { + if (!n) goto handle_ht; + end = zv + n; } while (zv != end) { if (Z_REFCOUNTED_P(zv)) { @@ -1382,6 +1397,7 @@ tail_call: return count; } +handle_ht: if (!ht->nNumUsed) return count; p = ht->arData; end = p + ht->nNumUsed; |