Skip to content

Conversation

@bluetech
Copy link
Member

Since I've read about counted_by I wanted to try it, it seems to work as expected!

There are some preparatory commits, and the last commit contains the details.

@wismill I'll leave the decision whether to merge it to you. The main catch is that it requires some care that the len is always valid even during initialization (see commit for details). I see that CI already has a run with -fsanitize=undefined, so at least covered code should be safe (I fixed what it caught already), but uncovered code might not be.

The next commit wants to use utils.h in darray.h.

Signed-off-by: Ran Benita <[email protected]>
This is kind-of nice self-documentation, and can be utilized for static
analysis and dynamic buffer overflow protection (such as
`-fsanitize=bounds` and `__builtin_dynamic_object_size` used by
`_FORTIFY_SOURCE=3`).

Clang<19.1.0 and GCC<=15.2 only support `counted_by` on flexible array
members, not pointer fields as used in xkbcommon, therefore we need a
configure check that annotating pointer fields is supported, not merely
that the attribute exists.

Clang (unlike GCC) currently requires that the count field come before
the pointer field. They have a flag to
`-fexperimental-late-parse-attributes` to enable this, but since it's
experimental I don't want to pass it. So we need to reorder some fields.

Another needed code adaption is to ensure that the length field is
always correctly set *before* the array is accessed. So e.g. the
sequence "alloc buffer, assign, set length field" is changed to "alloc
buffer, set length field, assign", otherwise the dynamic bounds check
during assignment fails.

I have verified that it works well with `-fsanitize=undefined` by
inserting some out-of-bounds access to `keymap->keys` and seeing that it
goes undetected before and detected after.

See:
https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-counted_005fby-variable-attribute
https://www.gnu.org/software/libc/manual/html_node/Source-Fortification.html#Fortification-of-function-calls
https://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html#index-_005f_005fbuiltin_005fdynamic_005fobject_005fsize
https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html#index-fsanitize_003dbounds

Signed-off-by: Ran Benita <[email protected]>
@wismill
Copy link
Member

wismill commented Nov 28, 2025

Rebased after merging the independent commits in #939.

@wismill
Copy link
Member

wismill commented Nov 28, 2025

@bluetech that seems a very interesting feature. Are there any relevant runtime costs though?

@bluetech
Copy link
Member Author

bluetech commented Nov 28, 2025

@bluetech that seems a very interesting feature. Are there any relevant runtime costs though?

Good question. There is a performance overhead due to additional bounds checking when _FORTIFY_SOURCE=3 is used.

In bench/compile-keymap I don't see a measurable difference. I do see a ~3% difference in bench/compose.c. To "pay" for it, I sent #940.

For the benchmarking I used Arch Linux's default flags (importantly _FORTIFY_SOURCE=3 is set) on "AMD Ryzen AI 9 HX 370" CPU, clang version 21.1.5.

CFLAGS="-march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions \
        -Wp,-D_FORTIFY_SOURCE=3 -Wformat -Werror=format-security \
        -fstack-clash-protection -fcf-protection \
        -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"
LDFLAGS="-Wl,-O1 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now \
         -Wl,-z,pack-relative-relocs"
LTOFLAGS="-flto=auto"
exec meson setup \
  --prefix        /usr \
  --libexecdir    lib \
  --sbindir       bin \
  --buildtype     plain \
  --auto-features enabled \
  --wrap-mode     nodownload \
  -D              b_pie=true \
  -D              python.bytecompile=1 \
  "$@"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants