* [PATCH] builtin: implement __builtin_strlen() for constants
@ 2025-10-15 13:08 Dan Carpenter
2025-10-15 15:13 ` Linus Torvalds
0 siblings, 1 reply; 4+ messages in thread
From: Dan Carpenter @ 2025-10-15 13:08 UTC (permalink / raw)
To: linux-sparse; +Cc: Ricardo Ribalda, Kees Cook, linux-media
People are adding compile time asserts to check whether strings are
the expected length. In GCC and Clang strlen("foo") is expanded at
compile time so this works, but in Sparse it triggers a "bad constant
expression" warning. Implement expand_strlen() to handle string
literals.
Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
Link: https://lore.kernel.org/all/CANiDSCsBAq3Yx4ybarUb_1NkQ-bvfXvWqb-DfqXatkiYJFZWiQ@mail.gmail.com/
---
builtin.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/builtin.c b/builtin.c
index 3a29c3aec8a6..9e8fa5964b37 100644
--- a/builtin.c
+++ b/builtin.c
@@ -596,6 +596,28 @@ static struct symbol_op object_size_op = {
.expand = expand_object_size,
};
+static int expand_strlen(struct expression *expr, int cost)
+{
+ struct expression *arg = first_expression(expr->args);
+
+ if (!arg)
+ return UNSAFE;
+ if (arg->type == EXPR_SYMBOL)
+ arg = arg->symbol->initializer;
+ if (!arg || arg->type != EXPR_STRING || !arg->string->length)
+ return UNSAFE;
+
+ expr->flags |= CEF_SET_ICE;
+ expr->type = EXPR_VALUE;
+ expr->value = arg->string->length - 1;
+ expr->taint = 0;
+ return 0;
+}
+
+static struct symbol_op strlen_op = {
+ .expand = expand_strlen,
+};
+
/*
* Builtin functions
*/
@@ -775,7 +797,7 @@ static const struct builtin_fn builtins_common[] = {
{ "__builtin_strcpy", &string_ctype, 0, { &string_ctype, &const_string_ctype }},
{ "__builtin_strcspn", size_t_ctype, 0, { &const_string_ctype, &const_string_ctype }},
{ "__builtin_strdup", &string_ctype, 0, { &const_string_ctype }},
- { "__builtin_strlen", size_t_ctype, 0, { &const_string_ctype }},
+ { "__builtin_strlen", size_t_ctype, 0, { &const_string_ctype }, .op = &strlen_op},
{ "__builtin_strncasecmp", &int_ctype, 0, { &const_string_ctype, &const_string_ctype, size_t_ctype }},
{ "__builtin_strncat", &string_ctype, 0, { &string_ctype, &const_string_ctype, size_t_ctype }},
{ "__builtin_strncmp", &int_ctype, 0, { &const_string_ctype, &const_string_ctype, size_t_ctype }},
--
2.51.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] builtin: implement __builtin_strlen() for constants
2025-10-15 13:08 [PATCH] builtin: implement __builtin_strlen() for constants Dan Carpenter
@ 2025-10-15 15:13 ` Linus Torvalds
2025-10-16 8:29 ` Dan Carpenter
0 siblings, 1 reply; 4+ messages in thread
From: Linus Torvalds @ 2025-10-15 15:13 UTC (permalink / raw)
To: Dan Carpenter; +Cc: linux-sparse, Ricardo Ribalda, Kees Cook, linux-media
On Wed, 15 Oct 2025 at 06:09, Dan Carpenter <dan.carpenter@linaro.org> wrote:
>
> People are adding compile time asserts to check whether strings are
> the expected length. In GCC and Clang strlen("foo") is expanded at
> compile time so this works, but in Sparse it triggers a "bad constant
> expression" warning. Implement expand_strlen() to handle string
> literals.
Ack.
Except it's not quite right.
Try this:
int i(void)
{
return __builtin_strlen("hello\0hi");
}
and you'll see that it returns 8, even though the correct string length is 5.
So you should add a
#include <string.h>
at the top, and do something like
- expr->value = arg->string->length - 1;
+ expr->value = strlen(arg->string->data);
in there instead, because constant strings can have embedded NUL characters.
Linus
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] builtin: implement __builtin_strlen() for constants
2025-10-15 15:13 ` Linus Torvalds
@ 2025-10-16 8:29 ` Dan Carpenter
2025-10-16 12:05 ` Chris Li
0 siblings, 1 reply; 4+ messages in thread
From: Dan Carpenter @ 2025-10-16 8:29 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-sparse, Ricardo Ribalda, Kees Cook, linux-media
On Wed, Oct 15, 2025 at 08:13:51AM -0700, Linus Torvalds wrote:
> So you should add a
>
> #include <string.h>
>
> at the top, and do something like
>
> - expr->value = arg->string->length - 1;
> + expr->value = strlen(arg->string->data);
>
> in there instead, because constant strings can have embedded NUL characters.
>
> Linus
Ah. Thanks.
regards,
dan carpenter
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] builtin: implement __builtin_strlen() for constants
2025-10-16 8:29 ` Dan Carpenter
@ 2025-10-16 12:05 ` Chris Li
0 siblings, 0 replies; 4+ messages in thread
From: Chris Li @ 2025-10-16 12:05 UTC (permalink / raw)
To: Dan Carpenter
Cc: Linus Torvalds, linux-sparse, Ricardo Ribalda, Kees Cook,
linux-media
Thanks,
Will apply with Linus' fix up.
Chris
On Thu, Oct 16, 2025 at 1:29 AM Dan Carpenter <dan.carpenter@linaro.org> wrote:
>
> On Wed, Oct 15, 2025 at 08:13:51AM -0700, Linus Torvalds wrote:
> > So you should add a
> >
> > #include <string.h>
> >
> > at the top, and do something like
> >
> > - expr->value = arg->string->length - 1;
> > + expr->value = strlen(arg->string->data);
> >
> > in there instead, because constant strings can have embedded NUL characters.
> >
> > Linus
>
> Ah. Thanks.
>
> regards,
> dan carpenter
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-10-16 12:05 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-15 13:08 [PATCH] builtin: implement __builtin_strlen() for constants Dan Carpenter
2025-10-15 15:13 ` Linus Torvalds
2025-10-16 8:29 ` Dan Carpenter
2025-10-16 12:05 ` Chris Li
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).