After upgrading the CI to use a newer clang for the check with sanitizers, I see a couple of runtime errors:
FAIL: test-map-c++ ================== ../../gllib/gl_array_map.c:90:17: runtime error: call to function streq through pointer to incorrect function type 'bool (*)(const void *, const void *)' /home/runner/work/ci-testdir-check/ci-testdir-check/testdir-all/build/gllib/./string.h:1369: note: streq defined here SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../../gllib/gl_array_map.c:90:17 FAIL test-map-c++ (exit status: 134) FAIL: test-oset-c++ =================== ../../gllib/gl_array_oset.c:252:24: runtime error: call to function reverse_strcmp(char const*, char const*) through pointer to incorrect function type 'int (*)(const void *, const void *)' /home/runner/work/ci-testdir-check/ci-testdir-check/testdir-all/build/gltests/../../gltests/test-oset-c++.cc:29: note: reverse_strcmp(char const*, char const*) defined here SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../../gllib/gl_array_oset.c:252:24 FAIL test-oset-c++ (exit status: 134) FAIL: test-categ_Cs =================== ../../gllib/unictype/categ_test.c:29:12: runtime error: call to function uc_is_category_Cs through pointer to incorrect function type 'bool (*)(unsigned int, unsigned int)' /home/runner/work/ci-testdir-check/ci-testdir-check/testdir-all/build/gllib/../../gllib/unictype/categ_Cs.c:33: note: uc_is_category_Cs defined here SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../../gllib/unictype/categ_test.c:29:12 FAIL test-categ_Cs (exit status: 134) FAIL: test-categ_Zl =================== ../../gllib/unictype/categ_test.c:29:12: runtime error: call to function uc_is_category_Zl through pointer to incorrect function type 'bool (*)(unsigned int, unsigned int)' /home/runner/work/ci-testdir-check/ci-testdir-check/testdir-all/build/gllib/../../gllib/unictype/categ_Zl.c:33: note: uc_is_category_Zl defined here SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../../gllib/unictype/categ_test.c:29:12 FAIL test-categ_Zl (exit status: 134) FAIL: test-categ_Zp =================== ../../gllib/unictype/categ_test.c:29:12: runtime error: call to function uc_is_category_Zp through pointer to incorrect function type 'bool (*)(unsigned int, unsigned int)' /home/runner/work/ci-testdir-check/ci-testdir-check/testdir-all/build/gllib/../../gllib/unictype/categ_Zp.c:33: note: uc_is_category_Zp defined here SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../../gllib/unictype/categ_test.c:29:12 FAIL test-categ_Zp (exit status: 134) These correspond to an UBSAN category that is implemented by clang, but not yet by GCC (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112284 ). This patch series fixes the errors. 2026-08-12 Bruno Haible <[email protected]> omap-c++: Avoid clang UBSAN runtime errors. * modules/omap-c++ (configure.ac): Define _GL_HAVE_OMAP_HH. * lib/gl_omap.h (_GL_OMAP_INVOKES_FN_PTR): New macro. (gl_omap_nx_put, gl_omap_remove): Mark as _GL_OMAP_INVOKES_FN_PTR. * lib/gl_array_omap.c (gl_array_indexof, gl_array_search_atleast, gl_array_nx_getput, gl_array_remove_at, gl_array_free): Likewise. * lib/gl_anytree_omap.h (gl_tree_search, gl_tree_search_atleast, gl_tree_nx_getput, gl_tree_getremove, gl_tree_omap_free): Likewise. 2026-08-12 Bruno Haible <[email protected]> map-c++: Avoid clang UBSAN runtime errors. * modules/map-c++ (configure.ac): Define _GL_HAVE_MAP_HH. * lib/gl_map.h (_GL_MAP_INVOKES_FN_PTR): New macro. (gl_map_nx_put, gl_map_remove): Mark as _GL_MAP_INVOKES_FN_PTR. * lib/gl_array_map.c (gl_array_indexof, gl_array_remove_at, gl_array_free): Likewise. * lib/gl_hash_map.c (gl_hash_search, gl_hash_nx_getput, gl_hash_getremove, gl_hash_free): Likewise. * lib/gl_linkedhash_map.c (gl_linkedhash_search, gl_linkedhash_nx_getput, gl_linkedhash_getremove, gl_linkedhash_free): Likewise. 2026-08-12 Bruno Haible <[email protected]> oset-c++: Avoid clang UBSAN runtime errors. * modules/oset-c++ (configure.ac): Define _GL_HAVE_OSET_HH. * lib/gl_oset.h (_GL_OSET_INVOKES_FN_PTR): New macro. * lib/gl_array_oset.c (gl_array_indexof, gl_array_indexof_atleast, gl_array_search_atleast, gl_array_remove_at, gl_array_nx_add, gl_array_update, gl_array_free(: Mark as _GL_OSET_INVOKES_FN_PTR. * lib/gl_anytree_oset.h (gl_tree_search, gl_tree_search_atleast, gl_tree_search_node, gl_tree_nx_add, gl_tree_update, gl_tree_oset_free, gl_tree_iterator_atleast): Likewise. 2026-08-12 Bruno Haible <[email protected]> set-c++: Avoid clang UBSAN runtime errors. * modules/set-c++ (configure.ac): Define _GL_HAVE_SET_HH. * lib/gl_set.h (_GL_SET_INVOKES_FN_PTR): New macro. * lib/gl_array_set.c (gl_array_search, gl_array_remove_at, gl_array_remove, gl_array_free): Mark as _GL_SET_INVOKES_FN_PTR. * lib/gl_hash_set.c (gl_hash_search, gl_hash_nx_add, gl_hash_remove, gl_hash_free): Likewise. 2026-08-12 Bruno Haible <[email protected]> list-c++: Avoid clang UBSAN runtime errors. * modules/list-c++ (configure.ac): Define _GL_HAVE_LIST_HH. * lib/gl_list.h (_GL_LIST_INVOKES_FN_PTR): New macro. * lib/gl_array_list.c (gl_array_indexof_from_to, gl_array_remove_node, gl_array_remove_at, gl_array_list_free, gl_array_sortedlist_indexof_from_to, gl_array_sortedlist_search): Mark as _GL_LIST_INVOKES_FN_PTR. * lib/gl_carray_list.c (gl_carray_indexof_from_to, gl_carray_remove_at, gl_carray_list_free, gl_carray_sortedlist_nx_add): Likewise. * lib/gl_anylinked_list2.h (gl_linked_nx_create, gl_linked_node_nx_set_value, gl_linked_get_at, gl_linked_nx_set_at, gl_linked_search_from_to, gl_linked_indexof_from_to, gl_linked_nx_add_last, gl_linked_nx_add_before, gl_linked_nx_add_after, gl_linked_nx_add_at, gl_linked_remove_node, gl_linked_remove_at, gl_linked_list_free, gl_linked_sortedlist_search, gl_linked_sortedlist_search_from_to, gl_linked_sortedlist_indexof, gl_linked_sortedlist_indexof_from_to, gl_linked_sortedlist_nx_add, gl_linked_sortedlist_remove): Likewise. * lib/gl_anyavltree_list2.h (gl_tree_nx_add_first, gl_tree_nx_add_last, gl_tree_nx_add_before, gl_tree_nx_add_after): Likewise. * lib/gl_anyrbtree_list2.h (gl_tree_nx_add_first, gl_tree_nx_add_last, gl_tree_nx_add_before, gl_tree_nx_add_after): Likewise. * lib/gl_anytree_list2.h (gl_tree_node_nx_set_value, gl_tree_nx_set_at, gl_tree_search_from_to, gl_tree_indexof_from_to, gl_tree_remove_node, gl_tree_list_free, gl_tree_sortedlist_search, gl_tree_sortedlist_search_from_to, gl_tree_sortedlist_indexof, gl_tree_sortedlist_indexof_from_to, gl_tree_sortedlist_nx_add): Likewise. * lib/gl_anytreehash_list1.h (add_to_bucket, remove_from_bucket, add_nodes_to_buckets): Likewise. * lib/gl_anytreehash_list2.h (gl_tree_search_from_to, gl_tree_list_free): Likewise. 2026-08-12 Bruno Haible <[email protected]> unictype: Fix undefined behaviour. Reported by clang's UBSAN. * lib/unictype/categ_Cs.c (uc_is_category_Cs): Add a bitmask argument. * lib/unictype/categ_Zl.c (uc_is_category_Zl): Likewise. * lib/unictype/categ_Zp.c (uc_is_category_Zp): Likewise.
>From 985c2291ee52a3e8d87d965471ff02c43de1b2d1 Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Wed, 12 Aug 2026 16:22:57 +0200 Subject: [PATCH 1/6] unictype: Fix undefined behaviour. Reported by clang's UBSAN. * lib/unictype/categ_Cs.c (uc_is_category_Cs): Add a bitmask argument. * lib/unictype/categ_Zl.c (uc_is_category_Zl): Likewise. * lib/unictype/categ_Zp.c (uc_is_category_Zp): Likewise. --- ChangeLog | 8 ++++++++ lib/unictype/categ_Cs.c | 2 +- lib/unictype/categ_Zl.c | 2 +- lib/unictype/categ_Zp.c | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index b4916c518e..5ae1141bd1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2026-08-12 Bruno Haible <[email protected]> + + unictype: Fix undefined behaviour. + Reported by clang's UBSAN. + * lib/unictype/categ_Cs.c (uc_is_category_Cs): Add a bitmask argument. + * lib/unictype/categ_Zl.c (uc_is_category_Zl): Likewise. + * lib/unictype/categ_Zp.c (uc_is_category_Zp): Likewise. + 2026-08-12 Bruno Haible <[email protected]> hamt: Fix compilation error on MSVC (regression 2026-08-10). diff --git a/lib/unictype/categ_Cs.c b/lib/unictype/categ_Cs.c index 8986d7b7bd..a208865252 100644 --- a/lib/unictype/categ_Cs.c +++ b/lib/unictype/categ_Cs.c @@ -29,7 +29,7 @@ #include "unictype.h" static bool -uc_is_category_Cs (ucs4_t uc) +uc_is_category_Cs (ucs4_t uc, _GL_UNUSED uint32_t bitmask) { return (uc >= 0xd800 && uc < 0xe000); } diff --git a/lib/unictype/categ_Zl.c b/lib/unictype/categ_Zl.c index 7e38efac02..00e5c7aa64 100644 --- a/lib/unictype/categ_Zl.c +++ b/lib/unictype/categ_Zl.c @@ -29,7 +29,7 @@ #include "unictype.h" static bool -uc_is_category_Zl (ucs4_t uc) +uc_is_category_Zl (ucs4_t uc, _GL_UNUSED uint32_t bitmask) { return (uc == 0x2028); } diff --git a/lib/unictype/categ_Zp.c b/lib/unictype/categ_Zp.c index 9ad2da11ce..daba70f52b 100644 --- a/lib/unictype/categ_Zp.c +++ b/lib/unictype/categ_Zp.c @@ -29,7 +29,7 @@ #include "unictype.h" static bool -uc_is_category_Zp (ucs4_t uc) +uc_is_category_Zp (ucs4_t uc, _GL_UNUSED uint32_t bitmask) { return (uc == 0x2029); } -- 2.53.0
>From 3041132e1d1d5d59ceacea14bf8b3b1c17298f26 Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Wed, 12 Aug 2026 18:55:46 +0200 Subject: [PATCH 2/6] list-c++: Avoid clang UBSAN runtime errors. * modules/list-c++ (configure.ac): Define _GL_HAVE_LIST_HH. * lib/gl_list.h (_GL_LIST_INVOKES_FN_PTR): New macro. * lib/gl_array_list.c (gl_array_indexof_from_to, gl_array_remove_node, gl_array_remove_at, gl_array_list_free, gl_array_sortedlist_indexof_from_to, gl_array_sortedlist_search): Mark as _GL_LIST_INVOKES_FN_PTR. * lib/gl_carray_list.c (gl_carray_indexof_from_to, gl_carray_remove_at, gl_carray_list_free, gl_carray_sortedlist_nx_add): Likewise. * lib/gl_anylinked_list2.h (gl_linked_nx_create, gl_linked_node_nx_set_value, gl_linked_get_at, gl_linked_nx_set_at, gl_linked_search_from_to, gl_linked_indexof_from_to, gl_linked_nx_add_last, gl_linked_nx_add_before, gl_linked_nx_add_after, gl_linked_nx_add_at, gl_linked_remove_node, gl_linked_remove_at, gl_linked_list_free, gl_linked_sortedlist_search, gl_linked_sortedlist_search_from_to, gl_linked_sortedlist_indexof, gl_linked_sortedlist_indexof_from_to, gl_linked_sortedlist_nx_add, gl_linked_sortedlist_remove): Likewise. * lib/gl_anyavltree_list2.h (gl_tree_nx_add_first, gl_tree_nx_add_last, gl_tree_nx_add_before, gl_tree_nx_add_after): Likewise. * lib/gl_anyrbtree_list2.h (gl_tree_nx_add_first, gl_tree_nx_add_last, gl_tree_nx_add_before, gl_tree_nx_add_after): Likewise. * lib/gl_anytree_list2.h (gl_tree_node_nx_set_value, gl_tree_nx_set_at, gl_tree_search_from_to, gl_tree_indexof_from_to, gl_tree_remove_node, gl_tree_list_free, gl_tree_sortedlist_search, gl_tree_sortedlist_search_from_to, gl_tree_sortedlist_indexof, gl_tree_sortedlist_indexof_from_to, gl_tree_sortedlist_nx_add): Likewise. * lib/gl_anytreehash_list1.h (add_to_bucket, remove_from_bucket, add_nodes_to_buckets): Likewise. * lib/gl_anytreehash_list2.h (gl_tree_search_from_to, gl_tree_list_free): Likewise. --- ChangeLog | 35 +++++++++++++++++++++++++++++++++++ lib/gl_anyavltree_list2.h | 4 ++++ lib/gl_anylinked_list2.h | 19 +++++++++++++++++++ lib/gl_anyrbtree_list2.h | 4 ++++ lib/gl_anytree_list2.h | 11 +++++++++++ lib/gl_anytreehash_list1.h | 3 +++ lib/gl_anytreehash_list2.h | 2 ++ lib/gl_array_list.c | 6 ++++++ lib/gl_carray_list.c | 15 ++++++++++----- lib/gl_list.h | 8 ++++++++ modules/list-c++ | 2 ++ 11 files changed, 104 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5ae1141bd1..226120dc15 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,38 @@ +2026-08-12 Bruno Haible <[email protected]> + + list-c++: Avoid clang UBSAN runtime errors. + * modules/list-c++ (configure.ac): Define _GL_HAVE_LIST_HH. + * lib/gl_list.h (_GL_LIST_INVOKES_FN_PTR): New macro. + * lib/gl_array_list.c (gl_array_indexof_from_to, gl_array_remove_node, + gl_array_remove_at, gl_array_list_free, + gl_array_sortedlist_indexof_from_to, gl_array_sortedlist_search): Mark + as _GL_LIST_INVOKES_FN_PTR. + * lib/gl_carray_list.c (gl_carray_indexof_from_to, gl_carray_remove_at, + gl_carray_list_free, gl_carray_sortedlist_nx_add): Likewise. + * lib/gl_anylinked_list2.h (gl_linked_nx_create, + gl_linked_node_nx_set_value, gl_linked_get_at, gl_linked_nx_set_at, + gl_linked_search_from_to, gl_linked_indexof_from_to, + gl_linked_nx_add_last, gl_linked_nx_add_before, gl_linked_nx_add_after, + gl_linked_nx_add_at, gl_linked_remove_node, gl_linked_remove_at, + gl_linked_list_free, gl_linked_sortedlist_search, + gl_linked_sortedlist_search_from_to, gl_linked_sortedlist_indexof, + gl_linked_sortedlist_indexof_from_to, gl_linked_sortedlist_nx_add, + gl_linked_sortedlist_remove): Likewise. + * lib/gl_anyavltree_list2.h (gl_tree_nx_add_first, gl_tree_nx_add_last, + gl_tree_nx_add_before, gl_tree_nx_add_after): Likewise. + * lib/gl_anyrbtree_list2.h (gl_tree_nx_add_first, gl_tree_nx_add_last, + gl_tree_nx_add_before, gl_tree_nx_add_after): Likewise. + * lib/gl_anytree_list2.h (gl_tree_node_nx_set_value, gl_tree_nx_set_at, + gl_tree_search_from_to, gl_tree_indexof_from_to, gl_tree_remove_node, + gl_tree_list_free, gl_tree_sortedlist_search, + gl_tree_sortedlist_search_from_to, gl_tree_sortedlist_indexof, + gl_tree_sortedlist_indexof_from_to, gl_tree_sortedlist_nx_add): + Likewise. + * lib/gl_anytreehash_list1.h (add_to_bucket, remove_from_bucket, + add_nodes_to_buckets): Likewise. + * lib/gl_anytreehash_list2.h (gl_tree_search_from_to, + gl_tree_list_free): Likewise. + 2026-08-12 Bruno Haible <[email protected]> unictype: Fix undefined behaviour. diff --git a/lib/gl_anyavltree_list2.h b/lib/gl_anyavltree_list2.h index 08e241b398..a89c4dcec7 100644 --- a/lib/gl_anyavltree_list2.h +++ b/lib/gl_anyavltree_list2.h @@ -517,6 +517,7 @@ gl_tree_remove_node_from_tree (gl_list_t list, gl_list_node_t node) static gl_list_node_t gl_tree_nx_add_first (gl_list_t list, const void *elt) + _GL_LIST_INVOKES_FN_PTR { /* Create new node. */ gl_list_node_t new_node = @@ -580,6 +581,7 @@ gl_tree_nx_add_first (gl_list_t list, const void *elt) static gl_list_node_t gl_tree_nx_add_last (gl_list_t list, const void *elt) + _GL_LIST_INVOKES_FN_PTR { /* Create new node. */ gl_list_node_t new_node = @@ -643,6 +645,7 @@ gl_tree_nx_add_last (gl_list_t list, const void *elt) static gl_list_node_t gl_tree_nx_add_before (gl_list_t list, gl_list_node_t node, const void *elt) + _GL_LIST_INVOKES_FN_PTR { /* Create new node. */ gl_list_node_t new_node; @@ -708,6 +711,7 @@ gl_tree_nx_add_before (gl_list_t list, gl_list_node_t node, const void *elt) static gl_list_node_t gl_tree_nx_add_after (gl_list_t list, gl_list_node_t node, const void *elt) + _GL_LIST_INVOKES_FN_PTR { /* Create new node. */ gl_list_node_t new_node; diff --git a/lib/gl_anylinked_list2.h b/lib/gl_anylinked_list2.h index 9fa25cf75a..1fcbedd7fd 100644 --- a/lib/gl_anylinked_list2.h +++ b/lib/gl_anylinked_list2.h @@ -81,6 +81,7 @@ gl_linked_nx_create (gl_list_implementation_t implementation, gl_listelement_dispose_fn dispose_fn, bool allow_duplicates, size_t count, const void **contents) + _GL_LIST_INVOKES_FN_PTR { struct gl_list_impl *list = (struct gl_list_impl *) malloc (sizeof (struct gl_list_impl)); @@ -175,6 +176,7 @@ static int gl_linked_node_nx_set_value (_GL_ATTRIBUTE_MAYBE_UNUSED gl_list_t list, gl_list_node_t node, const void *elt) + _GL_LIST_INVOKES_FN_PTR { #if WITH_HASHTABLE if (elt != node->value) @@ -270,6 +272,7 @@ gl_linked_get_at (gl_list_t list, size_t position) static gl_list_node_t gl_linked_nx_set_at (gl_list_t list, size_t position, const void *elt) + _GL_LIST_INVOKES_FN_PTR { size_t count = list->count; @@ -330,6 +333,7 @@ gl_linked_nx_set_at (gl_list_t list, size_t position, const void *elt) static gl_list_node_t _GL_ATTRIBUTE_PURE gl_linked_search_from_to (gl_list_t list, size_t start_index, size_t end_index, const void *elt) + _GL_LIST_INVOKES_FN_PTR { size_t count = list->count; @@ -481,6 +485,7 @@ gl_linked_search_from_to (gl_list_t list, size_t start_index, size_t end_index, static size_t _GL_ATTRIBUTE_PURE gl_linked_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index, const void *elt) + _GL_LIST_INVOKES_FN_PTR { size_t count = list->count; @@ -604,6 +609,7 @@ gl_linked_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index, static gl_list_node_t gl_linked_nx_add_first (gl_list_t list, const void *elt) + _GL_LIST_INVOKES_FN_PTR { gl_list_node_t node = (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); @@ -642,6 +648,7 @@ gl_linked_nx_add_first (gl_list_t list, const void *elt) static gl_list_node_t gl_linked_nx_add_last (gl_list_t list, const void *elt) + _GL_LIST_INVOKES_FN_PTR { gl_list_node_t node = (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); @@ -680,6 +687,7 @@ gl_linked_nx_add_last (gl_list_t list, const void *elt) static gl_list_node_t gl_linked_nx_add_before (gl_list_t list, gl_list_node_t node, const void *elt) + _GL_LIST_INVOKES_FN_PTR { gl_list_node_t new_node = (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); @@ -718,6 +726,7 @@ gl_linked_nx_add_before (gl_list_t list, gl_list_node_t node, const void *elt) static gl_list_node_t gl_linked_nx_add_after (gl_list_t list, gl_list_node_t node, const void *elt) + _GL_LIST_INVOKES_FN_PTR { gl_list_node_t new_node = (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); @@ -756,6 +765,7 @@ gl_linked_nx_add_after (gl_list_t list, gl_list_node_t node, const void *elt) static gl_list_node_t gl_linked_nx_add_at (gl_list_t list, size_t position, const void *elt) + _GL_LIST_INVOKES_FN_PTR { size_t count = list->count; gl_list_node_t new_node; @@ -819,6 +829,7 @@ gl_linked_nx_add_at (gl_list_t list, size_t position, const void *elt) static bool gl_linked_remove_node (gl_list_t list, gl_list_node_t node) + _GL_LIST_INVOKES_FN_PTR { #if WITH_HASHTABLE /* Remove node from the hash table. */ @@ -841,6 +852,7 @@ gl_linked_remove_node (gl_list_t list, gl_list_node_t node) static bool gl_linked_remove_at (gl_list_t list, size_t position) + _GL_LIST_INVOKES_FN_PTR { size_t count = list->count; @@ -897,6 +909,7 @@ gl_linked_remove (gl_list_t list, const void *elt) static void gl_linked_list_free (gl_list_t list) + _GL_LIST_INVOKES_FN_PTR { gl_listelement_dispose_fn dispose = list->base.dispose_fn; @@ -1025,6 +1038,7 @@ gl_linked_iterator_free (gl_list_iterator_t *_GL_UNNAMED (iterator)) static gl_list_node_t _GL_ATTRIBUTE_PURE gl_linked_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) + _GL_LIST_INVOKES_FN_PTR { for (gl_list_node_t node = list->root.next; node != &list->root; node = node->next) { @@ -1043,6 +1057,7 @@ gl_linked_sortedlist_search_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t low, size_t high, const void *elt) + _GL_LIST_INVOKES_FN_PTR { size_t count = list->count; @@ -1089,6 +1104,7 @@ gl_linked_sortedlist_search_from_to (gl_list_t list, static size_t _GL_ATTRIBUTE_PURE gl_linked_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) + _GL_LIST_INVOKES_FN_PTR { gl_list_node_t node; size_t index; @@ -1112,6 +1128,7 @@ gl_linked_sortedlist_indexof_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t low, size_t high, const void *elt) + _GL_LIST_INVOKES_FN_PTR { size_t count = list->count; @@ -1160,6 +1177,7 @@ gl_linked_sortedlist_indexof_from_to (gl_list_t list, static gl_list_node_t gl_linked_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) + _GL_LIST_INVOKES_FN_PTR { for (gl_list_node_t node = list->root.next; node != &list->root; node = node->next) if (compar (node->value, elt) >= 0) @@ -1170,6 +1188,7 @@ gl_linked_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar, static bool gl_linked_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) + _GL_LIST_INVOKES_FN_PTR { for (gl_list_node_t node = list->root.next; node != &list->root; node = node->next) { diff --git a/lib/gl_anyrbtree_list2.h b/lib/gl_anyrbtree_list2.h index 7d0a003d9c..b23eb2e64e 100644 --- a/lib/gl_anyrbtree_list2.h +++ b/lib/gl_anyrbtree_list2.h @@ -763,6 +763,7 @@ gl_tree_remove_node_from_tree (gl_list_t list, gl_list_node_t node) static gl_list_node_t gl_tree_nx_add_first (gl_list_t list, const void *elt) + _GL_LIST_INVOKES_FN_PTR { /* Create new node. */ gl_list_node_t new_node = @@ -824,6 +825,7 @@ gl_tree_nx_add_first (gl_list_t list, const void *elt) static gl_list_node_t gl_tree_nx_add_last (gl_list_t list, const void *elt) + _GL_LIST_INVOKES_FN_PTR { /* Create new node. */ gl_list_node_t new_node = @@ -885,6 +887,7 @@ gl_tree_nx_add_last (gl_list_t list, const void *elt) static gl_list_node_t gl_tree_nx_add_before (gl_list_t list, gl_list_node_t node, const void *elt) + _GL_LIST_INVOKES_FN_PTR { /* Create new node. */ gl_list_node_t new_node = @@ -940,6 +943,7 @@ gl_tree_nx_add_before (gl_list_t list, gl_list_node_t node, const void *elt) static gl_list_node_t gl_tree_nx_add_after (gl_list_t list, gl_list_node_t node, const void *elt) + _GL_LIST_INVOKES_FN_PTR { /* Create new node. */ gl_list_node_t new_node = diff --git a/lib/gl_anytree_list2.h b/lib/gl_anytree_list2.h index edc5ce2b10..408543566b 100644 --- a/lib/gl_anytree_list2.h +++ b/lib/gl_anytree_list2.h @@ -68,6 +68,7 @@ gl_tree_node_value (gl_list_t _GL_UNNAMED (list), gl_list_node_t node) static int gl_tree_node_nx_set_value (_GL_ATTRIBUTE_MAYBE_UNUSED gl_list_t list, gl_list_node_t node, const void *elt) + _GL_LIST_INVOKES_FN_PTR { #if WITH_HASHTABLE if (elt != node->value) @@ -203,6 +204,7 @@ gl_tree_get_at (gl_list_t list, size_t position) static gl_list_node_t gl_tree_nx_set_at (gl_list_t list, size_t position, const void *elt) + _GL_LIST_INVOKES_FN_PTR { gl_list_node_t node = list->root; @@ -247,6 +249,7 @@ gl_tree_nx_set_at (gl_list_t list, size_t position, const void *elt) static gl_list_node_t _GL_ATTRIBUTE_PURE gl_tree_search_from_to (gl_list_t list, size_t start_index, size_t end_index, const void *elt) + _GL_LIST_INVOKES_FN_PTR { if (!(start_index <= end_index && end_index <= (list->root != NULL ? list->root->branch_size : 0))) @@ -358,6 +361,7 @@ gl_tree_search_from_to (gl_list_t list, size_t start_index, size_t end_index, static size_t _GL_ATTRIBUTE_PURE gl_tree_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index, const void *elt) + _GL_LIST_INVOKES_FN_PTR { if (!(start_index <= end_index && end_index <= (list->root != NULL ? list->root->branch_size : 0))) @@ -484,6 +488,7 @@ gl_tree_nx_add_at (gl_list_t list, size_t position, const void *elt) static bool gl_tree_remove_node (gl_list_t list, gl_list_node_t node) + _GL_LIST_INVOKES_FN_PTR { #if WITH_HASHTABLE /* Remove node from the hash table. @@ -530,6 +535,7 @@ gl_tree_remove (gl_list_t list, const void *elt) static void gl_tree_list_free (gl_list_t list) + _GL_LIST_INVOKES_FN_PTR { /* Iterate across all elements in post-order. */ gl_list_node_t node = list->root; @@ -665,6 +671,7 @@ gl_tree_iterator_free (gl_list_iterator_t *_GL_UNNAMED (iterator)) static gl_list_node_t _GL_ATTRIBUTE_PURE gl_tree_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) + _GL_LIST_INVOKES_FN_PTR { for (gl_list_node_t node = list->root; node != NULL; ) { @@ -706,6 +713,7 @@ gl_tree_sortedlist_search_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t low, size_t high, const void *elt) + _GL_LIST_INVOKES_FN_PTR { if (!(low <= high && high <= (list->root != NULL ? list->root->branch_size : 0))) @@ -784,6 +792,7 @@ gl_tree_sortedlist_search_from_to (gl_list_t list, static size_t _GL_ATTRIBUTE_PURE gl_tree_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) + _GL_LIST_INVOKES_FN_PTR { gl_list_node_t node; size_t position; @@ -841,6 +850,7 @@ gl_tree_sortedlist_indexof_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t low, size_t high, const void *elt) + _GL_LIST_INVOKES_FN_PTR { if (!(low <= high && high <= (list->root != NULL ? list->root->branch_size : 0))) @@ -925,6 +935,7 @@ gl_tree_sortedlist_indexof_from_to (gl_list_t list, static gl_list_node_t gl_tree_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) + _GL_LIST_INVOKES_FN_PTR { gl_list_node_t node = list->root; diff --git a/lib/gl_anytreehash_list1.h b/lib/gl_anytreehash_list1.h index 665ecead66..9d0f4185d4 100644 --- a/lib/gl_anytreehash_list1.h +++ b/lib/gl_anytreehash_list1.h @@ -98,6 +98,7 @@ gl_oset_first (gl_oset_t set) Return 0 upon success, -1 upon out-of-memory. */ static int add_to_bucket (gl_list_t list, gl_list_node_t new_node) + _GL_LIST_INVOKES_FN_PTR { size_t bucket = new_node->h.hashcode % list->table_size; @@ -184,6 +185,7 @@ add_to_bucket (gl_list_t list, gl_list_node_t new_node) If duplicates are forbidden, this function is O(1) on average. */ static void remove_from_bucket (gl_list_t list, gl_list_node_t old_node) + _GL_LIST_INVOKES_FN_PTR { size_t bucket = old_node->h.hashcode % list->table_size; @@ -257,6 +259,7 @@ remove_from_bucket (gl_list_t list, gl_list_node_t old_node) Returns 0 upon success, -1 upon out-of-memory. */ static int add_nodes_to_buckets (gl_list_t list) + _GL_LIST_INVOKES_FN_PTR { /* Iterate across all nodes. */ gl_list_node_t node = list->root; diff --git a/lib/gl_anytreehash_list2.h b/lib/gl_anytreehash_list2.h index 3f53f8bb01..9cb36a2674 100644 --- a/lib/gl_anytreehash_list2.h +++ b/lib/gl_anytreehash_list2.h @@ -20,6 +20,7 @@ static gl_list_node_t gl_tree_search_from_to (gl_list_t list, size_t start_index, size_t end_index, const void *elt) + _GL_LIST_INVOKES_FN_PTR { if (!(start_index <= end_index && end_index <= (list->root != NULL ? list->root->branch_size : 0))) @@ -141,6 +142,7 @@ gl_tree_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index, static void gl_tree_list_free (gl_list_t list) + _GL_LIST_INVOKES_FN_PTR { if (list->base.allow_duplicates) { diff --git a/lib/gl_array_list.c b/lib/gl_array_list.c index 217b2d24ef..aeb2ad71bc 100644 --- a/lib/gl_array_list.c +++ b/lib/gl_array_list.c @@ -211,6 +211,7 @@ gl_array_nx_set_at (gl_list_t list, size_t position, const void *elt) static size_t _GL_ATTRIBUTE_PURE gl_array_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index, const void *elt) + _GL_LIST_INVOKES_FN_PTR { size_t count = list->count; @@ -367,6 +368,7 @@ gl_array_nx_add_at (gl_list_t list, size_t position, const void *elt) static bool gl_array_remove_node (gl_list_t list, gl_list_node_t node) + _GL_LIST_INVOKES_FN_PTR { size_t count = list->count; uintptr_t index = NODE_TO_INDEX (node); @@ -386,6 +388,7 @@ gl_array_remove_node (gl_list_t list, gl_list_node_t node) static bool gl_array_remove_at (gl_list_t list, size_t position) + _GL_LIST_INVOKES_FN_PTR { size_t count = list->count; @@ -413,6 +416,7 @@ gl_array_remove (gl_list_t list, const void *elt) static void gl_array_list_free (gl_list_t list) + _GL_LIST_INVOKES_FN_PTR { if (list->elements != NULL) { @@ -516,6 +520,7 @@ gl_array_sortedlist_indexof_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t low, size_t high, const void *elt) + _GL_LIST_INVOKES_FN_PTR { if (!(low <= high && high <= list->count)) /* Invalid arguments. */ @@ -601,6 +606,7 @@ gl_array_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar, static gl_list_node_t gl_array_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) + _GL_LIST_INVOKES_FN_PTR { size_t count = list->count; size_t low = 0; diff --git a/lib/gl_carray_list.c b/lib/gl_carray_list.c index 0d43fcae16..0a7086d45e 100644 --- a/lib/gl_carray_list.c +++ b/lib/gl_carray_list.c @@ -78,11 +78,11 @@ gl_carray_nx_create_empty (gl_list_implementation_t implementation, static gl_list_t gl_carray_nx_create (gl_list_implementation_t implementation, - gl_listelement_equals_fn equals_fn, - gl_listelement_hashcode_fn hashcode_fn, - gl_listelement_dispose_fn dispose_fn, - bool allow_duplicates, - size_t count, const void **contents) + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates, + size_t count, const void **contents) { struct gl_list_impl *list = (struct gl_list_impl *) malloc (sizeof (struct gl_list_impl)); @@ -230,6 +230,7 @@ gl_carray_nx_set_at (gl_list_t list, size_t position, const void *elt) static size_t _GL_ATTRIBUTE_PURE gl_carray_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index, const void *elt) + _GL_LIST_INVOKES_FN_PTR { size_t count = list->count; @@ -468,6 +469,7 @@ gl_carray_nx_add_after (gl_list_t list, gl_list_node_t node, const void *elt) static bool gl_carray_remove_at (gl_list_t list, size_t position) + _GL_LIST_INVOKES_FN_PTR { size_t count = list->count; @@ -568,6 +570,7 @@ gl_carray_remove (gl_list_t list, const void *elt) static void gl_carray_list_free (gl_list_t list) + _GL_LIST_INVOKES_FN_PTR { if (list->elements != NULL) { @@ -689,6 +692,7 @@ gl_carray_sortedlist_indexof_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t low, size_t high, const void *elt) + _GL_LIST_INVOKES_FN_PTR { if (!(low <= high && high <= list->count)) /* Invalid arguments. */ @@ -784,6 +788,7 @@ gl_carray_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar, static gl_list_node_t gl_carray_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) + _GL_LIST_INVOKES_FN_PTR { size_t count = list->count; size_t low = 0; diff --git a/lib/gl_list.h b/lib/gl_list.h index f62a7163fb..2bdd10c66b 100644 --- a/lib/gl_list.h +++ b/lib/gl_list.h @@ -917,6 +917,14 @@ gl_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar, const voi ->sortedlist_remove (list, compar, elt); } +/* Avoid that the reinterpret_cast<>s in gl_list.hh cause runtime errors + "call to function ... through pointer to incorrect function type". */ +#if _GL_HAVE_LIST_HH && defined __clang__ && __clang_major__ >= 4 +# define _GL_LIST_INVOKES_FN_PTR __attribute__ ((no_sanitize ("function"))) +#else +# define _GL_LIST_INVOKES_FN_PTR +#endif + #ifdef __cplusplus } #endif diff --git a/modules/list-c++ b/modules/list-c++ index c044b85fa9..9ea45ed4a9 100644 --- a/modules/list-c++ +++ b/modules/list-c++ @@ -9,6 +9,8 @@ xlist xsublist configure.ac: +AC_DEFINE([_GL_HAVE_LIST_HH], [1], + [Define if the gnulib module list-c++ is present.]) Makefile.am: -- 2.53.0
>From 97a3e07028cc9a5541818e992d43355a7aa76edd Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Wed, 12 Aug 2026 18:59:53 +0200 Subject: [PATCH 3/6] set-c++: Avoid clang UBSAN runtime errors. * modules/set-c++ (configure.ac): Define _GL_HAVE_SET_HH. * lib/gl_set.h (_GL_SET_INVOKES_FN_PTR): New macro. * lib/gl_array_set.c (gl_array_search, gl_array_remove_at, gl_array_remove, gl_array_free): Mark as _GL_SET_INVOKES_FN_PTR. * lib/gl_hash_set.c (gl_hash_search, gl_hash_nx_add, gl_hash_remove, gl_hash_free): Likewise. --- ChangeLog | 10 ++++++++++ lib/gl_array_set.c | 4 ++++ lib/gl_hash_set.c | 4 ++++ lib/gl_set.h | 8 ++++++++ modules/set-c++ | 2 ++ 5 files changed, 28 insertions(+) diff --git a/ChangeLog b/ChangeLog index 226120dc15..d68b783651 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2026-08-12 Bruno Haible <[email protected]> + + set-c++: Avoid clang UBSAN runtime errors. + * modules/set-c++ (configure.ac): Define _GL_HAVE_SET_HH. + * lib/gl_set.h (_GL_SET_INVOKES_FN_PTR): New macro. + * lib/gl_array_set.c (gl_array_search, gl_array_remove_at, + gl_array_remove, gl_array_free): Mark as _GL_SET_INVOKES_FN_PTR. + * lib/gl_hash_set.c (gl_hash_search, gl_hash_nx_add, gl_hash_remove, + gl_hash_free): Likewise. + 2026-08-12 Bruno Haible <[email protected]> list-c++: Avoid clang UBSAN runtime errors. diff --git a/lib/gl_array_set.c b/lib/gl_array_set.c index 0348627fb7..c0f3e22fa5 100644 --- a/lib/gl_array_set.c +++ b/lib/gl_array_set.c @@ -70,6 +70,7 @@ gl_array_size (gl_set_t set) static bool gl_array_search (gl_set_t set, const void *elt) + _GL_SET_INVOKES_FN_PTR { size_t count = set->count; @@ -135,6 +136,7 @@ gl_array_nx_add (gl_set_t set, const void *elt) 0 <= position < gl_set_size (set). */ static void gl_array_remove_at (gl_set_t set, size_t position) + _GL_SET_INVOKES_FN_PTR { size_t count = set->count; const void **elements = set->elements; @@ -148,6 +150,7 @@ gl_array_remove_at (gl_set_t set, size_t position) static bool gl_array_remove (gl_set_t set, const void *elt) + _GL_SET_INVOKES_FN_PTR { size_t count = set->count; @@ -180,6 +183,7 @@ gl_array_remove (gl_set_t set, const void *elt) static void gl_array_free (gl_set_t set) + _GL_SET_INVOKES_FN_PTR { if (set->elements != NULL) { diff --git a/lib/gl_hash_set.c b/lib/gl_hash_set.c index 5d56b298e1..1c39b26486 100644 --- a/lib/gl_hash_set.c +++ b/lib/gl_hash_set.c @@ -94,6 +94,7 @@ gl_hash_size (gl_set_t set) static bool _GL_ATTRIBUTE_PURE gl_hash_search (gl_set_t set, const void *elt) + _GL_SET_INVOKES_FN_PTR { size_t hashcode = (set->hashcode_fn != NULL @@ -116,6 +117,7 @@ gl_hash_search (gl_set_t set, const void *elt) static int gl_hash_nx_add (gl_set_t set, const void *elt) + _GL_SET_INVOKES_FN_PTR { size_t hashcode = (set->hashcode_fn != NULL @@ -158,6 +160,7 @@ gl_hash_nx_add (gl_set_t set, const void *elt) static bool gl_hash_remove (gl_set_t set, const void *elt) + _GL_SET_INVOKES_FN_PTR { size_t hashcode = (set->hashcode_fn != NULL @@ -195,6 +198,7 @@ gl_hash_remove (gl_set_t set, const void *elt) static void gl_hash_free (gl_set_t set) + _GL_SET_INVOKES_FN_PTR { if (set->count > 0) { diff --git a/lib/gl_set.h b/lib/gl_set.h index da11244fe3..e654f22d18 100644 --- a/lib/gl_set.h +++ b/lib/gl_set.h @@ -274,6 +274,14 @@ gl_set_iterator_free (gl_set_iterator_t *iterator) iterator->vtable->iterator_free (iterator); } +/* Avoid that the reinterpret_cast<>s in gl_set.hh cause runtime errors + "call to function ... through pointer to incorrect function type". */ +#if _GL_HAVE_SET_HH && defined __clang__ && __clang_major__ >= 4 +# define _GL_SET_INVOKES_FN_PTR __attribute__ ((no_sanitize ("function"))) +#else +# define _GL_SET_INVOKES_FN_PTR +#endif + #ifdef __cplusplus } #endif diff --git a/modules/set-c++ b/modules/set-c++ index df5b2f3c09..c47e5a9a0d 100644 --- a/modules/set-c++ +++ b/modules/set-c++ @@ -8,6 +8,8 @@ Depends-on: xset configure.ac: +AC_DEFINE([_GL_HAVE_SET_HH], [1], + [Define if the gnulib module set-c++ is present.]) Makefile.am: -- 2.53.0
>From d6398d893d19c24e4120793368b8f6f8592e235b Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Wed, 12 Aug 2026 19:04:24 +0200 Subject: [PATCH 4/6] oset-c++: Avoid clang UBSAN runtime errors. * modules/oset-c++ (configure.ac): Define _GL_HAVE_OSET_HH. * lib/gl_oset.h (_GL_OSET_INVOKES_FN_PTR): New macro. * lib/gl_array_oset.c (gl_array_indexof, gl_array_indexof_atleast, gl_array_search_atleast, gl_array_remove_at, gl_array_nx_add, gl_array_update, gl_array_free(: Mark as _GL_OSET_INVOKES_FN_PTR. * lib/gl_anytree_oset.h (gl_tree_search, gl_tree_search_atleast, gl_tree_search_node, gl_tree_nx_add, gl_tree_update, gl_tree_oset_free, gl_tree_iterator_atleast): Likewise. --- ChangeLog | 12 ++++++++++++ lib/gl_anytree_oset.h | 7 +++++++ lib/gl_array_oset.c | 7 +++++++ lib/gl_oset.h | 8 ++++++++ modules/oset-c++ | 2 ++ 5 files changed, 36 insertions(+) diff --git a/ChangeLog b/ChangeLog index d68b783651..f511eb6aa1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2026-08-12 Bruno Haible <[email protected]> + + oset-c++: Avoid clang UBSAN runtime errors. + * modules/oset-c++ (configure.ac): Define _GL_HAVE_OSET_HH. + * lib/gl_oset.h (_GL_OSET_INVOKES_FN_PTR): New macro. + * lib/gl_array_oset.c (gl_array_indexof, gl_array_indexof_atleast, + gl_array_search_atleast, gl_array_remove_at, gl_array_nx_add, + gl_array_update, gl_array_free(: Mark as _GL_OSET_INVOKES_FN_PTR. + * lib/gl_anytree_oset.h (gl_tree_search, gl_tree_search_atleast, + gl_tree_search_node, gl_tree_nx_add, gl_tree_update, gl_tree_oset_free, + gl_tree_iterator_atleast): Likewise. + 2026-08-12 Bruno Haible <[email protected]> set-c++: Avoid clang UBSAN runtime errors. diff --git a/lib/gl_anytree_oset.h b/lib/gl_anytree_oset.h index 99e42652bd..f9fc21bd10 100644 --- a/lib/gl_anytree_oset.h +++ b/lib/gl_anytree_oset.h @@ -93,6 +93,7 @@ gl_tree_prev_node (gl_oset_node_t node) static bool gl_tree_search (gl_oset_t set, const void *elt) + _GL_OSET_INVOKES_FN_PTR { gl_setelement_compar_fn compar = set->base.compar_fn; @@ -119,6 +120,7 @@ gl_tree_search_atleast (gl_oset_t set, gl_setelement_threshold_fn threshold_fn, const void *threshold, const void **eltp) + _GL_OSET_INVOKES_FN_PTR { for (gl_oset_node_t node = set->root; node != NULL; ) { @@ -149,6 +151,7 @@ gl_tree_search_atleast (gl_oset_t set, static gl_oset_node_t gl_tree_search_node (gl_oset_t set, const void *elt) + _GL_OSET_INVOKES_FN_PTR { gl_setelement_compar_fn compar = set->base.compar_fn; @@ -172,6 +175,7 @@ gl_tree_search_node (gl_oset_t set, const void *elt) static int gl_tree_nx_add (gl_oset_t set, const void *elt) + _GL_OSET_INVOKES_FN_PTR { gl_oset_node_t node = set->root; @@ -231,6 +235,7 @@ static int gl_tree_update (gl_oset_t set, const void *elt, void (*action) (const void * /*elt*/, void * /*action_data*/), void *action_data) + _GL_OSET_INVOKES_FN_PTR { /* Like gl_tree_remove, action (...), gl_tree_nx_add, except that we don't actually remove ELT. */ @@ -301,6 +306,7 @@ gl_tree_update (gl_oset_t set, const void *elt, static void gl_tree_oset_free (gl_oset_t set) + _GL_OSET_INVOKES_FN_PTR { /* Iterate across all elements in post-order. */ gl_oset_node_t node = set->root; @@ -374,6 +380,7 @@ static gl_oset_iterator_t gl_tree_iterator_atleast (gl_oset_t set, gl_setelement_threshold_fn threshold_fn, const void *threshold) + _GL_OSET_INVOKES_FN_PTR { gl_oset_iterator_t result; diff --git a/lib/gl_array_oset.c b/lib/gl_array_oset.c index e11d53ff8c..373b953af5 100644 --- a/lib/gl_array_oset.c +++ b/lib/gl_array_oset.c @@ -68,6 +68,7 @@ gl_array_size (gl_oset_t set) static size_t _GL_ATTRIBUTE_PURE gl_array_indexof (gl_oset_t set, const void *elt) + _GL_OSET_INVOKES_FN_PTR { size_t count = set->count; @@ -117,6 +118,7 @@ static size_t _GL_ATTRIBUTE_PURE gl_array_indexof_atleast (gl_oset_t set, gl_setelement_threshold_fn threshold_fn, const void *threshold) + _GL_OSET_INVOKES_FN_PTR { size_t count = set->count; @@ -166,6 +168,7 @@ gl_array_search_atleast (gl_oset_t set, gl_setelement_threshold_fn threshold_fn, const void *threshold, const void **eltp) + _GL_OSET_INVOKES_FN_PTR { size_t index = gl_array_indexof_atleast (set, threshold_fn, threshold); @@ -220,6 +223,7 @@ gl_array_nx_add_at (gl_oset_t set, size_t position, const void *elt) 0 <= position < gl_oset_size (set). */ static void gl_array_remove_at (gl_oset_t set, size_t position) + _GL_OSET_INVOKES_FN_PTR { size_t count = set->count; const void **elements = set->elements; @@ -232,6 +236,7 @@ gl_array_remove_at (gl_oset_t set, size_t position) static int gl_array_nx_add (gl_oset_t set, const void *elt) + _GL_OSET_INVOKES_FN_PTR { size_t count = set->count; size_t low = 0; @@ -282,6 +287,7 @@ static int gl_array_update (gl_oset_t set, const void *elt, void (*action) (const void * /*elt*/, void * /*action_data*/), void *action_data) + _GL_OSET_INVOKES_FN_PTR { /* Like gl_array_remove, action (...), gl_array_nx_add, except that we don't actually remove ELT. */ @@ -388,6 +394,7 @@ gl_array_update (gl_oset_t set, const void *elt, static void gl_array_free (gl_oset_t set) + _GL_OSET_INVOKES_FN_PTR { if (set->elements != NULL) { diff --git a/lib/gl_oset.h b/lib/gl_oset.h index c36bb7d4ac..559ab26f65 100644 --- a/lib/gl_oset.h +++ b/lib/gl_oset.h @@ -335,6 +335,14 @@ gl_oset_iterator_free (gl_oset_iterator_t *iterator) iterator->vtable->iterator_free (iterator); } +/* Avoid that the reinterpret_cast<>s in gl_oset.hh cause runtime errors + "call to function ... through pointer to incorrect function type". */ +#if _GL_HAVE_OSET_HH && defined __clang__ && __clang_major__ >= 4 +# define _GL_OSET_INVOKES_FN_PTR __attribute__ ((no_sanitize ("function"))) +#else +# define _GL_OSET_INVOKES_FN_PTR +#endif + #ifdef __cplusplus } #endif diff --git a/modules/oset-c++ b/modules/oset-c++ index 76980f9584..7c5de7df28 100644 --- a/modules/oset-c++ +++ b/modules/oset-c++ @@ -8,6 +8,8 @@ Depends-on: xoset configure.ac: +AC_DEFINE([_GL_HAVE_OSET_HH], [1], + [Define if the gnulib module oset-c++ is present.]) Makefile.am: -- 2.53.0
>From c1abdadc3881c0b1a365e3ae696d13a6d113b2a7 Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Wed, 12 Aug 2026 19:10:50 +0200 Subject: [PATCH 5/6] map-c++: Avoid clang UBSAN runtime errors. * modules/map-c++ (configure.ac): Define _GL_HAVE_MAP_HH. * lib/gl_map.h (_GL_MAP_INVOKES_FN_PTR): New macro. (gl_map_nx_put, gl_map_remove): Mark as _GL_MAP_INVOKES_FN_PTR. * lib/gl_array_map.c (gl_array_indexof, gl_array_remove_at, gl_array_free): Likewise. * lib/gl_hash_map.c (gl_hash_search, gl_hash_nx_getput, gl_hash_getremove, gl_hash_free): Likewise. * lib/gl_linkedhash_map.c (gl_linkedhash_search, gl_linkedhash_nx_getput, gl_linkedhash_getremove, gl_linkedhash_free): Likewise. --- ChangeLog | 14 ++++++++++++++ lib/gl_array_map.c | 3 +++ lib/gl_hash_map.c | 4 ++++ lib/gl_linkedhash_map.c | 4 ++++ lib/gl_map.h | 10 ++++++++++ modules/map-c++ | 2 ++ 6 files changed, 37 insertions(+) diff --git a/ChangeLog b/ChangeLog index f511eb6aa1..a700d95ef5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2026-08-12 Bruno Haible <[email protected]> + + map-c++: Avoid clang UBSAN runtime errors. + * modules/map-c++ (configure.ac): Define _GL_HAVE_MAP_HH. + * lib/gl_map.h (_GL_MAP_INVOKES_FN_PTR): New macro. + (gl_map_nx_put, gl_map_remove): Mark as _GL_MAP_INVOKES_FN_PTR. + * lib/gl_array_map.c (gl_array_indexof, gl_array_remove_at, + gl_array_free): Likewise. + * lib/gl_hash_map.c (gl_hash_search, gl_hash_nx_getput, + gl_hash_getremove, gl_hash_free): Likewise. + * lib/gl_linkedhash_map.c (gl_linkedhash_search, + gl_linkedhash_nx_getput, gl_linkedhash_getremove, gl_linkedhash_free): + Likewise. + 2026-08-12 Bruno Haible <[email protected]> oset-c++: Avoid clang UBSAN runtime errors. diff --git a/lib/gl_array_map.c b/lib/gl_array_map.c index e4c897fffd..30ff4a9d44 100644 --- a/lib/gl_array_map.c +++ b/lib/gl_array_map.c @@ -78,6 +78,7 @@ gl_array_size (gl_map_t map) static size_t gl_array_indexof (gl_map_t map, const void *key) + _GL_MAP_INVOKES_FN_PTR { size_t count = map->count; @@ -162,6 +163,7 @@ gl_array_nx_getput (gl_map_t map, const void *key, const void *value, 0 <= position < gl_map_size (map). */ static void gl_array_remove_at (gl_map_t map, size_t position) + _GL_MAP_INVOKES_FN_PTR { size_t count = map->count; struct pair *pairs = map->pairs; @@ -188,6 +190,7 @@ gl_array_getremove (gl_map_t map, const void *key, const void **oldvaluep) static void gl_array_free (gl_map_t map) + _GL_MAP_INVOKES_FN_PTR { if (map->pairs != NULL) { diff --git a/lib/gl_hash_map.c b/lib/gl_hash_map.c index 608c8475cf..dbfea05995 100644 --- a/lib/gl_hash_map.c +++ b/lib/gl_hash_map.c @@ -97,6 +97,7 @@ gl_hash_size (gl_map_t map) _GL_ATTRIBUTE_REPRODUCIBLE static bool gl_hash_search (gl_map_t map, const void *key, const void **valuep) + _GL_MAP_INVOKES_FN_PTR { size_t hashcode = (map->hashcode_fn != NULL @@ -123,6 +124,7 @@ gl_hash_search (gl_map_t map, const void *key, const void **valuep) static int gl_hash_nx_getput (gl_map_t map, const void *key, const void *value, const void **oldvaluep) + _GL_MAP_INVOKES_FN_PTR { size_t hashcode = (map->hashcode_fn != NULL @@ -170,6 +172,7 @@ gl_hash_nx_getput (gl_map_t map, const void *key, const void *value, static bool gl_hash_getremove (gl_map_t map, const void *key, const void **oldvaluep) + _GL_MAP_INVOKES_FN_PTR { size_t hashcode = (map->hashcode_fn != NULL @@ -209,6 +212,7 @@ gl_hash_getremove (gl_map_t map, const void *key, const void **oldvaluep) static void gl_hash_free (gl_map_t map) + _GL_MAP_INVOKES_FN_PTR { if (map->count > 0) { diff --git a/lib/gl_linkedhash_map.c b/lib/gl_linkedhash_map.c index d6530aa0bd..ece3437f2e 100644 --- a/lib/gl_linkedhash_map.c +++ b/lib/gl_linkedhash_map.c @@ -122,6 +122,7 @@ gl_linkedhash_size (gl_map_t map) _GL_ATTRIBUTE_REPRODUCIBLE static bool gl_linkedhash_search (gl_map_t map, const void *key, const void **valuep) + _GL_MAP_INVOKES_FN_PTR { size_t hashcode = (map->hashcode_fn != NULL @@ -148,6 +149,7 @@ gl_linkedhash_search (gl_map_t map, const void *key, const void **valuep) static int gl_linkedhash_nx_getput (gl_map_t map, const void *key, const void *value, const void **oldvaluep) + _GL_MAP_INVOKES_FN_PTR { size_t hashcode = (map->hashcode_fn != NULL @@ -199,6 +201,7 @@ gl_linkedhash_nx_getput (gl_map_t map, const void *key, const void *value, static bool gl_linkedhash_getremove (gl_map_t map, const void *key, const void **oldvaluep) + _GL_MAP_INVOKES_FN_PTR { size_t hashcode = (map->hashcode_fn != NULL @@ -245,6 +248,7 @@ gl_linkedhash_getremove (gl_map_t map, const void *key, const void **oldvaluep) static void gl_linkedhash_free (gl_map_t map) + _GL_MAP_INVOKES_FN_PTR { gl_mapkey_dispose_fn kdispose = map->base.kdispose_fn; gl_mapvalue_dispose_fn vdispose = map->base.vdispose_fn; diff --git a/lib/gl_map.h b/lib/gl_map.h index ac1762db9f..972689a551 100644 --- a/lib/gl_map.h +++ b/lib/gl_map.h @@ -327,6 +327,14 @@ gl_map_iterator_free (gl_map_iterator_t *iterator) iterator->vtable->iterator_free (iterator); } +/* Avoid that the reinterpret_cast<>s in gl_map.hh cause runtime errors + "call to function ... through pointer to incorrect function type". */ +#if _GL_HAVE_MAP_HH && defined __clang__ && __clang_major__ >= 4 +# define _GL_MAP_INVOKES_FN_PTR __attribute__ ((no_sanitize ("function"))) +#else +# define _GL_MAP_INVOKES_FN_PTR +#endif + /* Define the convenience functions, that is, the functions that are independent of the implementation. */ @@ -340,6 +348,7 @@ gl_map_get (gl_map_t map, const void *key) _GL_ATTRIBUTE_NODISCARD GL_MAP_INLINE int gl_map_nx_put (gl_map_t map, const void *key, const void *value) + _GL_MAP_INVOKES_FN_PTR { const void *oldvalue; int result = gl_map_nx_getput (map, key, value, &oldvalue); @@ -355,6 +364,7 @@ gl_map_nx_put (gl_map_t map, const void *key, const void *value) GL_MAP_INLINE bool gl_map_remove (gl_map_t map, const void *key) + _GL_MAP_INVOKES_FN_PTR { const void *oldvalue; bool result = gl_map_getremove (map, key, &oldvalue); diff --git a/modules/map-c++ b/modules/map-c++ index ea5f215b1c..c1d5006649 100644 --- a/modules/map-c++ +++ b/modules/map-c++ @@ -8,6 +8,8 @@ Depends-on: xmap configure.ac: +AC_DEFINE([_GL_HAVE_MAP_HH], [1], + [Define if the gnulib module map-c++ is present.]) Makefile.am: -- 2.53.0
>From 09b1597470c456aeac7e7d19b214821d4526934d Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Wed, 12 Aug 2026 19:14:19 +0200 Subject: [PATCH 6/6] omap-c++: Avoid clang UBSAN runtime errors. * modules/omap-c++ (configure.ac): Define _GL_HAVE_OMAP_HH. * lib/gl_omap.h (_GL_OMAP_INVOKES_FN_PTR): New macro. (gl_omap_nx_put, gl_omap_remove): Mark as _GL_OMAP_INVOKES_FN_PTR. * lib/gl_array_omap.c (gl_array_indexof, gl_array_search_atleast, gl_array_nx_getput, gl_array_remove_at, gl_array_free): Likewise. * lib/gl_anytree_omap.h (gl_tree_search, gl_tree_search_atleast, gl_tree_nx_getput, gl_tree_getremove, gl_tree_omap_free): Likewise. --- ChangeLog | 11 +++++++++++ lib/gl_anytree_omap.h | 5 +++++ lib/gl_array_omap.c | 5 +++++ lib/gl_omap.h | 10 ++++++++++ modules/omap-c++ | 2 ++ 5 files changed, 33 insertions(+) diff --git a/ChangeLog b/ChangeLog index a700d95ef5..fe2bd22dd8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2026-08-12 Bruno Haible <[email protected]> + + omap-c++: Avoid clang UBSAN runtime errors. + * modules/omap-c++ (configure.ac): Define _GL_HAVE_OMAP_HH. + * lib/gl_omap.h (_GL_OMAP_INVOKES_FN_PTR): New macro. + (gl_omap_nx_put, gl_omap_remove): Mark as _GL_OMAP_INVOKES_FN_PTR. + * lib/gl_array_omap.c (gl_array_indexof, gl_array_search_atleast, + gl_array_nx_getput, gl_array_remove_at, gl_array_free): Likewise. + * lib/gl_anytree_omap.h (gl_tree_search, gl_tree_search_atleast, + gl_tree_nx_getput, gl_tree_getremove, gl_tree_omap_free): Likewise. + 2026-08-12 Bruno Haible <[email protected]> map-c++: Avoid clang UBSAN runtime errors. diff --git a/lib/gl_anytree_omap.h b/lib/gl_anytree_omap.h index 6ee326371e..b0779a7446 100644 --- a/lib/gl_anytree_omap.h +++ b/lib/gl_anytree_omap.h @@ -57,6 +57,7 @@ gl_tree_size (gl_omap_t map) static bool gl_tree_search (gl_omap_t map, const void *key, const void **valuep) + _GL_OMAP_INVOKES_FN_PTR { gl_mapkey_compar_fn compar = map->base.compar_fn; @@ -86,6 +87,7 @@ gl_tree_search_atleast (gl_omap_t map, gl_mapkey_threshold_fn threshold_fn, const void *threshold, const void **keyp, const void **valuep) + _GL_OMAP_INVOKES_FN_PTR { for (gl_omap_node_t node = map->root; node != NULL; ) { @@ -118,6 +120,7 @@ gl_tree_search_atleast (gl_omap_t map, static int gl_tree_nx_getput (gl_omap_t map, const void *key, const void *value, const void **oldvaluep) + _GL_OMAP_INVOKES_FN_PTR { gl_omap_node_t node = map->root; @@ -168,6 +171,7 @@ gl_tree_nx_getput (gl_omap_t map, const void *key, const void *value, static bool gl_tree_getremove (gl_omap_t map, const void *key, const void **oldvaluep) + _GL_OMAP_INVOKES_FN_PTR { gl_mapkey_compar_fn compar = map->base.compar_fn; @@ -195,6 +199,7 @@ gl_tree_getremove (gl_omap_t map, const void *key, const void **oldvaluep) static void gl_tree_omap_free (gl_omap_t map) + _GL_OMAP_INVOKES_FN_PTR { /* Iterate across all elements in post-order. */ gl_omap_node_t node = map->root; diff --git a/lib/gl_array_omap.c b/lib/gl_array_omap.c index 24ea6a5d0b..f32c86210d 100644 --- a/lib/gl_array_omap.c +++ b/lib/gl_array_omap.c @@ -76,6 +76,7 @@ gl_array_size (gl_omap_t map) static size_t _GL_ATTRIBUTE_PURE gl_array_indexof (gl_omap_t map, const void *key) + _GL_OMAP_INVOKES_FN_PTR { size_t count = map->count; @@ -128,6 +129,7 @@ gl_array_search_atleast (gl_omap_t map, gl_mapkey_threshold_fn threshold_fn, const void *threshold, const void **keyp, const void **valuep) + _GL_OMAP_INVOKES_FN_PTR { size_t count = map->count; @@ -217,6 +219,7 @@ gl_array_nx_add_at (gl_omap_t map, size_t position, static int gl_array_nx_getput (gl_omap_t map, const void *key, const void *value, const void **oldvaluep) + _GL_OMAP_INVOKES_FN_PTR { size_t count = map->count; size_t low = 0; @@ -258,6 +261,7 @@ gl_array_nx_getput (gl_omap_t map, const void *key, const void *value, 0 <= position < gl_omap_size (map). */ static void gl_array_remove_at (gl_omap_t map, size_t position) + _GL_OMAP_INVOKES_FN_PTR { size_t count = map->count; struct pair *pairs = map->pairs; @@ -284,6 +288,7 @@ gl_array_getremove (gl_omap_t map, const void *key, const void **oldvaluep) static void gl_array_free (gl_omap_t map) + _GL_OMAP_INVOKES_FN_PTR { if (map->pairs != NULL) { diff --git a/lib/gl_omap.h b/lib/gl_omap.h index 59dc1d475f..ff12b4540c 100644 --- a/lib/gl_omap.h +++ b/lib/gl_omap.h @@ -345,6 +345,14 @@ gl_omap_iterator_free (gl_omap_iterator_t *iterator) iterator->vtable->iterator_free (iterator); } +/* Avoid that the reinterpret_cast<>s in gl_omap.hh cause runtime errors + "call to function ... through pointer to incorrect function type". */ +#if _GL_HAVE_OMAP_HH && defined __clang__ && __clang_major__ >= 4 +# define _GL_OMAP_INVOKES_FN_PTR __attribute__ ((no_sanitize ("function"))) +#else +# define _GL_OMAP_INVOKES_FN_PTR +#endif + /* Define the convenience functions, that is, the functions that are independent of the implementation. */ @@ -358,6 +366,7 @@ gl_omap_get (gl_omap_t map, const void *key) _GL_ATTRIBUTE_NODISCARD GL_OMAP_INLINE int gl_omap_nx_put (gl_omap_t map, const void *key, const void *value) + _GL_OMAP_INVOKES_FN_PTR { const void *oldvalue; int result = gl_omap_nx_getput (map, key, value, &oldvalue); @@ -373,6 +382,7 @@ gl_omap_nx_put (gl_omap_t map, const void *key, const void *value) GL_OMAP_INLINE bool gl_omap_remove (gl_omap_t map, const void *key) + _GL_OMAP_INVOKES_FN_PTR { const void *oldvalue; bool result = gl_omap_getremove (map, key, &oldvalue); diff --git a/modules/omap-c++ b/modules/omap-c++ index 3ced723ba5..10b59d0bf9 100644 --- a/modules/omap-c++ +++ b/modules/omap-c++ @@ -8,6 +8,8 @@ Depends-on: xomap configure.ac: +AC_DEFINE([_GL_HAVE_OMAP_HH], [1], + [Define if the gnulib module omap-c++ is present.]) Makefile.am: -- 2.53.0
