summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-05-20 21:54:51 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2010-05-20 21:57:58 +0100
commit2f0f4ed0e2ae5657dedfe180b7be3a2496753ba8 (patch)
tree64717101ae4456bbce7543e983cfb7c68e893895
parent97b4aeba44e5f4b23b3ed417b991570b46d4736e (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.h8
-rw-r--r--src/cairo-freed-pool.c4
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