The strlen(p) function-like macro uses:

  __is_constexpr(__builtin_strlen(p))

in which GCC would only yield true if the argument p is a string
literal. Otherwise, GCC would return false even if p is a const
string.

In contrary, by using:

  __builtin_constant_p(__builtin_strlen(p))

then GCC can also recognizes when p is a compile time constant string.

The above is illustrated in [1].

N.B.: clang is not impacted by any of this and gives the same results
with either __is_constexpr() and __builting_constant_p().

Use __builtin_constant_p() instead of __is_constexpr() so that GCC can
do the folding on constant strings. This done, strlen() does not
require any more to be a function-like macro, so turn it into a static
inline function. In the process, __fortify_strlen() had to be moved
above strlen() so that it became visible to strlen().

On a side note, strlen() did a double expansion of its argument p.
Turning it into an inline function also resolved this side issue.

[1] https://godbolt.org/z/rqr3YvoP4

Signed-off-by: Vincent Mailhol <mailhol.vinc...@wanadoo.fr>
---
This patch is the successor of patch [1] which was part of a longer
series [2]. Meanwhile, I decided to split it, so I am sending this again,
but as a stand-alone patch.

Changelog since [1]: use __builtin_constant_p() instead and turn
strlen() into an inline function

[1] 
https://lore.kernel.org/all/20241203-is_constexpr-refactor-v1-6-4e4cbaecc...@wanadoo.fr/
[2] 
https://lore.kernel.org/all/20241203-is_constexpr-refactor-v1-0-4e4cbaecc...@wanadoo.fr/
---
 include/linux/fortify-string.h | 34 +++++++++++++++++++---------------
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h
index 
e4ce1cae03bf770047ce8a7c032b183683388cd5..bd22dd66e5f5b66ad839df42247e6436e0afd053
 100644
--- a/include/linux/fortify-string.h
+++ b/include/linux/fortify-string.h
@@ -4,7 +4,6 @@
 
 #include <linux/bitfield.h>
 #include <linux/bug.h>
-#include <linux/const.h>
 #include <linux/limits.h>
 
 #define __FORTIFY_INLINE extern __always_inline __gnu_inline __overloadable
@@ -241,6 +240,21 @@ __FORTIFY_INLINE __kernel_size_t strnlen(const char * 
const POS p, __kernel_size
  * possible for strlen() to be used on compile-time strings for use in
  * static initializers (i.e. as a constant expression).
  */
+__FORTIFY_INLINE __diagnose_as(__builtin_strlen, 1)
+__kernel_size_t __fortify_strlen(const char * const POS p)
+{
+       const size_t p_size = __member_size(p);
+       __kernel_size_t ret;
+
+       /* Give up if we don't know how large p is. */
+       if (p_size == SIZE_MAX)
+               return __underlying_strlen(p);
+       ret = strnlen(p, p_size);
+       if (p_size <= ret)
+               fortify_panic(FORTIFY_FUNC_strlen, FORTIFY_READ, p_size, ret + 
1, ret);
+       return ret;
+}
+
 /**
  * strlen - Return count of characters in a NUL-terminated string
  *
@@ -254,22 +268,12 @@ __FORTIFY_INLINE __kernel_size_t strnlen(const char * 
const POS p, __kernel_size
  * Returns number of characters in @p (NOT including the final NUL).
  *
  */
-#define strlen(p)                                                      \
-       __builtin_choose_expr(__is_constexpr(__builtin_strlen(p)),      \
-               __builtin_strlen(p), __fortify_strlen(p))
 __FORTIFY_INLINE __diagnose_as(__builtin_strlen, 1)
-__kernel_size_t __fortify_strlen(const char * const POS p)
+__kernel_size_t strlen(const char *p)
 {
-       const size_t p_size = __member_size(p);
-       __kernel_size_t ret;
-
-       /* Give up if we don't know how large p is. */
-       if (p_size == SIZE_MAX)
-               return __underlying_strlen(p);
-       ret = strnlen(p, p_size);
-       if (p_size <= ret)
-               fortify_panic(FORTIFY_FUNC_strlen, FORTIFY_READ, p_size, ret + 
1, ret);
-       return ret;
+       if (__builtin_constant_p(__builtin_strlen(p)))
+               return __builtin_strlen(p);
+       return __fortify_strlen(p);
 }
 
 /* Defined after fortified strnlen() to reuse it. */

---
base-commit: 9d89551994a430b50c4fffcb1e617a057fa76e20
change-id: 20250105-strlen_use_builtin_constant_p-515aca505ca4

Best regards,
-- 
Vincent Mailhol <mailhol.vinc...@wanadoo.fr>


Reply via email to