diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-05-20 21:54:51 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-05-20 21:57:58 +0100 |
commit | 2f0f4ed0e2ae5657dedfe180b7be3a2496753ba8 (patch) | |
tree | 64717101ae4456bbce7543e983cfb7c68e893895 | |
parent | 97b4aeba44e5f4b23b3ed417b991570b46d4736e (diff) |
freed-pool: Don't access beyond the end of the array.
Argh. This bug has been here for quite some time and only showed itself
with a corrupt pointer on ppc32. Since the erroneous write is inside the
block, it remained undetected by valgrind.
-rw-r--r-- | src/cairo-freed-pool-private.h | 8 | ||||
-rw-r--r-- | src/cairo-freed-pool.c | 4 |
2 files changed, 8 insertions, 4 deletions
diff --git a/src/cairo-freed-pool-private.h b/src/cairo-freed-pool-private.h index 08fdd944..0a4ab0ee 100644 --- a/src/cairo-freed-pool-private.h +++ b/src/cairo-freed-pool-private.h @@ -50,7 +50,7 @@ typedef struct { int top; } freed_pool_t; -static inline void * +static cairo_always_inline void * _atomic_fetch (void **slot) { void *ptr; @@ -62,7 +62,7 @@ _atomic_fetch (void **slot) return ptr; } -static inline cairo_bool_t +static cairo_always_inline cairo_bool_t _atomic_store (void **slot, void *ptr) { return _cairo_atomic_ptr_cmpxchg (slot, NULL, ptr); @@ -100,7 +100,9 @@ _freed_pool_put (freed_pool_t *pool, void *ptr) int i; i = pool->top; - if (likely (_atomic_store (&pool->pool[i], ptr))) { + if (likely (i < ARRAY_LENGTH (pool->pool) && + _atomic_store (&pool->pool[i], ptr))) + { pool->top = i + 1; return; } diff --git a/src/cairo-freed-pool.c b/src/cairo-freed-pool.c index 9d426930..cfdc8e96 100644 --- a/src/cairo-freed-pool.c +++ b/src/cairo-freed-pool.c @@ -73,7 +73,7 @@ _freed_pool_put_search (freed_pool_t *pool, void *ptr) } /* full */ - pool->top = ARRAY_LENGTH (pool->pool); + pool->top = i; free (ptr); } @@ -86,6 +86,8 @@ _freed_pool_reset (freed_pool_t *pool) free (pool->pool[i]); pool->pool[i] = NULL; } + + pool->top = 0; } #endif |