Re: Fix some "call to function ... through pointer to incorrect function type" errors
Bruno Haible via Gnulib discussion list <[email protected]>
| Newsgroups | gmane.comp.lib.gnulib.bugs |
|---|---|
| Message-ID | <7889650.ZlIXO0BPYK@cagnes> |
Lasse Collin wrote:
> These sanitizer errors mean that the program cannot be compiled with
> strict forms of control flow integrity checking. It can be done in
> software (clang -flto -fsanitize=cfi -fvisibility=hidden)
Thanks for mentioning this; I did not know about this kind of sanitize
combined with optimization.
Indeed, I see a few test failures in the test cases, still (despite
the no_sanitize ("function") attributes). Fixing them through the attached
patch.
But some other test failures will remain:
- jit/test-cache,
- test-list-c++, test-map-c++, test-omap-c++, test-oset-c++.
The reason is that C is not only used for application programming —
for which the above options "-flto -fsanitize=cfi -fvisibility=hidden"
make sense [except for GNOME / Qt and their "signals"] — but also for
system programming, where treating functions of different prototypes
in the same way is commonplace (think of libffi or libffcall), or for
generics (where C++ programmers like to have 10 different code
instantiations for 10 different pointer types, but C programmers don't
like that).
Bruno
2026-08-15 Bruno Haible <[email protected]>
tests: Support CC="clang -flto -fsanitize=cfi -fvisibility=hidden".
Reported by Lasse Collin in
<https://lists.gnu.org/archive/html/bug-gnulib/2026-08/msg00190.html>.
* tests/test-array_map.c (string_compare): New function.
(main): Use instead of casting strcmp to a different function prototype.
* tests/test-array_omap.c (string_compare): New function.
(main): Use instead of casting strcmp to a different function prototype.
* tests/test-avltree_omap.c (string_compare): New function.
(main): Use instead of casting strcmp to a different function prototype.
* tests/test-rbtree_omap.c (string_compare): New function.
(main): Use instead of casting strcmp to a different function prototype.
* tests/test-array_set.c (string_compare): New function.
(main): Use instead of casting strcmp to a different function prototype.
* tests/test-array_oset.c (string_compare): New function.
(main): Use instead of casting strcmp to a different function prototype.
* tests/test-avltree_oset.c (string_compare): New function.
(main): Use instead of casting strcmp to a different function prototype.
* tests/test-rbtree_oset.c (string_compare): New function.
(main): Use instead of casting strcmp to a different function prototype.
* tests/test-oset-update.h (test_update): Likewise.
0001-tests-Support-CC-clang-flto-fsanitize-cfi-fvisibilit.patch
(text/x-patch, 19 KB)
From 9388edc18a2c1de1ae9f58cef2446e1c1116bf36 Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Sat, 15 Aug 2026 17:46:48 +0200 Subject: [PATCH] tests: Support CC="clang -flto -fsanitize=cfi -fvisibility=hidden". Reported by Lasse Collin in <https://lists.gnu.org/archive/html/bug-gnulib/2026-08/msg00190.html>. * tests/test-array_map.c (string_compare): New function. (main): Use instead of casting strcmp to a different function prototype. * tests/test-array_omap.c (string_compare): New function. (main): Use instead of casting strcmp to a different function prototype. * tests/test-avltree_omap.c (string_compare): New function. (main): Use instead of casting strcmp to a different function prototype. * tests/test-rbtree_omap.c (string_compare): New function. (main): Use instead of casting strcmp to a different function prototype. * tests/test-array_set.c (string_compare): New function. (main): Use instead of casting strcmp to a different function prototype. * tests/test-array_oset.c (string_compare): New function. (main): Use instead of casting strcmp to a different function prototype. * tests/test-avltree_oset.c (string_compare): New function. (main): Use instead of casting strcmp to a different function prototype. * tests/test-rbtree_oset.c (string_compare): New function. (main): Use instead of casting strcmp to a different function prototype. * tests/test-oset-update.h (test_update): Likewise. --- ChangeLog | 23 +++++++++++++++++++++++ tests/test-array_map.c | 24 ++++++++++++++++-------- tests/test-array_omap.c | 26 +++++++++++++++++--------- tests/test-array_oset.c | 26 +++++++++++++++++--------- tests/test-array_set.c | 10 +++++++++- tests/test-avltree_omap.c | 12 ++++++++++-- tests/test-avltree_oset.c | 16 ++++++++++++---- tests/test-oset-update.h | 2 +- tests/test-rbtree_omap.c | 12 ++++++++++-- tests/test-rbtree_oset.c | 16 ++++++++++++---- 10 files changed, 127 insertions(+), 40 deletions(-) diff --git a/ChangeLog b/ChangeLog index f6b4603910..19acb732d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2026-08-15 Bruno Haible <[email protected]> + + tests: Support CC="clang -flto -fsanitize=cfi -fvisibility=hidden". + Reported by Lasse Collin in + <https://lists.gnu.org/archive/html/bug-gnulib/2026-08/msg00190.html>. + * tests/test-array_map.c (string_compare): New function. + (main): Use instead of casting strcmp to a different function prototype. + * tests/test-array_omap.c (string_compare): New function. + (main): Use instead of casting strcmp to a different function prototype. + * tests/test-avltree_omap.c (string_compare): New function. + (main): Use instead of casting strcmp to a different function prototype. + * tests/test-rbtree_omap.c (string_compare): New function. + (main): Use instead of casting strcmp to a different function prototype. + * tests/test-array_set.c (string_compare): New function. + (main): Use instead of casting strcmp to a different function prototype. + * tests/test-array_oset.c (string_compare): New function. + (main): Use instead of casting strcmp to a different function prototype. + * tests/test-avltree_oset.c (string_compare): New function. + (main): Use instead of casting strcmp to a different function prototype. + * tests/test-rbtree_oset.c (string_compare): New function. + (main): Use instead of casting strcmp to a different function prototype. + * tests/test-oset-update.h (test_update): Likewise. + 2026-08-15 Bruno Haible <[email protected]> memmove: Avoid undefined behaviour upon memmove (NULL, ptr, 0). diff --git a/tests/test-array_map.c b/tests/test-array_map.c index 5e93d4b74c..265debd550 100644 --- a/tests/test-array_map.c +++ b/tests/test-array_map.c @@ -34,6 +34,14 @@ static const char *objects[30] = "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "<", ">", "[", "]" }; +static int +string_compare (const void *elt1, const void *elt2) +{ + const char *s1 = elt1; + const char *s2 = elt2; + return strcmp (s1, s2); +} + static bool string_equals (const void *x1, const void *x2) { @@ -143,12 +151,12 @@ main (int argc, char *argv[]) const char *key = RANDOM_OBJECT (); const char *value = RANDOM_OBJECT (); bool added = gl_map_nx_put (map1, key, value); - size_t index = gl_sortedlist_indexof (keys, (gl_listelement_compar_fn)strcmp, key); + size_t index = gl_sortedlist_indexof (keys, string_compare, key); ASSERT (added == (index == (size_t)(-1))); if (added) { - gl_sortedlist_add (keys, (gl_listelement_compar_fn)strcmp, key); - index = gl_sortedlist_indexof (keys, (gl_listelement_compar_fn)strcmp, key); + gl_sortedlist_add (keys, string_compare, key); + index = gl_sortedlist_indexof (keys, string_compare, key); gl_list_add_at (values, index, value); } else @@ -166,7 +174,7 @@ main (int argc, char *argv[]) const char *key = RANDOM_OBJECT (); const void *ret = gl_map_get (map1, key); size_t index = - gl_sortedlist_indexof (keys, (gl_listelement_compar_fn)strcmp, key); + gl_sortedlist_indexof (keys, string_compare, key); ASSERT (ret == (index != (size_t)(-1) ? gl_list_get_at (values, index) : NULL)); } @@ -177,12 +185,12 @@ main (int argc, char *argv[]) const char *value = RANDOM_OBJECT (); bool added = gl_map_nx_put (map1, key, value); size_t index = - gl_sortedlist_indexof (keys, (gl_listelement_compar_fn)strcmp, key); + gl_sortedlist_indexof (keys, string_compare, key); ASSERT (added == (index == (size_t)(-1))); if (added) { - gl_sortedlist_add (keys, (gl_listelement_compar_fn)strcmp, key); - index = gl_sortedlist_indexof (keys, (gl_listelement_compar_fn)strcmp, key); + gl_sortedlist_add (keys, string_compare, key); + index = gl_sortedlist_indexof (keys, string_compare, key); gl_list_add_at (values, index, value); } else @@ -194,7 +202,7 @@ main (int argc, char *argv[]) const char *key = RANDOM_OBJECT (); bool removed = gl_map_remove (map1, key); size_t index = - gl_sortedlist_indexof (keys, (gl_listelement_compar_fn)strcmp, key); + gl_sortedlist_indexof (keys, string_compare, key); ASSERT (removed == (index != (size_t)(-1))); if (removed) { diff --git a/tests/test-array_omap.c b/tests/test-array_omap.c index 44c4e8d18e..b04ab30467 100644 --- a/tests/test-array_omap.c +++ b/tests/test-array_omap.c @@ -73,6 +73,14 @@ check_all (gl_omap_t map1, gl_list_t keys, gl_list_t values) check_equals (map1, keys, values); } +static int +string_compare (const void *elt1, const void *elt2) +{ + const char *s1 = elt1; + const char *s2 = elt2; + return strcmp (s1, s2); +} + int main (int argc, char *argv[]) { @@ -88,7 +96,7 @@ main (int argc, char *argv[]) size_t initial_size = RANDOM (20); /* Create map1. */ - map1 = gl_omap_nx_create_empty (GL_ARRAY_OMAP, (gl_mapkey_compar_fn) strcmp, NULL, NULL); + map1 = gl_omap_nx_create_empty (GL_ARRAY_OMAP, string_compare, NULL, NULL); ASSERT (map1 != NULL); /* Create keys and values. */ @@ -103,12 +111,12 @@ main (int argc, char *argv[]) const char *key = RANDOM_OBJECT (); const char *value = RANDOM_OBJECT (); bool added = gl_omap_nx_put (map1, key, value); - size_t index = gl_sortedlist_indexof (keys, (gl_listelement_compar_fn)strcmp, key); + size_t index = gl_sortedlist_indexof (keys, string_compare, key); ASSERT (added == (index == (size_t)(-1))); if (added) { - gl_sortedlist_add (keys, (gl_listelement_compar_fn)strcmp, key); - index = gl_sortedlist_indexof (keys, (gl_listelement_compar_fn)strcmp, key); + gl_sortedlist_add (keys, string_compare, key); + index = gl_sortedlist_indexof (keys, string_compare, key); gl_list_add_at (values, index, value); } else @@ -126,7 +134,7 @@ main (int argc, char *argv[]) const char *key = RANDOM_OBJECT (); const void *ret = gl_omap_get (map1, key); size_t index = - gl_sortedlist_indexof (keys, (gl_listelement_compar_fn)strcmp, key); + gl_sortedlist_indexof (keys, string_compare, key); ASSERT (ret == (index != (size_t)(-1) ? gl_list_get_at (values, index) : NULL)); } @@ -137,12 +145,12 @@ main (int argc, char *argv[]) const char *value = RANDOM_OBJECT (); bool added = gl_omap_nx_put (map1, key, value); size_t index = - gl_sortedlist_indexof (keys, (gl_listelement_compar_fn)strcmp, key); + gl_sortedlist_indexof (keys, string_compare, key); ASSERT (added == (index == (size_t)(-1))); if (added) { - gl_sortedlist_add (keys, (gl_listelement_compar_fn)strcmp, key); - index = gl_sortedlist_indexof (keys, (gl_listelement_compar_fn)strcmp, key); + gl_sortedlist_add (keys, string_compare, key); + index = gl_sortedlist_indexof (keys, string_compare, key); gl_list_add_at (values, index, value); } else @@ -154,7 +162,7 @@ main (int argc, char *argv[]) const char *key = RANDOM_OBJECT (); bool removed = gl_omap_remove (map1, key); size_t index = - gl_sortedlist_indexof (keys, (gl_listelement_compar_fn)strcmp, key); + gl_sortedlist_indexof (keys, string_compare, key); ASSERT (removed == (index != (size_t)(-1))); if (removed) { diff --git a/tests/test-array_oset.c b/tests/test-array_oset.c index 59aae8be9c..99c095a2bb 100644 --- a/tests/test-array_oset.c +++ b/tests/test-array_oset.c @@ -27,8 +27,6 @@ #include "gl_array_list.h" #include "macros.h" -#include "test-oset-update.h" - static const char *objects[30] = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", @@ -68,6 +66,14 @@ check_all (gl_oset_t set1, gl_list_t set2) check_equals (set1, set2); } +static int +string_compare (const void *elt1, const void *elt2) +{ + const char *s1 = elt1; + const char *s2 = elt2; + return strcmp (s1, s2); +} + static bool is_at_least (const void *elt, const void *threshold) { @@ -88,6 +94,8 @@ gl_sortedlist_indexof_atleast (gl_list_t set, return (size_t)(-1); } +#include "test-oset-update.h" + int main (int argc, char *argv[]) { @@ -102,7 +110,7 @@ main (int argc, char *argv[]) size_t initial_size = RANDOM (20); /* Create set1. */ - set1 = gl_oset_nx_create_empty (GL_ARRAY_OSET, (gl_setelement_compar_fn) strcmp, NULL); + set1 = gl_oset_nx_create_empty (GL_ARRAY_OSET, string_compare, NULL); ASSERT (set1 != NULL); /* Create set2. */ @@ -115,9 +123,9 @@ main (int argc, char *argv[]) { const char *obj = RANDOM_OBJECT (); ASSERT (gl_oset_nx_add (set1, obj) - == (gl_sortedlist_search (set2, (gl_listelement_compar_fn)strcmp, obj) != NULL + == (gl_sortedlist_search (set2, string_compare, obj) != NULL ? false - : (gl_sortedlist_add (set2, (gl_listelement_compar_fn)strcmp, obj), true))); + : (gl_sortedlist_add (set2, string_compare, obj), true))); check_all (set1, set2); } @@ -130,23 +138,23 @@ main (int argc, char *argv[]) { const char *obj = RANDOM_OBJECT (); ASSERT (gl_oset_search (set1, obj) - == (gl_sortedlist_search (set2, (gl_listelement_compar_fn)strcmp, obj) != NULL)); + == (gl_sortedlist_search (set2, string_compare, obj) != NULL)); } break; case 1: { const char *obj = RANDOM_OBJECT (); ASSERT (gl_oset_nx_add (set1, obj) - == (gl_sortedlist_search (set2, (gl_listelement_compar_fn)strcmp, obj) != NULL + == (gl_sortedlist_search (set2, string_compare, obj) != NULL ? false - : (gl_sortedlist_add (set2, (gl_listelement_compar_fn)strcmp, obj), true))); + : (gl_sortedlist_add (set2, string_compare, obj), true))); } break; case 2: { const char *obj = RANDOM_OBJECT (); ASSERT (gl_oset_remove (set1, obj) - == gl_sortedlist_remove (set2, (gl_listelement_compar_fn)strcmp, obj)); + == gl_sortedlist_remove (set2, string_compare, obj)); } break; case 3: diff --git a/tests/test-array_set.c b/tests/test-array_set.c index 4d18ecd1c7..1d02238fa7 100644 --- a/tests/test-array_set.c +++ b/tests/test-array_set.c @@ -88,6 +88,14 @@ check_all (gl_set_t set1, gl_oset_t set2) check_equals (set1, set2); } +static int +string_compare (const void *elt1, const void *elt2) +{ + const char *s1 = elt1; + const char *s2 = elt2; + return strcmp (s1, s2); +} + int main (int argc, char *argv[]) { @@ -106,7 +114,7 @@ main (int argc, char *argv[]) ASSERT (set1 != NULL); /* Create set2. */ - set2 = gl_oset_create_empty (GL_ARRAY_OSET, (gl_setelement_compar_fn) strcmp, NULL); + set2 = gl_oset_create_empty (GL_ARRAY_OSET, string_compare, NULL); check_all (set1, set2); diff --git a/tests/test-avltree_omap.c b/tests/test-avltree_omap.c index d116971c4e..0a9bb3a616 100644 --- a/tests/test-avltree_omap.c +++ b/tests/test-avltree_omap.c @@ -69,6 +69,14 @@ check_all (gl_omap_t map1, gl_omap_t map2) check_equals (map1, map2); } +static int +string_compare (const void *key1, const void *key2) +{ + const char *s1 = key1; + const char *s2 = key2; + return strcmp (s1, s2); +} + int main (int argc, char *argv[]) { @@ -82,11 +90,11 @@ main (int argc, char *argv[]) size_t initial_size = RANDOM (20); /* Create map1. */ - map1 = gl_omap_nx_create_empty (GL_ARRAY_OMAP, (gl_mapkey_compar_fn) strcmp, NULL, NULL); + map1 = gl_omap_nx_create_empty (GL_ARRAY_OMAP, string_compare, NULL, NULL); ASSERT (map1 != NULL); /* Create map2. */ - map2 = gl_omap_nx_create_empty (GL_AVLTREE_OMAP, (gl_mapkey_compar_fn) strcmp, NULL, NULL); + map2 = gl_omap_nx_create_empty (GL_AVLTREE_OMAP, string_compare, NULL, NULL); ASSERT (map2 != NULL); check_all (map1, map2); diff --git a/tests/test-avltree_oset.c b/tests/test-avltree_oset.c index 2a68aca332..9b1f2e32a1 100644 --- a/tests/test-avltree_oset.c +++ b/tests/test-avltree_oset.c @@ -26,8 +26,6 @@ #include "gl_array_oset.h" #include "macros.h" -#include "test-oset-update.h" - extern void gl_avltree_oset_check_invariants (gl_oset_t set); static const char *objects[30] = @@ -68,12 +66,22 @@ check_all (gl_oset_t set1, gl_oset_t set2) check_equals (set1, set2); } +static int +string_compare (const void *elt1, const void *elt2) +{ + const char *s1 = elt1; + const char *s2 = elt2; + return strcmp (s1, s2); +} + static bool is_at_least (const void *elt, const void *threshold) { return strcmp ((const char *) elt, (const char *) threshold) >= 0; } +#include "test-oset-update.h" + int main (int argc, char *argv[]) { @@ -87,11 +95,11 @@ main (int argc, char *argv[]) size_t initial_size = RANDOM (20); /* Create set1. */ - set1 = gl_oset_nx_create_empty (GL_ARRAY_OSET, (gl_setelement_compar_fn) strcmp, NULL); + set1 = gl_oset_nx_create_empty (GL_ARRAY_OSET, string_compare, NULL); ASSERT (set1 != NULL); /* Create set2. */ - set2 = gl_oset_nx_create_empty (GL_AVLTREE_OSET, (gl_setelement_compar_fn) strcmp, NULL); + set2 = gl_oset_nx_create_empty (GL_AVLTREE_OSET, string_compare, NULL); ASSERT (set2 != NULL); check_all (set1, set2); diff --git a/tests/test-oset-update.h b/tests/test-oset-update.h index 973b6258a8..e301eb218e 100644 --- a/tests/test-oset-update.h +++ b/tests/test-oset-update.h @@ -30,7 +30,7 @@ test_update (gl_oset_implementation_t implementation) char D[2] = "D"; gl_oset_t set1 = - gl_oset_nx_create_empty (implementation, (gl_setelement_compar_fn) strcmp, NULL); + gl_oset_nx_create_empty (implementation, string_compare, NULL); ASSERT (set1 != NULL); /* Fill the set. */ diff --git a/tests/test-rbtree_omap.c b/tests/test-rbtree_omap.c index 4d0781ca5e..777170fba8 100644 --- a/tests/test-rbtree_omap.c +++ b/tests/test-rbtree_omap.c @@ -69,6 +69,14 @@ check_all (gl_omap_t map1, gl_omap_t map2) check_equals (map1, map2); } +static int +string_compare (const void *key1, const void *key2) +{ + const char *s1 = key1; + const char *s2 = key2; + return strcmp (s1, s2); +} + int main (int argc, char *argv[]) { @@ -82,11 +90,11 @@ main (int argc, char *argv[]) size_t initial_size = RANDOM (20); /* Create map1. */ - map1 = gl_omap_nx_create_empty (GL_ARRAY_OMAP, (gl_mapkey_compar_fn) strcmp, NULL, NULL); + map1 = gl_omap_nx_create_empty (GL_ARRAY_OMAP, string_compare, NULL, NULL); ASSERT (map1 != NULL); /* Create map2. */ - map2 = gl_omap_nx_create_empty (GL_RBTREE_OMAP, (gl_mapkey_compar_fn) strcmp, NULL, NULL); + map2 = gl_omap_nx_create_empty (GL_RBTREE_OMAP, string_compare, NULL, NULL); ASSERT (map2 != NULL); check_all (map1, map2); diff --git a/tests/test-rbtree_oset.c b/tests/test-rbtree_oset.c index 6edb6e72e1..385a216cd3 100644 --- a/tests/test-rbtree_oset.c +++ b/tests/test-rbtree_oset.c @@ -26,8 +26,6 @@ #include "gl_array_oset.h" #include "macros.h" -#include "test-oset-update.h" - extern void gl_rbtree_oset_check_invariants (gl_oset_t set); static const char *objects[30] = @@ -68,12 +66,22 @@ check_all (gl_oset_t set1, gl_oset_t set2) check_equals (set1, set2); } +static int +string_compare (const void *elt1, const void *elt2) +{ + const char *s1 = elt1; + const char *s2 = elt2; + return strcmp (s1, s2); +} + static bool is_at_least (const void *elt, const void *threshold) { return strcmp ((const char *) elt, (const char *) threshold) >= 0; } +#include "test-oset-update.h" + int main (int argc, char *argv[]) { @@ -87,11 +95,11 @@ main (int argc, char *argv[]) size_t initial_size = RANDOM (20); /* Create set1. */ - set1 = gl_oset_nx_create_empty (GL_ARRAY_OSET, (gl_setelement_compar_fn) strcmp, NULL); + set1 = gl_oset_nx_create_empty (GL_ARRAY_OSET, string_compare, NULL); ASSERT (set1 != NULL); /* Create set2. */ - set2 = gl_oset_nx_create_empty (GL_RBTREE_OSET, (gl_setelement_compar_fn) strcmp, NULL); + set2 = gl_oset_nx_create_empty (GL_RBTREE_OSET, string_compare, NULL); ASSERT (set2 != NULL); check_all (set1, set2); -- 2.53.0