clang implements and gcc 16 promises to implement the 'counted_by' attribute. It can help strengthen the bounds-checking done by the UBSAN.
For now, you'll need clang (19 or newer) in order to make use of it. Use clang's UBSAN to verify that your code sets the counter field and the array/pointer field in the right order. Later, when gcc fixes <https://gcc.gnu.org/PR125072>, we will also be able to make use of it with gcc. 2026-05-01 Bruno Haible <[email protected]> hamt: Use the counted_by attribute. * lib/hamt.c (struct bucket): Mark the elts fields as counted_by elt_count. 2026-05-01 Bruno Haible <[email protected]> attribute: Provide access to clang's counted_by attribute. * m4/gnulib-common.m4 (gl_COMMON_BODY): Define _GL_ATTRIBUTE_COUNTED_BY. * lib/attribute.h (COUNTED_BY): New macro.
>From f1e03c6be1a257cda1a6b00b1dac7de6c72237b0 Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Fri, 1 May 2026 23:59:06 +0200 Subject: [PATCH 1/2] attribute: Provide access to clang's counted_by attribute. * m4/gnulib-common.m4 (gl_COMMON_BODY): Define _GL_ATTRIBUTE_COUNTED_BY. * lib/attribute.h (COUNTED_BY): New macro. --- ChangeLog | 6 ++++++ lib/attribute.h | 17 +++++++++++++++-- m4/gnulib-common.m4 | 19 ++++++++++++++++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9841cc99fd..fea097ebd4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2026-05-01 Bruno Haible <[email protected]> + + attribute: Provide access to clang's counted_by attribute. + * m4/gnulib-common.m4 (gl_COMMON_BODY): Define _GL_ATTRIBUTE_COUNTED_BY. + * lib/attribute.h (COUNTED_BY): New macro. + 2026-05-01 Bruno Haible <[email protected]> Improve comments about GCC bugs. diff --git a/lib/attribute.h b/lib/attribute.h index c50befdfdd..10de47516f 100644 --- a/lib/attribute.h +++ b/lib/attribute.h @@ -81,8 +81,8 @@ /* This file uses _GL_ATTRIBUTE_ALLOC_SIZE, _GL_ATTRIBUTE_ALWAYS_INLINE, _GL_ATTRIBUTE_ARTIFICIAL, _GL_ATTRIBUTE_COLD, _GL_ATTRIBUTE_CONST, - _GL_ATTRIBUTE_DEALLOC, _GL_ATTRIBUTE_DEPRECATED, _GL_ATTRIBUTE_ERROR, - _GL_ATTRIBUTE_WARNING, _GL_ATTRIBUTE_EXTERNALLY_VISIBLE, + _GL_ATTRIBUTE_COUNTED_BY, _GL_ATTRIBUTE_DEALLOC, _GL_ATTRIBUTE_DEPRECATED, + _GL_ATTRIBUTE_ERROR, _GL_ATTRIBUTE_WARNING, _GL_ATTRIBUTE_EXTERNALLY_VISIBLE, _GL_ATTRIBUTE_FALLTHROUGH, _GL_ATTRIBUTE_FORMAT, _GL_ATTRIBUTE_LEAF, _GL_ATTRIBUTE_MALLOC, _GL_ATTRIBUTE_MAY_ALIAS, _GL_ATTRIBUTE_MAYBE_UNUSED, _GL_ATTRIBUTE_NODISCARD, _GL_ATTRIBUTE_NOINLINE, _GL_ATTRIBUTE_NONNULL, @@ -210,6 +210,19 @@ #define FALLTHROUGH _GL_ATTRIBUTE_FALLTHROUGH +/* =================== Attributes for runtime diagnostics =================== */ + +/* Attributes that provide information to the undefined-behaviour sanitizer + (UBSAN). */ + +/* COUNTED_BY (C) declares that the number of elements of the field is given + by C, which must be another field in the same struct. + The programmer is responsible for guaranteeing some invariants; see + <https://gcc.gnu.org/onlinedocs/gcc/Common-Attributes.html> for details. */ +/* Applies to struct fields of type array or pointer (to data). */ +#define COUNTED_BY(c) _GL_ATTRIBUTE_COUNTED_BY (c) + + /* ================== Attributes for debugging information ================== */ /* Attributes regarding debugging information emitted by the compiler. */ diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4 index 56189a7d78..e11be3cc84 100644 --- a/m4/gnulib-common.m4 +++ b/m4/gnulib-common.m4 @@ -1,5 +1,5 @@ # gnulib-common.m4 -# serial 116 +# serial 117 dnl Copyright (C) 2007-2026 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -436,6 +436,23 @@ AC_DEFUN([gl_COMMON_BODY] # endif #endif +/* _GL_ATTRIBUTE_COUNTED_BY (C) declares that the number of elements of + the field is given by C, which must be another field in the same struct. + The programmer is responsible for guaranteeing some invariants; see + <https://gcc.gnu.org/onlinedocs/gcc/Common-Attributes.html> for details. */ +/* Applies to struct fields of type array or pointer (to data). */ +#ifndef _GL_ATTRIBUTE_COUNTED_BY +/* This attributes is supported + - for fields of array type: by gcc >= 16, clang >= 18, + - for fields of pointer type: by gcc when <https://gcc.gnu.org/PR125072> + will be fixed, clang >= 19. */ +# if defined __clang__ && __clang_major__ >= 19 +# define _GL_ATTRIBUTE_COUNTED_BY(c) __attribute__ ((__counted_by__ (c))) +# else +# define _GL_ATTRIBUTE_COUNTED_BY(c) +# endif +#endif + /* _GL_ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers that can be freed by passing them as the Ith argument to the function F. -- 2.52.0
>From 095a527db6528a01b976277e853f212b2f3a8507 Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Sat, 2 May 2026 00:14:10 +0200 Subject: [PATCH 2/2] hamt: Use the counted_by attribute. * lib/hamt.c (struct bucket): Mark the elts fields as counted_by elt_count. --- ChangeLog | 6 ++++++ lib/hamt.c | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index fea097ebd4..95e6371a86 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2026-05-01 Bruno Haible <[email protected]> + + hamt: Use the counted_by attribute. + * lib/hamt.c (struct bucket): Mark the elts fields as counted_by + elt_count. + 2026-05-01 Bruno Haible <[email protected]> attribute: Provide access to clang's counted_by attribute. diff --git a/lib/hamt.c b/lib/hamt.c index 3fbb68e402..fa4bed98d1 100644 --- a/lib/hamt.c +++ b/lib/hamt.c @@ -122,7 +122,8 @@ struct bucket { ref_counter ref_counter; size_t elt_count; - Hamt_entry *elts[FLEXIBLE_ARRAY_MEMBER]; + Hamt_entry *elts[FLEXIBLE_ARRAY_MEMBER] + _GL_ATTRIBUTE_COUNTED_BY (elt_count); }; /* A hamt consists of its function table and the root entry. */ -- 2.52.0
