From eab63a38f0a09a33fc74645161b1f067287154af Mon Sep 17 00:00:00 2001 From: Paul Olteanu <170131110+cmpwi@users.noreply.github.com> Date: Sun, 19 Apr 2026 00:09:59 -0400 Subject: [PATCH 1/3] Fix conflicting checks for stop point in arc.mm:emptyPool() --- arc.mm | 68 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/arc.mm b/arc.mm index 502ab450..3b4758f4 100644 --- a/arc.mm +++ b/arc.mm @@ -155,57 +155,71 @@ - (void)release; /** * Empties objects from the autorelease pool, stating at the head of the list - * specified by pool and continuing until it reaches the stop point. If the stop point is NULL then + * specified by pool and continuing until it reaches the stop point. If the stop + * point is NULL then all pools are cleared. */ -static void emptyPool(struct arc_tls *tls, void *stop) +static void emptyPool(struct arc_tls *tls, void *stopAt) { + /* Clear all pools by default. */ struct arc_autorelease_pool *stopPool = NULL; - if (NULL != stop) + void *oldPool; + + /* Are we clearing up to a given object? */ + if (stopAt != NULL) { stopPool = tls->pool; - while (1) + + /* Find pool in which object to stop at is located. */ + while (stopPool != NULL) { - // Invalid stop location - if (NULL == stopPool) - { - return; - } - // NULL is the placeholder for the top-level pool - if (NULL == stop && stopPool->previous == NULL) - { - break; - } - // Stop location was found in this pool - if ((stop >= stopPool->pool) && (stop < &stopPool->pool[POOL_SIZE])) + if (stopAt >= (void *)stopPool->pool && + stopAt < (void *)&stopPool->pool[POOL_SIZE]) { break; } + stopPool = stopPool->previous; } + + /* Invalid pointer, quit. */ + if (stopPool == NULL) + { + return; + } } - do { + + do + { + /* Clear all pools up to the stop pool. */ while (tls->pool != stopPool) { while (tls->pool->insert > tls->pool->pool) { - tls->pool->insert--; - // This may autorelease some other objects, so we have to work in - // the case where the autorelease pool is extended during a -release. + --tls->pool->insert; release(*tls->pool->insert); } - void *old = tls->pool; + + oldPool = tls->pool; tls->pool = tls->pool->previous; - free(old); + free(oldPool); } - if (NULL == tls->pool) break; - while ((stop == NULL || (tls->pool->insert > stop)) && - (tls->pool->insert > tls->pool->pool)) + + /* If we cleared them all, quit. */ + if (tls->pool == NULL) { - tls->pool->insert--; + return; + } + + /* Release objects up to the stopping point, if necessary. */ + while (tls->pool->insert > (id *)stopAt) + { + --tls->pool->insert; release(*tls->pool->insert); } + + /* Be sure that releasing objects did not push any new pools. */ } while (tls->pool != stopPool); - //fprintf(stderr, "New insert: %p. Stop: %p\n", tls->pool->insert, stop); + /* fprintf(stderr, "New insert: %p. Stop: %p\n", tls->pool->insert, stop); */ } #ifdef arc_tls_store From ee3b6f2e6cf07aec5c8bd86f9aff3439d8899396 Mon Sep 17 00:00:00 2001 From: Paul Olteanu <170131110+cmpwi@users.noreply.github.com> Date: Sun, 19 Apr 2026 12:37:16 -0400 Subject: [PATCH 2/3] Guard against releasing bogus objects behind the current autorelease pool while looping to the stopping point --- arc.mm | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arc.mm b/arc.mm index 3b4758f4..21d98fa3 100644 --- a/arc.mm +++ b/arc.mm @@ -210,8 +210,12 @@ static void emptyPool(struct arc_tls *tls, void *stopAt) return; } - /* Release objects up to the stopping point, if necessary. */ - while (tls->pool->insert > (id *)stopAt) + /* + * Release objects down to the stopping point, but never below + * the pool's base. + */ + while (tls->pool->insert > (id *)stopAt && + tls->pool->insert > tls->pool->pool) { --tls->pool->insert; release(*tls->pool->insert); From 9d69a6d1f44fcdf68f7b1df48163b8d9b26d37a5 Mon Sep 17 00:00:00 2001 From: Paul Olteanu <170131110+cmpwi@users.noreply.github.com> Date: Sun, 19 Apr 2026 12:48:37 -0400 Subject: [PATCH 3/3] Comment fix-up --- arc.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arc.mm b/arc.mm index 21d98fa3..3ec541bc 100644 --- a/arc.mm +++ b/arc.mm @@ -211,8 +211,8 @@ static void emptyPool(struct arc_tls *tls, void *stopAt) } /* - * Release objects down to the stopping point, but never below - * the pool's base. + * Release objects down to the stopping point. If a new pool is + * pushed, never release below the pool's base. */ while (tls->pool->insert > (id *)stopAt && tls->pool->insert > tls->pool->pool)