1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

MDEV-33161 Function pointer signature mismatch in LF_HASH

In cmake -DWITH_UBSAN=ON builds with clang but not with GCC,
-fsanitize=undefined will flag several runtime errors on
function pointer mismatch related to the lock-free hash table LF_HASH.

Let us use matching function signatures and remove function pointer
casts in order to avoid potential bugs due to undefined behaviour.

These errors could be caught at compilation time by
-Wcast-function-type-strict, which is available starting with clang-16,
but not available in any version of GCC as of now. The old GCC flag
-Wcast-function-type is enabled as part of -Wextra, but it specifically
does not catch these errors.

Reviewed by: Vladislav Vaintroub
This commit is contained in:
Marko Mäkelä
2024-06-10 12:35:33 +03:00
parent 246c0b3a35
commit a2bd936c52
12 changed files with 137 additions and 131 deletions

View File

@@ -242,8 +242,10 @@ void lf_pinbox_put_pins(LF_PINS *pins)
return;
}
static int ptr_cmp(void **a, void **b)
static int ptr_cmp(const void *pa, const void *pb)
{
const void *const*a= pa;
const void *const*b= pb;
return *a < *b ? -1 : *a == *b ? 0 : 1;
}
@@ -283,8 +285,10 @@ struct st_harvester {
callback forlf_dynarray_iterate:
scan all pins of all threads and accumulate all pins
*/
static int harvest_pins(LF_PINS *el, struct st_harvester *hv)
static int harvest_pins(void *e, void *h)
{
LF_PINS *el= e;
struct st_harvester *hv= h;
int i;
LF_PINS *el_end= el+MY_MIN(hv->npins, LF_DYNARRAY_LEVEL_LENGTH);
for (; el < el_end; el++)
@@ -310,8 +314,9 @@ static int harvest_pins(LF_PINS *el, struct st_harvester *hv)
callback forlf_dynarray_iterate:
scan all pins of all threads and see if addr is present there
*/
static int match_pins(LF_PINS *el, void *addr)
static int match_pins(void *e, void *addr)
{
LF_PINS *el= e;
int i;
LF_PINS *el_end= el+LF_DYNARRAY_LEVEL_LENGTH;
for (; el < el_end; el++)
@@ -352,13 +357,12 @@ static void lf_pinbox_real_free(LF_PINS *pins)
hv.granary= addr;
hv.npins= npins;
/* scan the dynarray and accumulate all pinned addresses */
lf_dynarray_iterate(&pinbox->pinarray,
(lf_dynarray_func)harvest_pins, &hv);
lf_dynarray_iterate(&pinbox->pinarray, harvest_pins, &hv);
npins= (int)(hv.granary-addr);
/* and sort them */
if (npins)
qsort(addr, npins, sizeof(void *), (qsort_cmp)ptr_cmp);
qsort(addr, npins, sizeof(void *), ptr_cmp);
}
}
#endif
@@ -387,8 +391,7 @@ static void lf_pinbox_real_free(LF_PINS *pins)
}
else /* no alloca - no cookie. linear search here */
{
if (lf_dynarray_iterate(&pinbox->pinarray,
(lf_dynarray_func)match_pins, cur))
if (lf_dynarray_iterate(&pinbox->pinarray, match_pins, cur))
goto found;
}
}
@@ -416,10 +419,11 @@ found:
'first' and 'last' are the ends of the linked list of nodes:
first->el->el->....->el->last. Use first==last to free only one element.
*/
static void alloc_free(uchar *first,
uchar volatile *last,
LF_ALLOCATOR *allocator)
static void alloc_free(void *f, void *l, void *alloc)
{
uchar *first= f;
uchar volatile *last= l;
LF_ALLOCATOR *allocator= alloc;
/*
we need a union here to access type-punned pointer reliably.
otherwise gcc -fstrict-aliasing will not see 'tmp' changed in the loop
@@ -448,8 +452,7 @@ static void alloc_free(uchar *first,
*/
void lf_alloc_init(LF_ALLOCATOR *allocator, uint size, uint free_ptr_offset)
{
lf_pinbox_init(&allocator->pinbox, free_ptr_offset,
(lf_pinbox_free_func *)alloc_free, allocator);
lf_pinbox_init(&allocator->pinbox, free_ptr_offset, alloc_free, allocator);
allocator->top= 0;
allocator->mallocs= 0;
allocator->element_size= size;