linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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).