mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v3 0/5] Add strprefix() and fix a bug with it
@ 2026-11-10 15:33 Alejandro Colomar
  2026-11-10 15:33 ` [PATCH v3 1/5] string: Add strprefix(), and deprecate str_has_prefix() Alejandro Colomar
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Alejandro Colomar @ 2026-11-10 15:33 UTC (permalink / raw)
  To: linux-hardening
  Cc: Krzysztof Kozlowski, Maciej W. Rozycki, Geert Uytterhoeven,
	Alejandro Colomar, Andreas Schwab, Andy Shevchenko,
	Bartosz Golaszewski, Daniel Scally, Danilo Krummrich,
	Greg Kroah-Hartman, Hans Verkuil, Heikki Krogerus, Joe Perches,
	Johan Hovold, Kees Cook, Laurent Pinchart, Len Brown,
	Linus Torvalds, Linus Walleij, Namhyung Kim, Rafael J. Wysocki,
	Rob Herring, Sakari Ailus, Saravana Kannan, Steven Rostedt,
	Tom Zanussi, linux-acpi, driver-core, linux-kernel, devicetree,
	linux-gpio

[-- Attachment #1: Type: text/plain, Size: 6762 bytes --]

Hi!

str_has_prefix() is based on sizes and lengths, which means it must
overload the valid length 0 to mean not found.  This is a typical
consequence of choosing to design an API around sizes and lengths, and
vanishes when moving to pointer-based similar APIs.

According to its author (Steven R.), str_has_prefix() was never meant to
accept an empty prefix, but that's not documented, and there's no
obvious reason why that would be acceptable for a generic string
function (as opposed to a function very specific to its original use).
Users of strings need a function whose behavior extends naturally to the
empty string, and we can do better, by returning a pointer.  And indeed,
users have ended up using str_has_prefix() with empty prefix, expecting
it to work (as is natural of a generic string API).

This patch set adds strprefix(), deprecates str_has_prefix(), and uses
strprefix() in one place to fix a bug reported by Bartosz.

We can later work on replacing the other uses of str_has_prefix(), which
might hide similar bugs.

This patch set also adds infrastructure to make string functions return
a pointer that is as qualified as the input pointer.

Changes in v2
~~~~~~~~~~~~~

-  Copy the description from str_has_prefix().  [Steve]
-  Add links for the Reported-by tags.
-  Make these APIs const-generic.  [Geert]

I didn't apply some changes requested by reviewers:

-  I didn't remove the deprecation of str_has_prefix(), because I think
   it should not be used in new code.  It remains useful for code that
   is already using it, because rewriting all the surrounding code to
   use pointers instead of offsets might be too risky.  However, for new
   code, strprefix() produces simpler code, and is safer, so I don't see
   why str_has_prefix() would be good in any new code.

-  I didn't rename strprefix() to strsuffix(), because that name would
   be worse (strsuffix() is widely implemented with other semantics, and
   having it different here would lead to confusion and bugs).  Andy
   agreed.

See range-diff below.

Testing
~~~~~~~

I haven't changed the implementation of the function, so haven't re-run
tests.  Since the changes since v2 are only about type safety, with a
new wrapper macro, I have built again with 'allmodconfig', just to make
sure it still compiles.


Have a lovely day!
Alex

v1: <https://lore.kernel.org/linux-hardening/cover.1793876837.git.alx@kernel.org/>
v2: <https://lore.kernel.org/linux-hardening/cover.1793882260.git.alx@kernel.org/>

Alejandro Colomar (5):
  string: Add strprefix(), and deprecate str_has_prefix()
  device property: Fix fwnode_name_eq() for empty node names
  stddef: Add const_cast()
  string: Add [C]QChar_of() and QVoid_of()
  string: Make strprefix() const-qualifier-generic

 drivers/base/property.c  |  5 +---
 include/linux/stddef.h   | 12 ++++++++
 include/linux/string.h   | 63 +++++++++++++++++++++++++++++++++++++---
 lib/tests/string_kunit.c |  9 ++++++
 4 files changed, 81 insertions(+), 8 deletions(-)

Range-diff against v2:
1:  d3b325ecefd1 ! 1:  556766412884 string: Add strprefix(), and deprecate str_has_prefix()
    @@ Commit message
     
         We'll slowly migrate existing code from str_has_prefix() to strprefix().
     
    +    Copy the description from str_has_prefix().
    +
         Reported-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
    +    Link: https://lore.kernel.org/linux-hardening/20261104-fwnode-for-each-prop-v1-1-6e28fe1c72c4@oss.qualcomm.com/
         Cc: Andy Shevchenko <andy@kernel.org>
         Signed-off-by: Alejandro Colomar <alx@kernel.org>
     
      ## include/linux/string.h ##
     @@ include/linux/string.h: void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
    - 	       sizeof(*(obj)) - offsetof(typeof(*(obj)), member));	\
      })
      
    -+/**
    + /**
    +- * 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
     + * strprefix - string prefix
     + * @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)
    -+{
    -+	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:
    ++ * *  @s+strlen(@prefix) if @s starts with @prefix
    ++ * *  NULL if @s does not start with @prefix
    ++ */
    ++static inline char *strprefix(const char *s, const char *prefix)
    ++{
    ++	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 strprefix().
       *
       * Returns:
2:  ac9728afa027 ! 2:  eed085c85f36 device property: Fix fwnode_name_eq() for empty node names
    @@ Commit message
     
         Fixes: a9c8c738066b7 ("device property: Add fwnode_name_eq()")
         Reported-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
    +    Link: https://lore.kernel.org/linux-hardening/20261104-fwnode-for-each-prop-v1-1-6e28fe1c72c4@oss.qualcomm.com/
         Cc: Andy Shevchenko <andy@kernel.org>
         Signed-off-by: Alejandro Colomar <alx@kernel.org>
     
-:  ------------ > 3:  2bf5cf7baad8 stddef: Add const_cast()
-:  ------------ > 4:  415453a31ebf string: Add [C]QChar_of() and QVoid_of()
-:  ------------ > 5:  35bf6672f84f string: Make strprefix() const-qualifier-generic
-- 
2.55.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v3 1/5] string: Add strprefix(), and deprecate str_has_prefix()
  2026-11-10 15:33 [PATCH v3 0/5] Add strprefix() and fix a bug with it Alejandro Colomar
@ 2026-11-10 15:33 ` Alejandro Colomar
  2026-11-10 15:47   ` Joe Perches
  2026-11-10 15:33 ` [PATCH v3 2/5] device property: Fix fwnode_name_eq() for empty node names Alejandro Colomar
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: Alejandro Colomar @ 2026-11-10 15:33 UTC (permalink / raw)
  To: linux-hardening
  Cc: Krzysztof Kozlowski, Maciej W. Rozycki, Geert Uytterhoeven,
	Alejandro Colomar, Andreas Schwab, Andy Shevchenko,
	Bartosz Golaszewski, Daniel Scally, Danilo Krummrich,
	Greg Kroah-Hartman, Hans Verkuil, Heikki Krogerus, Joe Perches,
	Johan Hovold, Kees Cook, Laurent Pinchart, Len Brown,
	Linus Torvalds, Linus Walleij, Namhyung Kim, Rafael J. Wysocki,
	Rob Herring, Sakari Ailus, Saravana Kannan, Steven Rostedt,
	Tom Zanussi, linux-acpi, driver-core, linux-kernel, devicetree,
	linux-gpio, Bartosz Golaszewski

[-- Attachment #1: Type: text/plain, Size: 3877 bytes --]

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().

Copy the description from str_has_prefix().

Reported-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Link: https://lore.kernel.org/linux-hardening/20261104-fwnode-for-each-prop-v1-1-6e28fe1c72c4@oss.qualcomm.com/
Cc: Andy Shevchenko <andy@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
---
 include/linux/string.h   | 31 +++++++++++++++++++++++++++----
 lib/tests/string_kunit.c |  9 +++++++++
 2 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/include/linux/string.h b/include/linux/string.h
index 6cb5cdd01158..12e31c17f0d3 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -546,15 +546,38 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
 })
 
 /**
- * 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
+ * strprefix - string prefix
+ * @s: The string to be tested
+ * @prefix: The string to see if @s starts with
  *
  * 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:
+ * *  @s+strlen(@prefix) if @s starts with @prefix
+ * *  NULL if @s does not start with @prefix
+ */
+static inline char *strprefix(const char *s, const char *prefix)
+{
+	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 strprefix().
  *
  * Returns:
  * * strlen(@prefix) if @str starts with @prefix
diff --git a/lib/tests/string_kunit.c b/lib/tests/string_kunit.c
index 0819ace5b027..73d2614b1474 100644
--- a/lib/tests/string_kunit.c
+++ b/lib/tests/string_kunit.c
@@ -287,6 +287,14 @@ static void string_test_strspn(struct kunit *test)
 	}
 }
 
+static void string_test_strprefix(struct kunit *test)
+{
+	KUNIT_ASSERT_EQ(test, 0, strcmp(strprefix("foobar", "foo"), "bar"));
+	KUNIT_ASSERT_EQ(test, 0, strcmp(strprefix("foobar", ""), "foobar"));
+	KUNIT_ASSERT_EQ(test, 0, strcmp(strprefix("foobar", "foobar"), ""));
+	KUNIT_ASSERT_NULL(test, strprefix("foobar", "bar"));
+}
+
 static char strcmp_buffer1[STRCMP_LARGE_BUF_LEN];
 static char strcmp_buffer2[STRCMP_LARGE_BUF_LEN];
 
@@ -891,6 +899,7 @@ static struct kunit_case string_test_cases[] = {
 	KUNIT_CASE(string_test_strnchr),
 	KUNIT_CASE(string_test_strrchr),
 	KUNIT_CASE(string_test_strspn),
+	KUNIT_CASE(string_test_strprefix),
 	KUNIT_CASE(string_test_strcmp),
 	KUNIT_CASE(string_test_strcmp_long_strings),
 	KUNIT_CASE(string_test_strncmp),
-- 
2.55.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v3 2/5] device property: Fix fwnode_name_eq() for empty node names
  2026-11-10 15:33 [PATCH v3 0/5] Add strprefix() and fix a bug with it Alejandro Colomar
  2026-11-10 15:33 ` [PATCH v3 1/5] string: Add strprefix(), and deprecate str_has_prefix() Alejandro Colomar
@ 2026-11-10 15:33 ` Alejandro Colomar
  2026-11-10 15:33 ` [PATCH v3 3/5] stddef: Add const_cast() Alejandro Colomar
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Alejandro Colomar @ 2026-11-10 15:33 UTC (permalink / raw)
  To: linux-hardening
  Cc: Krzysztof Kozlowski, Maciej W. Rozycki, Geert Uytterhoeven,
	Alejandro Colomar, Andreas Schwab, Andy Shevchenko,
	Bartosz Golaszewski, Daniel Scally, Danilo Krummrich,
	Greg Kroah-Hartman, Hans Verkuil, Heikki Krogerus, Joe Perches,
	Johan Hovold, Kees Cook, Laurent Pinchart, Len Brown,
	Linus Torvalds, Linus Walleij, Namhyung Kim, Rafael J. Wysocki,
	Rob Herring, Sakari Ailus, Saravana Kannan, Steven Rostedt,
	Tom Zanussi, linux-acpi, driver-core, linux-kernel, devicetree,
	linux-gpio, Bartosz Golaszewski

[-- Attachment #1: Type: text/plain, Size: 1549 bytes --]

str_has_prefix() returns the prefix length on match and 0 on mismatch,
so the mistmatch case can't be told from "empty prefix matched an empty
string".

For instance: the OF root node's name as returned by
fwnode_get_name() is "" and will return 0 for any name matched against
it and since len is 0 too, fwnode_name_eq() will return true.

Let's use strprefix() instead, which also makes this function simpler.

Fixes: a9c8c738066b7 ("device property: Add fwnode_name_eq()")
Reported-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Link: https://lore.kernel.org/linux-hardening/20261104-fwnode-for-each-prop-v1-1-6e28fe1c72c4@oss.qualcomm.com/
Cc: Andy Shevchenko <andy@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
---
 drivers/base/property.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index 51109794d727..7728116e2968 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -692,15 +692,12 @@ const char *fwnode_get_name_prefix(const struct fwnode_handle *fwnode)
 bool fwnode_name_eq(const struct fwnode_handle *fwnode, const char *name)
 {
 	const char *node_name;
-	ptrdiff_t len;
 
 	node_name = fwnode_get_name(fwnode);
 	if (!node_name)
 		return false;
 
-	len = strchrnul(node_name, '@') - node_name;
-
-	return str_has_prefix(node_name, name) == len;
+	return strprefix(node_name, name) == strchrnul(node_name, '@');
 }
 EXPORT_SYMBOL_GPL(fwnode_name_eq);
 
-- 
2.55.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v3 3/5] stddef: Add const_cast()
  2026-11-10 15:33 [PATCH v3 0/5] Add strprefix() and fix a bug with it Alejandro Colomar
  2026-11-10 15:33 ` [PATCH v3 1/5] string: Add strprefix(), and deprecate str_has_prefix() Alejandro Colomar
  2026-11-10 15:33 ` [PATCH v3 2/5] device property: Fix fwnode_name_eq() for empty node names Alejandro Colomar
@ 2026-11-10 15:33 ` Alejandro Colomar
  2026-11-10 15:33 ` [PATCH v3 4/5] string: Add [C]QChar_of() and QVoid_of() Alejandro Colomar
  2026-11-10 15:33 ` [PATCH v3 5/5] string: Make strprefix() const-qualifier-generic Alejandro Colomar
  4 siblings, 0 replies; 9+ messages in thread
From: Alejandro Colomar @ 2026-11-10 15:33 UTC (permalink / raw)
  To: linux-hardening
  Cc: Krzysztof Kozlowski, Maciej W. Rozycki, Geert Uytterhoeven,
	Alejandro Colomar, Andreas Schwab, Andy Shevchenko,
	Bartosz Golaszewski, Daniel Scally, Danilo Krummrich,
	Greg Kroah-Hartman, Hans Verkuil, Heikki Krogerus, Joe Perches,
	Johan Hovold, Kees Cook, Laurent Pinchart, Len Brown,
	Linus Torvalds, Linus Walleij, Namhyung Kim, Rafael J. Wysocki,
	Rob Herring, Sakari Ailus, Saravana Kannan, Steven Rostedt,
	Tom Zanussi, linux-acpi, driver-core, linux-kernel, devicetree,
	linux-gpio

[-- Attachment #1: Type: text/plain, Size: 1125 bytes --]

This macro serves to cast const away without risking unwanted
conversions due to mistakes in the cast.

It's similar to C++'s const_cast(), but it is more restrictive: it can
only cast away 'const', and not arbitrary qualifiers.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
---
 include/linux/stddef.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/include/linux/stddef.h b/include/linux/stddef.h
index e1851c50c89b..d79a81406b78 100644
--- a/include/linux/stddef.h
+++ b/include/linux/stddef.h
@@ -194,4 +194,16 @@ enum {
 #define TRAILING_OVERLAP(TYPE, NAME, FAM, MEMBERS)				\
 	__TRAILING_OVERLAP(TYPE, NAME, FAM, /* no attrs */, MEMBERS)
 
+/**
+ * const_cast() - Drop const in the left-most derivation of a pointer
+ *
+ * @T: Type for the cast.
+ * @p: Pointer to be casted.
+ *
+ * If @p is of type const @T, then it is casted to @T.
+ * Otherwise, @p is returned without any casts.
+ * This avoids mistakes that change anything other than 'const' in a cast.
+ */
+#define const_cast(T, p)  _Generic(p, const T: (T) (p), default: (p))
+
 #endif
-- 
2.55.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v3 4/5] string: Add [C]QChar_of() and QVoid_of()
  2026-11-10 15:33 [PATCH v3 0/5] Add strprefix() and fix a bug with it Alejandro Colomar
                   ` (2 preceding siblings ...)
  2026-11-10 15:33 ` [PATCH v3 3/5] stddef: Add const_cast() Alejandro Colomar
@ 2026-11-10 15:33 ` Alejandro Colomar
  2026-11-10 15:33 ` [PATCH v3 5/5] string: Make strprefix() const-qualifier-generic Alejandro Colomar
  4 siblings, 0 replies; 9+ messages in thread
From: Alejandro Colomar @ 2026-11-10 15:33 UTC (permalink / raw)
  To: linux-hardening
  Cc: Krzysztof Kozlowski, Maciej W. Rozycki, Geert Uytterhoeven,
	Alejandro Colomar, Andreas Schwab, Andy Shevchenko,
	Bartosz Golaszewski, Daniel Scally, Danilo Krummrich,
	Greg Kroah-Hartman, Hans Verkuil, Heikki Krogerus, Joe Perches,
	Johan Hovold, Kees Cook, Laurent Pinchart, Len Brown,
	Linus Torvalds, Linus Walleij, Namhyung Kim, Rafael J. Wysocki,
	Rob Herring, Sakari Ailus, Saravana Kannan, Steven Rostedt,
	Tom Zanussi, linux-acpi, driver-core, linux-kernel, devicetree,
	linux-gpio

[-- Attachment #1: Type: text/plain, Size: 1784 bytes --]

These macros serve to implement qualifier-generic macros as those
specified in ISO C23.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
---
 include/linux/string.h | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/include/linux/string.h b/include/linux/string.h
index 12e31c17f0d3..9e59f9697c9e 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -14,6 +14,36 @@
 #include <linux/stdarg.h>
 #include <uapi/linux/string.h>
 
+/**
+ * QVoid_of - qualified void of
+ *
+ * @p: Pointer to test for qualifiers
+ *
+ * This macro produces the type name 'void',
+ * qualified with any qualifiers present in the element of @p.
+ */
+#define QVoid_of(p)       typeof((__QVoidptr_of(p)){0}[0])
+#define __QVoidptr_of(p)  typeof(1?(p):(void*){0})
+
+/**
+ * QChar_of - qualified char of
+ *
+ * @Q: Qualifier to test.
+ * @p: Pointer to test for the @Q qualifier
+ *
+ * This macro produces the type name 'char',
+ * @Q-qualified iff the input pointer points to a @Q-qualified element.
+ */
+#define QChar_of(Q, p)  typeof                                        \
+(                                                                     \
+	_Generic((QVoid_of(p) *){0},                                  \
+		Q void *:  (Q char){0},                               \
+		void *:    (  char){0}                                \
+	)                                                             \
+)
+// CQChar_of - const qualified char of
+#define CQChar_of(p)  QChar_of(const, p)
+
 extern char *strndup_user(const char __user *, long);
 extern void *memdup_user(const void __user *, size_t) __realloc_size(2);
 extern void *vmemdup_user(const void __user *, size_t) __realloc_size(2);
-- 
2.55.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v3 5/5] string: Make strprefix() const-qualifier-generic
  2026-11-10 15:33 [PATCH v3 0/5] Add strprefix() and fix a bug with it Alejandro Colomar
                   ` (3 preceding siblings ...)
  2026-11-10 15:33 ` [PATCH v3 4/5] string: Add [C]QChar_of() and QVoid_of() Alejandro Colomar
@ 2026-11-10 15:33 ` Alejandro Colomar
  2026-11-10 16:32   ` Joe Perches
  4 siblings, 1 reply; 9+ messages in thread
From: Alejandro Colomar @ 2026-11-10 15:33 UTC (permalink / raw)
  To: linux-hardening
  Cc: Krzysztof Kozlowski, Maciej W. Rozycki, Geert Uytterhoeven,
	Alejandro Colomar, Andreas Schwab, Andy Shevchenko,
	Bartosz Golaszewski, Daniel Scally, Danilo Krummrich,
	Greg Kroah-Hartman, Hans Verkuil, Heikki Krogerus, Joe Perches,
	Johan Hovold, Kees Cook, Laurent Pinchart, Len Brown,
	Linus Torvalds, Linus Walleij, Namhyung Kim, Rafael J. Wysocki,
	Rob Herring, Sakari Ailus, Saravana Kannan, Steven Rostedt,
	Tom Zanussi, linux-acpi, driver-core, linux-kernel, devicetree,
	linux-gpio

[-- Attachment #1: Type: text/plain, Size: 899 bytes --]

Suggested-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
---
 include/linux/string.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/include/linux/string.h b/include/linux/string.h
index 9e59f9697c9e..55ca4cb5122c 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -590,7 +590,9 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
  * *  @s+strlen(@prefix) if @s starts with @prefix
  * *  NULL if @s does not start with @prefix
  */
-static inline char *strprefix(const char *s, const char *prefix)
+#define strprefix(s, pfx)  const_cast(CQChar_of(s) *, strprefix(s, pfx))
+
+static inline char *(strprefix)(const char *s, const char *prefix)
 {
 	size_t len = strlen(prefix);
 	return strncmp(s, prefix, len) == 0 ? (char *) s + len : NULL;
-- 
2.55.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 1/5] string: Add strprefix(), and deprecate str_has_prefix()
  2026-11-10 15:33 ` [PATCH v3 1/5] string: Add strprefix(), and deprecate str_has_prefix() Alejandro Colomar
@ 2026-11-10 15:47   ` Joe Perches
  2026-11-10 16:14     ` Alejandro Colomar
  0 siblings, 1 reply; 9+ messages in thread
From: Joe Perches @ 2026-11-10 15:47 UTC (permalink / raw)
  To: Alejandro Colomar, linux-hardening
  Cc: Krzysztof Kozlowski, Maciej W. Rozycki, Geert Uytterhoeven,
	Andreas Schwab, Andy Shevchenko, Bartosz Golaszewski,
	Daniel Scally, Danilo Krummrich, Greg Kroah-Hartman,
	Hans Verkuil, Heikki Krogerus, Johan Hovold, Kees Cook,
	Laurent Pinchart, Len Brown, Linus Torvalds, Linus Walleij,
	Namhyung Kim, Rafael J. Wysocki, Rob Herring, Sakari Ailus,
	Saravana Kannan, Steven Rostedt, Tom Zanussi, linux-acpi,
	driver-core, linux-kernel, devicetree, linux-gpio,
	Bartosz Golaszewski

On Tue, 2026-11-10 at 16:33 +0100, 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().

Most uses of str_has_prefix could use the existing strstarts.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 1/5] string: Add strprefix(), and deprecate str_has_prefix()
  2026-11-10 15:47   ` Joe Perches
@ 2026-11-10 16:14     ` Alejandro Colomar
  0 siblings, 0 replies; 9+ messages in thread
From: Alejandro Colomar @ 2026-11-10 16:14 UTC (permalink / raw)
  To: Joe Perches
  Cc: Alejandro Colomar, linux-hardening, Krzysztof Kozlowski,
	Maciej W. Rozycki, Geert Uytterhoeven, Andreas Schwab,
	Andy Shevchenko, Bartosz Golaszewski, Daniel Scally,
	Danilo Krummrich, Greg Kroah-Hartman, Hans Verkuil,
	Heikki Krogerus, Johan Hovold, Kees Cook, Laurent Pinchart,
	Len Brown, Linus Torvalds, Linus Walleij, Namhyung Kim,
	Rafael J. Wysocki, Rob Herring, Sakari Ailus, Saravana Kannan,
	Steven Rostedt, Tom Zanussi, linux-acpi, driver-core,
	linux-kernel, devicetree, linux-gpio, Bartosz Golaszewski

[-- Attachment #1: Type: text/plain, Size: 1322 bytes --]

Hi Joe,

> Date: 2026-11-10 07:47:55-0800
> From: Joe Perches <joe@perches.com>
>
> On Tue, 2026-11-10 at 16:33 +0100, 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().
> 
> Most uses of str_has_prefix could use the existing strstarts.

Hmmm, actually, both str_has_prefix() and strstarts() can be replaced by
strprefix(), which provides functionality for both use cases.  It's the
more generic API for this.  And I expect compilers can optimize the
unused parts if actually unused.


Have a lovely day!
Alex

-- 
<https://www.alejandro-colomar.es>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 5/5] string: Make strprefix() const-qualifier-generic
  2026-11-10 15:33 ` [PATCH v3 5/5] string: Make strprefix() const-qualifier-generic Alejandro Colomar
@ 2026-11-10 16:32   ` Joe Perches
  0 siblings, 0 replies; 9+ messages in thread
From: Joe Perches @ 2026-11-10 16:32 UTC (permalink / raw)
  To: Alejandro Colomar, linux-hardening
  Cc: Krzysztof Kozlowski, Maciej W. Rozycki, Geert Uytterhoeven,
	Andreas Schwab, Andy Shevchenko, Bartosz Golaszewski,
	Daniel Scally, Danilo Krummrich, Greg Kroah-Hartman,
	Hans Verkuil, Heikki Krogerus, Johan Hovold, Kees Cook,
	Laurent Pinchart, Len Brown, Linus Torvalds, Linus Walleij,
	Namhyung Kim, Rafael J. Wysocki, Rob Herring, Sakari Ailus,
	Saravana Kannan, Steven Rostedt, Tom Zanussi, linux-acpi,
	driver-core, linux-kernel, devicetree, linux-gpio

On Tue, 2026-11-10 at 16:33 +0100, Alejandro Colomar wrote:

no commit description on proposed patch

> Suggested-by: Geert Uytterhoeven <geert@linux-m68k.org>
> Signed-off-by: Alejandro Colomar <alx@kernel.org>
> ---
>  include/linux/string.h | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/string.h b/include/linux/string.h
> index 9e59f9697c9e..55ca4cb5122c 100644
> --- a/include/linux/string.h
> +++ b/include/linux/string.h
> @@ -590,7 +590,9 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
>   * *  @s+strlen(@prefix) if @s starts with @prefix
>   * *  NULL if @s does not start with @prefix
>   */
> -static inline char *strprefix(const char *s, const char *prefix)
> +#define strprefix(s, pfx)  const_cast(CQChar_of(s) *, strprefix(s, pfx))
> +
> +static inline char *(strprefix)(const char *s, const char *prefix)

Why introduce a new coding style?

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-11-10 16:32 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-10 15:33 [PATCH v3 0/5] Add strprefix() and fix a bug with it Alejandro Colomar
2026-11-10 15:33 ` [PATCH v3 1/5] string: Add strprefix(), and deprecate str_has_prefix() Alejandro Colomar
2026-11-10 15:47   ` Joe Perches
2026-11-10 16:14     ` Alejandro Colomar
2026-11-10 15:33 ` [PATCH v3 2/5] device property: Fix fwnode_name_eq() for empty node names Alejandro Colomar
2026-11-10 15:33 ` [PATCH v3 3/5] stddef: Add const_cast() Alejandro Colomar
2026-11-10 15:33 ` [PATCH v3 4/5] string: Add [C]QChar_of() and QVoid_of() Alejandro Colomar
2026-11-10 15:33 ` [PATCH v3 5/5] string: Make strprefix() const-qualifier-generic Alejandro Colomar
2026-11-10 16:32   ` Joe Perches

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®