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
This commit is contained in:
Fujii Hironori 2023-01-10 15:12:07 +09:00
parent c76a699f6c
commit 2135fd4a49
2 changed files with 28 additions and 14 deletions

View file

@ -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); \

View file

@ -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