From 074e16d58e6b78612c22ff611aa469ee929cc37f Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sun, 23 Nov 2025 06:48:19 +0100 Subject: [PATCH] compiler_types: introduce at_least parameter decoration pseudo keyword MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Clang and recent gcc support warning if they are able to prove that the user is passing to a function an array that is too short in size. For example: void blah(unsigned char herp[at_least 7]); static void schma(void) { unsigned char good[] = { 1, 2, 3, 4, 5, 6, 7 }; unsigned char bad[] = { 1, 2, 3, 4, 5, 6 }; blah(good); blah(bad); } The notation here, `static 7`, which this commit makes explicit by allowing us to write it as `at_least 7`, means that it's incorrect to pass anything less than 7 elements. This is section 6.7.5.3 of C99: If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression. Here is the output from gcc 15: zx2c4@thinkpad /tmp $ gcc -c a.c a.c: In function ‘schma’: a.c:9:9: warning: ‘blah’ accessing 7 bytes in a region of size 6 [-Wstringop-overflow=] 9 | blah(bad); | ^~~~~~~~~ a.c:9:9: note: referencing argument 1 of type ‘unsigned char[7]’ a.c:2:6: note: in a call to function ‘blah’ 2 | void blah(unsigned char herp[at_least 7]); | ^~~~ And from clang 21: zx2c4@thinkpad /tmp $ clang -c a.c a.c:9:2: warning: array argument is too small; contains 6 elements, callee requires at least 7 [-Warray-bounds] 9 | blah(bad); | ^ ~~~ a.c:2:25: note: callee declares array parameter as static here 2 | void blah(unsigned char herp[at_least 7]); | ^ ~~~~~~~~~~ 1 warning generated. So these are covered by, variously, -Wstringop-overflow and -Warray-bounds. Acked-by: Ard Biesheuvel Signed-off-by: "Jason A. Donenfeld" Link: https://lore.kernel.org/r/20251123054819.2371989-3-Jason@zx2c4.com Signed-off-by: Eric Biggers --- include/linux/compiler_types.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h index 59288a2c1ad27..51f0dccdb54d1 100644 --- a/include/linux/compiler_types.h +++ b/include/linux/compiler_types.h @@ -394,6 +394,21 @@ struct ftrace_likely_data { #define __counted_by_be(member) __counted_by(member) #endif +/* + * This designates the minimum number of elements a passed array parameter must + * have. For example: + * + * void some_function(u8 param[at_least 7]); + * + * If a caller passes an array with fewer than 7 elements, the compiler will + * emit a warning. + */ +#ifndef __CHECKER__ +#define at_least static +#else +#define at_least +#endif + /* Do not trap wrapping arithmetic within an annotated function. */ #ifdef CONFIG_UBSAN_INTEGER_WRAP # define __signed_wrap __attribute__((no_sanitize("signed-integer-overflow"))) -- 2.47.3