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; 16+ 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] 16+ 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-11  8:43   ` Steven Rostedt
  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, 2 replies; 16+ 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] 16+ 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; 16+ 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] 16+ 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-11 10:25   ` David Laight
  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, 1 reply; 16+ 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] 16+ 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; 16+ 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] 16+ 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
  2026-11-11 10:34   ` David Laight
  4 siblings, 2 replies; 16+ 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] 16+ 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
  2026-11-11  8:43   ` Steven Rostedt
  1 sibling, 1 reply; 16+ 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] 16+ 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; 16+ 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] 16+ 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
  2026-11-10 23:27     ` Alejandro Colomar
  2026-11-11 10:34   ` David Laight
  1 sibling, 1 reply; 16+ 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] 16+ messages in thread

* Re: [PATCH v3 5/5] string: Make strprefix() const-qualifier-generic
  2026-11-10 16:32   ` Joe Perches
@ 2026-11-10 23:27     ` Alejandro Colomar
  2026-11-11 10:28       ` David Laight
  0 siblings, 1 reply; 16+ messages in thread
From: Alejandro Colomar @ 2026-11-10 23:27 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

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

Hi Joe,

> Date: 2026-11-10 08:32:41-0800
> From: Joe Perches <joe@perches.com>
>
> On Tue, 2026-11-10 at 16:33 +0100, Alejandro Colomar wrote:
> 
> no commit description on proposed patch

There isn't much to say, but I'll add something (the explanation of why
the parentheses are needed around the function name, for example).

> > 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?

It's not style; the parentheses are technically needed to avoid macro
expansion, since the macro has the same name as the function.

Alternatively, I could rename the function to __strprefix().


Have a lovely night!
Alex

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

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

^ permalink raw reply	[flat|nested] 16+ 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-11  8:43   ` Steven Rostedt
  1 sibling, 0 replies; 16+ messages in thread
From: Steven Rostedt @ 2026-11-11  8:43 UTC (permalink / raw)
  To: Alejandro Colomar
  Cc: 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, 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, Tom Zanussi,
	linux-acpi, driver-core, linux-kernel, devicetree, linux-gpio,
	Bartosz Golaszewski

On Tue, 10 Nov 2026 16:33:23 +0100
Alejandro Colomar <alx@kernel.org> wrote:

> +/**
> + * 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()

I'm still not convinced, so NAK on this part.

-- Steve


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

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

* Re: [PATCH v3 3/5] stddef: Add const_cast()
  2026-11-10 15:33 ` [PATCH v3 3/5] stddef: Add const_cast() Alejandro Colomar
@ 2026-11-11 10:25   ` David Laight
  2026-11-11 10:51     ` Alejandro Colomar
  0 siblings, 1 reply; 16+ messages in thread
From: David Laight @ 2026-11-11 10:25 UTC (permalink / raw)
  To: Alejandro Colomar
  Cc: 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, 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

On Tue, 10 Nov 2026 16:33:40 +0100
Alejandro Colomar <alx@kernel.org> wrote:

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

Should it be de_const_cast(), or just de_const().
It is a shame you need to specify the type, but why not:
	_Generic(p, T: p, const T: (T)(p))
so that you get a compile time error from the _Generic() if the type
is wrong.

David


> +
>  #endif


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

* Re: [PATCH v3 5/5] string: Make strprefix() const-qualifier-generic
  2026-11-10 23:27     ` Alejandro Colomar
@ 2026-11-11 10:28       ` David Laight
  2026-11-11 10:59         ` Alejandro Colomar
  0 siblings, 1 reply; 16+ messages in thread
From: David Laight @ 2026-11-11 10:28 UTC (permalink / raw)
  To: Alejandro Colomar
  Cc: Joe Perches, 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

On Wed, 11 Nov 2026 00:27:28 +0100
Alejandro Colomar <alx+linux-hardening@kernel.org> wrote:

> Hi Joe,
> 
> > Date: 2026-11-10 08:32:41-0800
> > From: Joe Perches <joe@perches.com>
> >
> > On Tue, 2026-11-10 at 16:33 +0100, Alejandro Colomar wrote:
> > 
> > no commit description on proposed patch  
> 
> There isn't much to say, but I'll add something (the explanation of why
> the parentheses are needed around the function name, for example).
> 
> > > 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?  
> 
> It's not style; the parentheses are technically needed to avoid macro
> expansion, since the macro has the same name as the function.
> 
> Alternatively, I could rename the function to __strprefix().

Or put the #define after the function definition.

David

> 
> 
> Have a lovely night!
> Alex
> 


^ permalink raw reply	[flat|nested] 16+ 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
@ 2026-11-11 10:34   ` David Laight
  1 sibling, 0 replies; 16+ messages in thread
From: David Laight @ 2026-11-11 10:34 UTC (permalink / raw)
  To: Alejandro Colomar
  Cc: 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, 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

On Tue, 10 Nov 2026 16:33:56 +0100
Alejandro Colomar <alx@kernel.org> wrote:

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

Isn't in enough to do:
#define strprefix(s, pfx) ((typeof(s))strprefix(s, pfx))

which correctly preserves all qualifiers.

David

> +
> +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;


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

* Re: [PATCH v3 3/5] stddef: Add const_cast()
  2026-11-11 10:25   ` David Laight
@ 2026-11-11 10:51     ` Alejandro Colomar
  0 siblings, 0 replies; 16+ messages in thread
From: Alejandro Colomar @ 2026-11-11 10:51 UTC (permalink / raw)
  To: David Laight
  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, 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: 2709 bytes --]

Hi David,

> Date: 2026-11-11 10:25:35+0000
> From: David Laight <david.laight.linux@gmail.com>
>
> On Tue, 10 Nov 2026 16:33:40 +0100
> Alejandro Colomar <alx@kernel.org> wrote:
> 
> > 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))
> 
> Should it be de_const_cast(), or just de_const().

If we want to be explicit about it being for dropping, perhaps
drop_const() or cast_drop_const() feels more readable to me than
de_const().  I had been calling this const_cast() for following C++'s
name.

> It is a shame you need to specify the type,

In some cases we don't want to drop const; it's a "maybe drop const",
actually.  Perhaps for this reason, cast_drop_const() might be
misleading, in that it tells you that it dropped const, but sometimes
it didn't.  On the other hand, if you thougt you had dropped const and
haven't, you'll get build errors, so it's not a big problem.

The reason why we may want to not drop const is that since we do:

	const_cast(CQChar_of(s) *, strprefix(s, pfx))

'CQChar_of() *' expands to either 'const char *' or 'char *', depending
on the qualification of 's'.  In case it expands to 'const char *', we
want to retain const, and not drop it.  The most accurate name would be
cast_at_most_drop_const_but_maybe_not().  :)

> but why not:
> 	_Generic(p, T: p, const T: (T)(p))
> so that you get a compile time error from the _Generic() if the type
> is wrong.

Thanks!  I like that being more robust.


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] 16+ messages in thread

* Re: [PATCH v3 5/5] string: Make strprefix() const-qualifier-generic
  2026-11-11 10:28       ` David Laight
@ 2026-11-11 10:59         ` Alejandro Colomar
  0 siblings, 0 replies; 16+ messages in thread
From: Alejandro Colomar @ 2026-11-11 10:59 UTC (permalink / raw)
  To: David Laight
  Cc: Joe Perches, 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

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

Hi David,

> Date: 2026-11-11 10:28:36+0000
> From: David Laight <david.laight.linux@gmail.com>
>
> On Wed, 11 Nov 2026 00:27:28 +0100
> Alejandro Colomar <alx+linux-hardening@kernel.org> wrote:
> 
> > Hi Joe,
> > 
> > > Date: 2026-11-10 08:32:41-0800
> > > From: Joe Perches <joe@perches.com>
> > >
> > > On Tue, 2026-11-10 at 16:33 +0100, Alejandro Colomar wrote:
> > > 
> > > no commit description on proposed patch  
> > 
> > There isn't much to say, but I'll add something (the explanation of why
> > the parentheses are needed around the function name, for example).
> > 
> > > > 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?  
> > 
> > It's not style; the parentheses are technically needed to avoid macro
> > expansion, since the macro has the same name as the function.
> > 
> > Alternatively, I could rename the function to __strprefix().
> 
> Or put the #define after the function definition.

Done for v4.


Cheers,
Alex

> 
> David
> 
> > 
> > 
> > Have a lovely night!
> > Alex
> > 
> 
> 

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

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

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

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

Thread overview: 16+ 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-11  8:43   ` Steven Rostedt
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-11 10:25   ` David Laight
2026-11-11 10:51     ` 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
2026-11-10 23:27     ` Alejandro Colomar
2026-11-11 10:28       ` David Laight
2026-11-11 10:59         ` Alejandro Colomar
2026-11-11 10:34   ` David Laight

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®