Re: [PATCH v2 1/2] string: Add strprefix(), and deprecate str_has_prefix()
From: Geert Uytterhoeven
Date: Thu Nov 05 2026 - 07:59:03 EST
Hi Alejandro,
On Thu, 5 Nov 2026 13:46:29, Alejandro Colomar wrote:
> As Bartosz reported, str_has_prefix() has a bug: it can't differentiate
> between an empty prefix matching an empty string from a non-matching
> prefix. This is a fundamental design flaw in this API, and not
> something that can be fixed.
>
> As always, this is a consequence of choosing sizes instead of pointers.
> Sizes are often the wrong choice. In this specific case, pointers are
> more capable of differentiating these cases, as NULL is a special
> sentinel value that doesn't need to overload a valid value.
>
> Let's implement strprefix(), a function that returns a pointer
> right after the prefix if found, and a null pointer if not found.
>
> We'll slowly migrate existing code from str_has_prefix() to strprefix().
>
> Reported-by: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxxxxxxxx>
> Cc: Andy Shevchenko <andy@xxxxxxxxxx>
> Signed-off-by: Alejandro Colomar <alx@xxxxxxxxxx>
Thanks for your patch!
> --- a/include/linux/string.h
> +++ b/include/linux/string.h
> @@ -545,16 +545,33 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
> sizeof(*(obj)) - offsetof(typeof(*(obj)), member)); \
> })
>
> +/**
> + * strprefix - string prefix
Naive me assumes this function must return the prefix of the string,
so IMO is it named badly.
> + * @s: The string to be tested
> + * @prefix: The string to see if @s starts with
> + *
> + * Returns:
> + * * @s+strlen(@prefix) if @s starts with @prefix
> + * * NULL if @s does not start with @prefix
> + */
> +static __always_inline char *strprefix(const char *s, const char *prefix)
This returns a non-const substring of the original const parameter, thus
allowing the caller to modify the original even when it is const.
While this is not uncommon behavior for existing standard string
helpers, I think it would be good to make new functions safer, by not
allowing to drop constness. Using _Generic() can be used to support
both const and non-const strings in a safe way.
> +{
> + size_t len = strlen(prefix);
> + return strncmp(s, prefix, len) == 0 ? (char *) s + len : NULL;
> +}
> +
> /**
> * str_has_prefix - Test if a string has a given prefix
> * @str: The string to test
> * @prefix: The string to see if @str starts with
> *
> + * DEPRECATED: Use strprefix()
> + *
> * A common way to test a prefix of a string is to do:
> * strncmp(str, prefix, sizeof(prefix) - 1)
> *
> * But this can lead to bugs due to typos, or if prefix is a pointer
> - * and not a constant. Instead use str_has_prefix().
> + * and not a constant. Instead use strprefix().
> *
> * Returns:
> * * strlen(@prefix) if @str starts with @prefix
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@xxxxxxxxxxxxxx
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds