From 2135fd4a49eff16284397982448f1496fa9361ca Mon Sep 17 00:00:00 2001 From: Fujii Hironori Date: Tue, 10 Jan 2023 15:12:07 +0900 Subject: [PATCH] sizeof(cairo_atomic_int_t) should be sizeof(int) `_cairo_status_set_error` was using `_cairo_atomic_int_cmpxchg` to set a `cairo_status_t` variable by casting a `cairo_status_t*` to `cairo_atomic_int_t*`. `cairo_atomic_int` has a generic implementation which is using a mutex. In the implementation, `cairo_atomic_int_t` was typedef-ed to `cairo_atomic_intptr_t`. In a typical 64bit system, cairo_atomic_intptr_t is 64bit and cairo_status_t is 32bit, _cairo_status_set_error didn't work as expected. Define `cairo_atomic_int_t` as an alias of `int`. Added an assertion in `_cairo_status_set_error` to ensure that `*err` has the same size with `cairo_atomic_int_t`. Fixes cairo/cairo#606 --- src/cairo-atomic-private.h | 8 +++++--- src/cairo-atomic.c | 34 +++++++++++++++++++++++----------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/cairo-atomic-private.h b/src/cairo-atomic-private.h index a9eb38a7f..727f97c75 100644 --- a/src/cairo-atomic-private.h +++ b/src/cairo-atomic-private.h @@ -340,6 +340,8 @@ _cairo_atomic_ptr_cmpxchg_return_old (void **x, void *oldv, void *newv) #ifndef HAS_ATOMIC_OPS +typedef int cairo_atomic_int_t; + #if SIZEOF_VOID_P==SIZEOF_INT typedef unsigned int cairo_atomic_intptr_t; #elif SIZEOF_VOID_P==SIZEOF_LONG @@ -350,8 +352,6 @@ typedef unsigned long long cairo_atomic_intptr_t; #error No matching integer pointer type #endif -typedef cairo_atomic_intptr_t cairo_atomic_int_t; - cairo_private void _cairo_atomic_int_inc (cairo_atomic_int_t *x); @@ -376,7 +376,8 @@ cairo_private cairo_atomic_int_t _cairo_atomic_int_get_relaxed (cairo_atomic_int_t *x); void _cairo_atomic_int_set_relaxed (cairo_atomic_int_t *x, cairo_atomic_int_t val); -# define _cairo_atomic_ptr_get(x) (void *) _cairo_atomic_int_get((cairo_atomic_int_t *) x) +cairo_private void* +_cairo_atomic_ptr_get(void **x); #else # define _cairo_atomic_int_get(x) (*x) # define _cairo_atomic_int_get_relaxed(x) (*x) @@ -441,6 +442,7 @@ _cairo_atomic_ptr_cmpxchg_return_old_fallback(void **x, void *oldv, void *newv) #define _cairo_status_set_error(status, err) do { \ int ret__; \ assert (err < CAIRO_STATUS_LAST_STATUS); \ + assert (sizeof(*status) == sizeof(cairo_atomic_int_t)); \ /* hide compiler warnings about cairo_status_t != int (gcc treats its as \ * an unsigned integer instead, and about ignoring the return value. */ \ ret__ = _cairo_atomic_int_cmpxchg ((cairo_atomic_int_t *) status, CAIRO_STATUS_SUCCESS, err); \ diff --git a/src/cairo-atomic.c b/src/cairo-atomic.c index 2af50cd38..3c4d51972 100644 --- a/src/cairo-atomic.c +++ b/src/cairo-atomic.c @@ -42,7 +42,7 @@ COMPILE_TIME_ASSERT(sizeof(void*) == sizeof(int) || sizeof(void*) == sizeof(long long)); #else void -_cairo_atomic_int_inc (cairo_atomic_intptr_t *x) +_cairo_atomic_int_inc (cairo_atomic_int_t *x) { CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); *x += 1; @@ -50,7 +50,7 @@ _cairo_atomic_int_inc (cairo_atomic_intptr_t *x) } cairo_bool_t -_cairo_atomic_int_dec_and_test (cairo_atomic_intptr_t *x) +_cairo_atomic_int_dec_and_test (cairo_atomic_int_t *x) { cairo_bool_t ret; @@ -61,10 +61,10 @@ _cairo_atomic_int_dec_and_test (cairo_atomic_intptr_t *x) return ret; } -cairo_atomic_intptr_t -_cairo_atomic_int_cmpxchg_return_old_impl (cairo_atomic_intptr_t *x, cairo_atomic_intptr_t oldv, cairo_atomic_intptr_t newv) +cairo_atomic_int_t +_cairo_atomic_int_cmpxchg_return_old_impl (cairo_atomic_int_t *x, cairo_atomic_int_t oldv, cairo_atomic_int_t newv) { - cairo_atomic_intptr_t ret; + cairo_atomic_int_t ret; CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); ret = *x; @@ -90,10 +90,10 @@ _cairo_atomic_ptr_cmpxchg_return_old_impl (void **x, void *oldv, void *newv) } #ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER -cairo_atomic_intptr_t -_cairo_atomic_int_get (cairo_atomic_intptr_t *x) +cairo_atomic_int_t +_cairo_atomic_int_get (cairo_atomic_int_t *x) { - cairo_atomic_intptr_t ret; + cairo_atomic_int_t ret; CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); ret = *x; @@ -102,19 +102,31 @@ _cairo_atomic_int_get (cairo_atomic_intptr_t *x) return ret; } -cairo_atomic_intptr_t -_cairo_atomic_int_get_relaxed (cairo_atomic_intptr_t *x) +cairo_atomic_int_t +_cairo_atomic_int_get_relaxed (cairo_atomic_int_t *x) { return _cairo_atomic_int_get (x); } void -_cairo_atomic_int_set_relaxed (cairo_atomic_intptr_t *x, cairo_atomic_intptr_t val) +_cairo_atomic_int_set_relaxed (cairo_atomic_int_t *x, cairo_atomic_int_t val) { CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); *x = val; CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); } + +void* +_cairo_atomic_ptr_get (void **x) +{ + void *ret; + + CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); + ret = *x; + CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); + + return ret; +} #endif #endif