Cast via guintptr when adding/removing bitsflags on pointers

Round-tripping pointers via gsize is not guaranteed to work (the C standard
only requires this for (u)inptr_t) and in fact breaks on CHERI-enabled
systems such as Arm Morello where pointers are 128-bits but size_t is 64.
This means the current casts would strip the high bits of the pointer and
return a non-dereferenceable value. Fix this by casting the operand that
holds the pointer to guintptr instead of gsize.

Helps: https://gitlab.gnome.org/GNOME/glib/-/issues/2842
This commit is contained in:
Alex Richardson 2022-12-14 23:55:18 +00:00
parent c762d51134
commit ab7e584e9f
3 changed files with 6 additions and 6 deletions

View File

@ -142,13 +142,13 @@
/* datalist pointer accesses have to be carried out atomically */
#define G_DATALIST_GET_POINTER(datalist) \
((GData*) ((gsize) g_atomic_pointer_get (datalist) & ~(gsize) G_DATALIST_FLAGS_MASK_INTERNAL))
((GData*) ((guintptr) g_atomic_pointer_get (datalist) & ~(gsize) G_DATALIST_FLAGS_MASK_INTERNAL))
#define G_DATALIST_SET_POINTER(datalist, pointer) G_STMT_START { \
gpointer _oldv = g_atomic_pointer_get (datalist); \
gpointer _newv; \
do { \
_newv = (gpointer) (((gsize) _oldv & G_DATALIST_FLAGS_MASK_INTERNAL) | (gsize) pointer); \
_newv = (gpointer) (((gsize) _oldv & G_DATALIST_FLAGS_MASK_INTERNAL) | (guintptr) pointer); \
} while (!g_atomic_pointer_compare_and_exchange_full ((void**) datalist, _oldv, \
_newv, &_oldv)); \
} G_STMT_END

View File

@ -3447,7 +3447,7 @@ object_floating_flag_handler (GObject *object,
oldvalue = g_atomic_pointer_get (&object->qdata);
while (!g_atomic_pointer_compare_and_exchange_full (
(void**) &object->qdata, oldvalue,
(void *) ((gsize) oldvalue | OBJECT_FLOATING_FLAG),
(void *) ((guintptr) oldvalue | OBJECT_FLOATING_FLAG),
&oldvalue))
;
return (gsize) oldvalue & OBJECT_FLOATING_FLAG;
@ -3455,7 +3455,7 @@ object_floating_flag_handler (GObject *object,
oldvalue = g_atomic_pointer_get (&object->qdata);
while (!g_atomic_pointer_compare_and_exchange_full (
(void**) &object->qdata, oldvalue,
(void *) ((gsize) oldvalue & ~(gsize) OBJECT_FLOATING_FLAG),
(void *) ((guintptr) oldvalue & ~(gsize) OBJECT_FLOATING_FLAG),
&oldvalue))
;
return (gsize) oldvalue & OBJECT_FLOATING_FLAG;

View File

@ -257,7 +257,7 @@ g_param_spec_unref (GParamSpec *pspec)
void
g_param_spec_sink (GParamSpec *pspec)
{
gsize oldvalue;
guintptr oldvalue;
g_return_if_fail (G_IS_PARAM_SPEC (pspec));
oldvalue = g_atomic_pointer_and (&pspec->qdata, ~(gsize)PARAM_FLOATING_FLAG);
@ -277,7 +277,7 @@ g_param_spec_sink (GParamSpec *pspec)
GParamSpec*
g_param_spec_ref_sink (GParamSpec *pspec)
{
gsize oldvalue;
guintptr oldvalue;
g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
oldvalue = g_atomic_pointer_and (&pspec->qdata, ~(gsize)PARAM_FLOATING_FLAG);