* [PATCH 1/4] lib/sprintf: add scnprintf_append() helper function
[not found] <20251107051616.21606-1-moonafterrain@outlook.com>
@ 2025-11-07 5:16 ` Junrui Luo
2025-11-07 5:38 ` Andrew Morton
2025-11-07 9:34 ` Andy Shevchenko
2025-11-07 5:16 ` [PATCH 2/4] ALSA: wavefront: use scnprintf_append for longname construction Junrui Luo
` (2 subsequent siblings)
3 siblings, 2 replies; 15+ messages in thread
From: Junrui Luo @ 2025-11-07 5:16 UTC (permalink / raw)
To: linux-kernel
Cc: pmladek, rostedt, andriy.shevchenko, akpm, tiwai, perex,
linux-sound, mchehab, awalls, linux-media, davem, edumazet, kuba,
pabeni, netdev, Junrui Luo
Add a new scnprintf_append() helper function that appends formatted
strings to an existing buffer.
The function safely handles buffer bounds and returns the total length
of the string, making it suitable for chaining multiple append operations.
Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
---
include/linux/sprintf.h | 1 +
lib/vsprintf.c | 28 ++++++++++++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/include/linux/sprintf.h b/include/linux/sprintf.h
index f06f7b785091..3906e17fefec 100644
--- a/include/linux/sprintf.h
+++ b/include/linux/sprintf.h
@@ -14,6 +14,7 @@ __printf(3, 4) int snprintf(char *buf, size_t size, const char *fmt, ...);
__printf(3, 0) int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
__printf(3, 4) int scnprintf(char *buf, size_t size, const char *fmt, ...);
__printf(3, 0) int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
+__printf(3, 4) int scnprintf_append(char *buf, size_t size, const char *fmt, ...);
__printf(2, 3) __malloc char *kasprintf(gfp_t gfp, const char *fmt, ...);
__printf(2, 0) __malloc char *kvasprintf(gfp_t gfp, const char *fmt, va_list args);
__printf(2, 0) const char *kvasprintf_const(gfp_t gfp, const char *fmt, va_list args);
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index eb0cb11d0d12..f9540de300cd 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -3048,6 +3048,34 @@ int scnprintf(char *buf, size_t size, const char *fmt, ...)
}
EXPORT_SYMBOL(scnprintf);
+/**
+ * scnprintf_append - Append a formatted string to a buffer
+ * @buf: The buffer to append to (must be null-terminated)
+ * @size: The size of the buffer
+ * @fmt: Format string
+ * @...: Arguments for the format string
+ *
+ * This function appends a formatted string to an existing null-terminated
+ * buffer. It is safe to use in a chain of calls, as it returns the total
+ * length of the string.
+ *
+ * Returns: The total length of the string in @buf
+ */
+int scnprintf_append(char *buf, size_t size, const char *fmt, ...)
+{
+ va_list args;
+ size_t len;
+
+ len = strnlen(buf, size);
+ if (len >= size)
+ return len;
+ va_start(args, fmt);
+ len += vscnprintf(buf + len, size - len, fmt, args);
+ va_end(args);
+ return len;
+}
+EXPORT_SYMBOL(scnprintf_append);
+
/**
* vsprintf - Format a string and place it in a buffer
* @buf: The buffer to place the result into
--
2.51.1.dirty
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 1/4] lib/sprintf: add scnprintf_append() helper function
2025-11-07 5:16 ` [PATCH 1/4] lib/sprintf: add scnprintf_append() helper function Junrui Luo
@ 2025-11-07 5:38 ` Andrew Morton
2025-11-07 9:12 ` David Laight
2025-11-07 9:34 ` Andy Shevchenko
1 sibling, 1 reply; 15+ messages in thread
From: Andrew Morton @ 2025-11-07 5:38 UTC (permalink / raw)
To: Junrui Luo
Cc: linux-kernel, pmladek, rostedt, andriy.shevchenko, tiwai, perex,
linux-sound, mchehab, awalls, linux-media, davem, edumazet, kuba,
pabeni, netdev
On Fri, 7 Nov 2025 13:16:13 +0800 Junrui Luo <moonafterrain@outlook.com> wrote:
> +/**
> + * scnprintf_append - Append a formatted string to a buffer
> + * @buf: The buffer to append to (must be null-terminated)
> + * @size: The size of the buffer
> + * @fmt: Format string
> + * @...: Arguments for the format string
> + *
> + * This function appends a formatted string to an existing null-terminated
> + * buffer. It is safe to use in a chain of calls, as it returns the total
> + * length of the string.
> + *
> + * Returns: The total length of the string in @buf
It wouldn't hurt to describe the behavior when this runs out of space
in *buf.
The whole thing is a bit unweildy - how much space must the caller
allocate for `buf'? I bet that's a wild old guess.
I wonder if we should instead implement a kasprintf() version of this
which reallocs each time and then switch all the callers over to that.
um,
int kasprintf_append(char **pbuf, gfp_t gfp_flags, const char *fmt, ...);
int caller()
{
char *buf = NULL;
while (...) {
x = kasprintf_append(&buf, GFP_KERNEL, "%whatever", stuff...);
if (x == -ENOMEM)
return x;
}
...
kfree(buf);
}
So much nicer!
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH 1/4] lib/sprintf: add scnprintf_append() helper function
2025-11-07 5:38 ` Andrew Morton
@ 2025-11-07 9:12 ` David Laight
2025-11-07 9:35 ` Andy Shevchenko
2025-11-08 0:11 ` Andrew Morton
0 siblings, 2 replies; 15+ messages in thread
From: David Laight @ 2025-11-07 9:12 UTC (permalink / raw)
To: Andrew Morton
Cc: Junrui Luo, linux-kernel, pmladek, rostedt, andriy.shevchenko,
tiwai, perex, linux-sound, mchehab, awalls, linux-media, davem,
edumazet, kuba, pabeni, netdev
On Thu, 6 Nov 2025 21:38:33 -0800
Andrew Morton <akpm@linux-foundation.org> wrote:
> On Fri, 7 Nov 2025 13:16:13 +0800 Junrui Luo <moonafterrain@outlook.com> wrote:
>
> > +/**
> > + * scnprintf_append - Append a formatted string to a buffer
> > + * @buf: The buffer to append to (must be null-terminated)
> > + * @size: The size of the buffer
> > + * @fmt: Format string
> > + * @...: Arguments for the format string
> > + *
> > + * This function appends a formatted string to an existing null-terminated
> > + * buffer. It is safe to use in a chain of calls, as it returns the total
> > + * length of the string.
> > + *
> > + * Returns: The total length of the string in @buf
>
> It wouldn't hurt to describe the behavior when this runs out of space
> in *buf.
>
>
>
> The whole thing is a bit unweildy - how much space must the caller
> allocate for `buf'? I bet that's a wild old guess.
That is true for all the snprintf() functions.
> I wonder if we should instead implement a kasprintf() version of this
> which reallocs each time and then switch all the callers over to that.
That adds the cost of a malloc, and I, like kasprintf() probably ends up
doing all the work of snprintf twice.
I'd be tempted to avoid the strlen() by passing in the offset.
So (say):
#define scnprintf_at(buf, len, off, ...) \
scnprintf((buf) + off, (len) - off, __VA_ARGS__)
Then you can chain calls, eg:
off = scnprintf(buf, sizeof buf, ....);
off += scnprintf_at(buf, sizeof buf, off, ....);
David
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH 1/4] lib/sprintf: add scnprintf_append() helper function
2025-11-07 9:12 ` David Laight
@ 2025-11-07 9:35 ` Andy Shevchenko
2025-11-07 12:52 ` Petr Mladek
2025-11-08 0:11 ` Andrew Morton
1 sibling, 1 reply; 15+ messages in thread
From: Andy Shevchenko @ 2025-11-07 9:35 UTC (permalink / raw)
To: David Laight
Cc: Andrew Morton, Junrui Luo, linux-kernel, pmladek, rostedt, tiwai,
perex, linux-sound, mchehab, awalls, linux-media, davem, edumazet,
kuba, pabeni, netdev
On Fri, Nov 07, 2025 at 09:12:46AM +0000, David Laight wrote:
> On Thu, 6 Nov 2025 21:38:33 -0800
> Andrew Morton <akpm@linux-foundation.org> wrote:
> > On Fri, 7 Nov 2025 13:16:13 +0800 Junrui Luo <moonafterrain@outlook.com> wrote:
...
> That is true for all the snprintf() functions.
>
> > I wonder if we should instead implement a kasprintf() version of this
> > which reallocs each time and then switch all the callers over to that.
>
> That adds the cost of a malloc, and I, like kasprintf() probably ends up
> doing all the work of snprintf twice.
>
> I'd be tempted to avoid the strlen() by passing in the offset.
> So (say):
> #define scnprintf_at(buf, len, off, ...) \
> scnprintf((buf) + off, (len) - off, __VA_ARGS__)
>
> Then you can chain calls, eg:
> off = scnprintf(buf, sizeof buf, ....);
> off += scnprintf_at(buf, sizeof buf, off, ....);
I like this suggestion. Also note, that the original implementation works directly
on static buffers.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/4] lib/sprintf: add scnprintf_append() helper function
2025-11-07 9:35 ` Andy Shevchenko
@ 2025-11-07 12:52 ` Petr Mladek
2025-11-07 17:51 ` David Laight
0 siblings, 1 reply; 15+ messages in thread
From: Petr Mladek @ 2025-11-07 12:52 UTC (permalink / raw)
To: Andy Shevchenko
Cc: David Laight, Andrew Morton, Junrui Luo, linux-kernel, rostedt,
tiwai, perex, linux-sound, mchehab, awalls, linux-media, davem,
edumazet, kuba, pabeni, netdev
On Fri 2025-11-07 11:35:35, Andy Shevchenko wrote:
> On Fri, Nov 07, 2025 at 09:12:46AM +0000, David Laight wrote:
> > On Thu, 6 Nov 2025 21:38:33 -0800
> > Andrew Morton <akpm@linux-foundation.org> wrote:
> > > On Fri, 7 Nov 2025 13:16:13 +0800 Junrui Luo <moonafterrain@outlook.com> wrote:
>
> ...
>
> > That is true for all the snprintf() functions.
> >
> > > I wonder if we should instead implement a kasprintf() version of this
> > > which reallocs each time and then switch all the callers over to that.
> >
> > That adds the cost of a malloc, and I, like kasprintf() probably ends up
> > doing all the work of snprintf twice.
> >
> > I'd be tempted to avoid the strlen() by passing in the offset.
> > So (say):
> > #define scnprintf_at(buf, len, off, ...) \
> > scnprintf((buf) + off, (len) - off, __VA_ARGS__)
It does not handle correctly the situation when len < off.
Othersise, it looks good.
> > Then you can chain calls, eg:
> > off = scnprintf(buf, sizeof buf, ....);
> > off += scnprintf_at(buf, sizeof buf, off, ....);
>
> I like this suggestion. Also note, that the original implementation works directly
> on static buffers.
I would prefer this as well. IMHO, it encourages people to write a better code.
Best Regards,
Petr
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/4] lib/sprintf: add scnprintf_append() helper function
2025-11-07 12:52 ` Petr Mladek
@ 2025-11-07 17:51 ` David Laight
2025-11-10 14:13 ` Petr Mladek
0 siblings, 1 reply; 15+ messages in thread
From: David Laight @ 2025-11-07 17:51 UTC (permalink / raw)
To: Petr Mladek
Cc: Andy Shevchenko, Andrew Morton, Junrui Luo, linux-kernel, rostedt,
tiwai, perex, linux-sound, mchehab, awalls, linux-media, davem,
edumazet, kuba, pabeni, netdev
On Fri, 7 Nov 2025 13:52:27 +0100
Petr Mladek <pmladek@suse.com> wrote:
> On Fri 2025-11-07 11:35:35, Andy Shevchenko wrote:
> > On Fri, Nov 07, 2025 at 09:12:46AM +0000, David Laight wrote:
> > > On Thu, 6 Nov 2025 21:38:33 -0800
> > > Andrew Morton <akpm@linux-foundation.org> wrote:
> > > > On Fri, 7 Nov 2025 13:16:13 +0800 Junrui Luo <moonafterrain@outlook.com> wrote:
> >
> > ...
> >
> > > That is true for all the snprintf() functions.
> > >
> > > > I wonder if we should instead implement a kasprintf() version of this
> > > > which reallocs each time and then switch all the callers over to that.
> > >
> > > That adds the cost of a malloc, and I, like kasprintf() probably ends up
> > > doing all the work of snprintf twice.
> > >
> > > I'd be tempted to avoid the strlen() by passing in the offset.
> > > So (say):
> > > #define scnprintf_at(buf, len, off, ...) \
> > > scnprintf((buf) + off, (len) - off, __VA_ARGS__)
>
> It does not handle correctly the situation when len < off.
> Othersise, it looks good.
That shouldn't happen unless the calling code is really buggy.
There is also a WARN_ON_ONCE() at the top of snprintf().
David
>
> > > Then you can chain calls, eg:
> > > off = scnprintf(buf, sizeof buf, ....);
> > > off += scnprintf_at(buf, sizeof buf, off, ....);
> >
> > I like this suggestion. Also note, that the original implementation works directly
> > on static buffers.
>
> I would prefer this as well. IMHO, it encourages people to write a better code.
>
> Best Regards,
> Petr
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/4] lib/sprintf: add scnprintf_append() helper function
2025-11-07 17:51 ` David Laight
@ 2025-11-10 14:13 ` Petr Mladek
2025-11-11 13:31 ` Junrui Luo
0 siblings, 1 reply; 15+ messages in thread
From: Petr Mladek @ 2025-11-10 14:13 UTC (permalink / raw)
To: David Laight
Cc: Andy Shevchenko, Andrew Morton, Junrui Luo, linux-kernel, rostedt,
tiwai, perex, linux-sound, mchehab, awalls, linux-media, davem,
edumazet, kuba, pabeni, netdev
On Fri 2025-11-07 17:51:23, David Laight wrote:
> On Fri, 7 Nov 2025 13:52:27 +0100
> Petr Mladek <pmladek@suse.com> wrote:
>
> > On Fri 2025-11-07 11:35:35, Andy Shevchenko wrote:
> > > On Fri, Nov 07, 2025 at 09:12:46AM +0000, David Laight wrote:
> > > > On Thu, 6 Nov 2025 21:38:33 -0800
> > > > Andrew Morton <akpm@linux-foundation.org> wrote:
> > > > > On Fri, 7 Nov 2025 13:16:13 +0800 Junrui Luo <moonafterrain@outlook.com> wrote:
> > >
> > > ...
> > >
> > > > That is true for all the snprintf() functions.
> > > >
> > > > > I wonder if we should instead implement a kasprintf() version of this
> > > > > which reallocs each time and then switch all the callers over to that.
> > > >
> > > > That adds the cost of a malloc, and I, like kasprintf() probably ends up
> > > > doing all the work of snprintf twice.
> > > >
> > > > I'd be tempted to avoid the strlen() by passing in the offset.
> > > > So (say):
> > > > #define scnprintf_at(buf, len, off, ...) \
> > > > scnprintf((buf) + off, (len) - off, __VA_ARGS__)
> >
> > It does not handle correctly the situation when len < off.
> > Othersise, it looks good.
>
> That shouldn't happen unless the calling code is really buggy.
> There is also a WARN_ON_ONCE() at the top of snprintf().
Fair enough.
BTW: I have found there exists a userspace library which implements
this idea, the funtion is called vsnoprintf(), see
https://arpa2.gitlab.io/arpa2common/group__snoprintf.html
I know that it is cryptic. But I like the name. The letters "no"
match the ordering of the parameters "size, offset".
In our case, it would be scnoprintf() ...
Best Regards,
Petr
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/4] lib/sprintf: add scnprintf_append() helper function
2025-11-10 14:13 ` Petr Mladek
@ 2025-11-11 13:31 ` Junrui Luo
2025-11-12 9:39 ` Petr Mladek
0 siblings, 1 reply; 15+ messages in thread
From: Junrui Luo @ 2025-11-11 13:31 UTC (permalink / raw)
To: Petr Mladek
Cc: Andy Shevchenko, Andrew Morton, linux-kernel@vger.kernel.org,
rostedt@goodmis.org, tiwai@suse.com, perex@perex.cz,
linux-sound@vger.kernel.org, mchehab@kernel.org,
awalls@md.metrocast.net, linux-media@vger.kernel.org,
David Laight, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org, pabeni@redhat.com, netdev@vger.kernel.org
On Mon, Nov 10, 2025 at 03:13:56PM +0100, Petr Mladek wrote:
> On Fri 2025-11-07 17:51:23, David Laight wrote:
> > On Fri, 7 Nov 2025 13:52:27 +0100
> > Petr Mladek <pmladek@suse.com> wrote:
> >
> > > On Fri 2025-11-07 11:35:35, Andy Shevchenko wrote:
> > > > On Fri, Nov 07, 2025 at 09:12:46AM +0000, David Laight wrote:
> > > > > On Thu, 6 Nov 2025 21:38:33 -0800
> > > > > Andrew Morton <akpm@linux-foundation.org> wrote:
> > > > > > On Fri, 7 Nov 2025 13:16:13 +0800 Junrui Luo <moonafterrain@outlook.com> wrote:
> > > >
> > > > ...
> > > >
> > > > > That is true for all the snprintf() functions.
> > > > >
> > > > > > I wonder if we should instead implement a kasprintf() version of this
> > > > > > which reallocs each time and then switch all the callers over to that.
> > > > >
> > > > > That adds the cost of a malloc, and I, like kasprintf() probably ends up
> > > > > doing all the work of snprintf twice.
> > > > >
> > > > > I'd be tempted to avoid the strlen() by passing in the offset.
> > > > > So (say):
> > > > > #define scnprintf_at(buf, len, off, ...) \
> > > > > scnprintf((buf) + off, (len) - off, __VA_ARGS__)
> > >
> > > It does not handle correctly the situation when len < off.
> > > Othersise, it looks good.
> >
> > That shouldn't happen unless the calling code is really buggy.
> > There is also a WARN_ON_ONCE() at the top of snprintf().
>
> Fair enough.
>
> BTW: I have found there exists a userspace library which implements
> this idea, the funtion is called vsnoprintf(), see
> https://arpa2.gitlab.io/arpa2common/group__snoprintf.html
>
> I know that it is cryptic. But I like the name. The letters "no"
> match the ordering of the parameters "size, offset".
>
> In our case, it would be scnoprintf() ...
>
Thanks for the feedback. Based on the discussion above, I plan to prepare a v2 patch.
int scnprintf_append(char *buf, size_t size, const char *fmt, ...)
{
va_list args;
size_t len;
len = strnlen(buf, size);
if (len == size)
return len;
va_start(args, fmt);
len += vscnprintf(buf + len, size - len, fmt, args);
va_end(args);
return len;
}
EXPORT_SYMBOL(scnprintf_append);
I agree that using a macro like David suggested, with an explicit offset, is a reasonable and efficient approach.
The `scnprintf_append()` function, however, does not require such a variable; though if used improperly, it could introduce an extra `strlen()` overhead.
However, if the consensus is to prefer the macro approach, I can rework the series to use `scnoprintf()`, as suggested by Petr instead.
That said, I believe `scnprintf_append()` also has its merits:
it simplifies one-off string constructions and provides built-in bound checking for safety.
Some existing code that appends strings in the kernel lacks proper bound checks, and this function could serve as a graceful replacement.
The benefits were also demonstrated in other patches.
Thanks,
Junrui
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH 1/4] lib/sprintf: add scnprintf_append() helper function
2025-11-11 13:31 ` Junrui Luo
@ 2025-11-12 9:39 ` Petr Mladek
0 siblings, 0 replies; 15+ messages in thread
From: Petr Mladek @ 2025-11-12 9:39 UTC (permalink / raw)
To: Junrui Luo
Cc: Andy Shevchenko, Andrew Morton, linux-kernel@vger.kernel.org,
rostedt@goodmis.org, tiwai@suse.com, perex@perex.cz,
linux-sound@vger.kernel.org, mchehab@kernel.org,
awalls@md.metrocast.net, linux-media@vger.kernel.org,
David Laight, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org, pabeni@redhat.com, netdev@vger.kernel.org
On Tue 2025-11-11 13:31:00, Junrui Luo wrote:
> On Mon, Nov 10, 2025 at 03:13:56PM +0100, Petr Mladek wrote:
> > On Fri 2025-11-07 17:51:23, David Laight wrote:
> > > On Fri, 7 Nov 2025 13:52:27 +0100
> > > Petr Mladek <pmladek@suse.com> wrote:
> > >
> > > > On Fri 2025-11-07 11:35:35, Andy Shevchenko wrote:
> > > > > On Fri, Nov 07, 2025 at 09:12:46AM +0000, David Laight wrote:
> > > > > > On Thu, 6 Nov 2025 21:38:33 -0800
> > > > > > Andrew Morton <akpm@linux-foundation.org> wrote:
> > > > > > > On Fri, 7 Nov 2025 13:16:13 +0800 Junrui Luo <moonafterrain@outlook.com> wrote:
> > > > >
> > > > > ...
> > > > >
> > > > > > That is true for all the snprintf() functions.
> > > > > >
> > > > > > > I wonder if we should instead implement a kasprintf() version of this
> > > > > > > which reallocs each time and then switch all the callers over to that.
> > > > > >
> > > > > > That adds the cost of a malloc, and I, like kasprintf() probably ends up
> > > > > > doing all the work of snprintf twice.
> > > > > >
> > > > > > I'd be tempted to avoid the strlen() by passing in the offset.
> > > > > > So (say):
> > > > > > #define scnprintf_at(buf, len, off, ...) \
> > > > > > scnprintf((buf) + off, (len) - off, __VA_ARGS__)
> > > >
> > > > It does not handle correctly the situation when len < off.
> > > > Othersise, it looks good.
> > >
> > > That shouldn't happen unless the calling code is really buggy.
> > > There is also a WARN_ON_ONCE() at the top of snprintf().
> >
> > Fair enough.
> >
> > BTW: I have found there exists a userspace library which implements
> > this idea, the funtion is called vsnoprintf(), see
> > https://arpa2.gitlab.io/arpa2common/group__snoprintf.html
> >
> > I know that it is cryptic. But I like the name. The letters "no"
> > match the ordering of the parameters "size, offset".
> >
> > In our case, it would be scnoprintf() ...
> >
>
> Thanks for the feedback. Based on the discussion above, I plan to prepare a v2 patch.
> int scnprintf_append(char *buf, size_t size, const char *fmt, ...)
> {
> va_list args;
> size_t len;
>
> len = strnlen(buf, size);
> if (len == size)
> return len;
> va_start(args, fmt);
> len += vscnprintf(buf + len, size - len, fmt, args);
> va_end(args);
> return len;
> }
> EXPORT_SYMBOL(scnprintf_append);
I am fine with this. Just please add a comment that that it can be
inefficient when using massively because it does strlen().
I see similar comment in "CAVEATS" section in man 3 strcat.
> I agree that using a macro like David suggested, with an explicit offset, is a reasonable and efficient approach.
> The `scnprintf_append()` function, however, does not require such a variable; though if used improperly, it could introduce an extra `strlen()` overhead.
>
> However, if the consensus is to prefer the macro approach, I can rework the series to use `scnoprintf()`, as suggested by Petr instead.
>
> That said, I believe `scnprintf_append()` also has its merits:
> it simplifies one-off string constructions and provides built-in bound checking for safety.
> Some existing code that appends strings in the kernel lacks proper bound checks, and this function could serve as a graceful replacement.
> The benefits were also demonstrated in other patches.
I think that both functions might have their users. You might consider
adding the other variant when doing the conversions.
Best Regards,
Petr
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/4] lib/sprintf: add scnprintf_append() helper function
2025-11-07 9:12 ` David Laight
2025-11-07 9:35 ` Andy Shevchenko
@ 2025-11-08 0:11 ` Andrew Morton
2025-11-08 9:11 ` Takashi Iwai
1 sibling, 1 reply; 15+ messages in thread
From: Andrew Morton @ 2025-11-08 0:11 UTC (permalink / raw)
To: David Laight
Cc: Junrui Luo, linux-kernel, pmladek, rostedt, andriy.shevchenko,
tiwai, perex, linux-sound, mchehab, awalls, linux-media, davem,
edumazet, kuba, pabeni, netdev
On Fri, 7 Nov 2025 09:12:46 +0000 David Laight <david.laight.linux@gmail.com> wrote:
> > I wonder if we should instead implement a kasprintf() version of this
> > which reallocs each time and then switch all the callers over to that.
>
> That adds the cost of a malloc, and I, like kasprintf() probably ends up
> doing all the work of snprintf twice.
There is no need at all to optimize the performance of scruffy once-off
string pasting functions. For these it's better to optimize for
readability, reliability. maintainability.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/4] lib/sprintf: add scnprintf_append() helper function
2025-11-08 0:11 ` Andrew Morton
@ 2025-11-08 9:11 ` Takashi Iwai
0 siblings, 0 replies; 15+ messages in thread
From: Takashi Iwai @ 2025-11-08 9:11 UTC (permalink / raw)
To: Andrew Morton
Cc: David Laight, Junrui Luo, linux-kernel, pmladek, rostedt,
andriy.shevchenko, tiwai, perex, linux-sound, mchehab, awalls,
linux-media, davem, edumazet, kuba, pabeni, netdev
On Sat, 08 Nov 2025 01:11:30 +0100,
Andrew Morton wrote:
>
> On Fri, 7 Nov 2025 09:12:46 +0000 David Laight <david.laight.linux@gmail.com> wrote:
>
> > > I wonder if we should instead implement a kasprintf() version of this
> > > which reallocs each time and then switch all the callers over to that.
> >
> > That adds the cost of a malloc, and I, like kasprintf() probably ends up
> > doing all the work of snprintf twice.
>
> There is no need at all to optimize the performance of scruffy once-off
> string pasting functions. For these it's better to optimize for
> readability, reliability. maintainability.
Actually this scnprintf_append() helper was my suggestion in another
threads:
https://lore.kernel.org/ME2PR01MB3156CEC4F31F253C9B540FB7AFFDA@ME2PR01MB3156.ausprd01.prod.outlook.com
https://lore.kernel.org/SYBPR01MB7881987D79C62D8122B655FEAFC6A@SYBPR01MB7881.ausprd01.prod.outlook.com
Basically its use is for filling a substring with s*printf() inside a
fixed string such as a field in a struct. Through a quick grep, there
are many kernel code doing it without bounce checks, and it's for
helping those. So it's a bit different from what you assumed with the
re-allocatable buffers.
The most merit of this API is that it can just be a kind of drop-in
replacement without extra variable to keep the offset, as found in
this patch series.
Though, it won't change too much to introduce an offset variable as
the API David suggested, which looks nice, so I myself don't mind
either way (it's a bike-shed topic, after all :)
thanks,
Takashi
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/4] lib/sprintf: add scnprintf_append() helper function
2025-11-07 5:16 ` [PATCH 1/4] lib/sprintf: add scnprintf_append() helper function Junrui Luo
2025-11-07 5:38 ` Andrew Morton
@ 2025-11-07 9:34 ` Andy Shevchenko
1 sibling, 0 replies; 15+ messages in thread
From: Andy Shevchenko @ 2025-11-07 9:34 UTC (permalink / raw)
To: Junrui Luo
Cc: linux-kernel, pmladek, rostedt, akpm, tiwai, perex, linux-sound,
mchehab, awalls, linux-media, davem, edumazet, kuba, pabeni,
netdev
On Fri, Nov 07, 2025 at 01:16:13PM +0800, Junrui Luo wrote:
> Add a new scnprintf_append() helper function that appends formatted
> strings to an existing buffer.
>
> The function safely handles buffer bounds and returns the total length
> of the string, making it suitable for chaining multiple append operations.
This won't work as expected in the *printf() functions.
...
> +/**
> + * scnprintf_append - Append a formatted string to a buffer
The name with _cat would be probably closer to the strcpy()/strcat().
OTOH we have pr_cont(), so perhaps I would name this scnprintf_cont().
> + * @buf: The buffer to append to (must be null-terminated)
Yeah, and must be not NULL which is no go. The *printf() should tolerate
the (buf = NULL, size = 0) input.
> + * @size: The size of the buffer
> + * @fmt: Format string
> + * @...: Arguments for the format string
> + *
> + * This function appends a formatted string to an existing null-terminated
Use the form of "null-terminated" used in the file. Perhaps you want to update
the existing one(s), just make sure there is some consistency.
> + * buffer. It is safe to use in a chain of calls, as it returns the total
> + * length of the string.
> + *
> + * Returns: The total length of the string in @buf
> + */
> +int scnprintf_append(char *buf, size_t size, const char *fmt, ...)
> +{
> + va_list args;
> + size_t len;
> + len = strnlen(buf, size);
> + if (len >= size)
How can it be '>' ?
> + return len;
> + va_start(args, fmt);
> + len += vscnprintf(buf + len, size - len, fmt, args);
> + va_end(args);
> + return len;
> +}
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 2/4] ALSA: wavefront: use scnprintf_append for longname construction
[not found] <20251107051616.21606-1-moonafterrain@outlook.com>
2025-11-07 5:16 ` [PATCH 1/4] lib/sprintf: add scnprintf_append() helper function Junrui Luo
@ 2025-11-07 5:16 ` Junrui Luo
2025-11-07 5:16 ` [PATCH 3/4] media: ivtv: use scnprintf_append for i2c adapter name Junrui Luo
2025-11-07 5:16 ` [PATCH 4/4] net: qede: use scnprintf_append for version string Junrui Luo
3 siblings, 0 replies; 15+ messages in thread
From: Junrui Luo @ 2025-11-07 5:16 UTC (permalink / raw)
To: linux-kernel
Cc: pmladek, rostedt, andriy.shevchenko, akpm, tiwai, perex,
linux-sound, mchehab, awalls, linux-media, davem, edumazet, kuba,
pabeni, netdev, Junrui Luo, stable
Replace sprintf() calls with scnprintf() and the new scnprintf_append()
helper function when constructing card->longname. This improves code
readability and provides bounds checking.
Cc: stable@vger.kernel.org
Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
---
sound/isa/wavefront/wavefront.c | 37 +++++++++++++++++----------------
1 file changed, 19 insertions(+), 18 deletions(-)
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index 07c68568091d..eec4be5c3217 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -492,26 +492,27 @@ snd_wavefront_probe (struct snd_card *card, int dev)
length restrictions
*/
- sprintf(card->longname, "%s PCM 0x%lx irq %d dma %d",
- card->driver,
- chip->port,
- cs4232_pcm_irq[dev],
- dma1[dev]);
+ scnprintf(card->longname, sizeof(card->longname),
+ "%s PCM 0x%lx irq %d dma %d",
+ card->driver,
+ chip->port,
+ cs4232_pcm_irq[dev],
+ dma1[dev]);
if (dma2[dev] >= 0 && dma2[dev] < 8)
- sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
-
- if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) {
- sprintf (card->longname + strlen (card->longname),
- " MPU-401 0x%lx irq %d",
- cs4232_mpu_port[dev],
- cs4232_mpu_irq[dev]);
- }
-
- sprintf (card->longname + strlen (card->longname),
- " SYNTH 0x%lx irq %d",
- ics2115_port[dev],
- ics2115_irq[dev]);
+ scnprintf_append(card->longname, sizeof(card->longname),
+ "&%d", dma2[dev]);
+
+ if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT)
+ scnprintf_append(card->longname, sizeof(card->longname),
+ " MPU-401 0x%lx irq %d",
+ cs4232_mpu_port[dev],
+ cs4232_mpu_irq[dev]);
+
+ scnprintf_append(card->longname, sizeof(card->longname),
+ " SYNTH 0x%lx irq %d",
+ ics2115_port[dev],
+ ics2115_irq[dev]);
return snd_card_register(card);
}
--
2.51.1.dirty
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 3/4] media: ivtv: use scnprintf_append for i2c adapter name
[not found] <20251107051616.21606-1-moonafterrain@outlook.com>
2025-11-07 5:16 ` [PATCH 1/4] lib/sprintf: add scnprintf_append() helper function Junrui Luo
2025-11-07 5:16 ` [PATCH 2/4] ALSA: wavefront: use scnprintf_append for longname construction Junrui Luo
@ 2025-11-07 5:16 ` Junrui Luo
2025-11-07 5:16 ` [PATCH 4/4] net: qede: use scnprintf_append for version string Junrui Luo
3 siblings, 0 replies; 15+ messages in thread
From: Junrui Luo @ 2025-11-07 5:16 UTC (permalink / raw)
To: linux-kernel
Cc: pmladek, rostedt, andriy.shevchenko, akpm, tiwai, perex,
linux-sound, mchehab, awalls, linux-media, davem, edumazet, kuba,
pabeni, netdev, Junrui Luo
Replace sprintf(itv->i2c_adap.name + strlen(...), ...) with
scnprintf_append() for building the i2c adapter name. This provides
proper bounds checking and improves code readability.
Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
---
drivers/media/pci/ivtv/ivtv-i2c.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/media/pci/ivtv/ivtv-i2c.c b/drivers/media/pci/ivtv/ivtv-i2c.c
index 28cb22d6a892..a12c6b9fb4a7 100644
--- a/drivers/media/pci/ivtv/ivtv-i2c.c
+++ b/drivers/media/pci/ivtv/ivtv-i2c.c
@@ -711,8 +711,7 @@ int init_ivtv_i2c(struct ivtv *itv)
itv->i2c_algo.data = itv;
itv->i2c_adap.algo_data = &itv->i2c_algo;
- sprintf(itv->i2c_adap.name + strlen(itv->i2c_adap.name), " #%d",
- itv->instance);
+ scnprintf_append(itv->i2c_adap.name, sizeof(itv->i2c_adap.name), " #%d", itv->instance);
i2c_set_adapdata(&itv->i2c_adap, &itv->v4l2_dev);
itv->i2c_client = ivtv_i2c_client_template;
--
2.51.1.dirty
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 4/4] net: qede: use scnprintf_append for version string
[not found] <20251107051616.21606-1-moonafterrain@outlook.com>
` (2 preceding siblings ...)
2025-11-07 5:16 ` [PATCH 3/4] media: ivtv: use scnprintf_append for i2c adapter name Junrui Luo
@ 2025-11-07 5:16 ` Junrui Luo
3 siblings, 0 replies; 15+ messages in thread
From: Junrui Luo @ 2025-11-07 5:16 UTC (permalink / raw)
To: linux-kernel
Cc: pmladek, rostedt, andriy.shevchenko, akpm, tiwai, perex,
linux-sound, mchehab, awalls, linux-media, davem, edumazet, kuba,
pabeni, netdev, Junrui Luo
Replace snprintf(buf + strlen(buf), left_size, ...) with
scnprintf_append() for building the firmware version string. This
simplifies the code.
Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
---
drivers/net/ethernet/qlogic/qede/qede_main.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index b5d744d2586f..6e85c3a4aaa9 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -1185,7 +1185,6 @@ static void qede_log_probe(struct qede_dev *edev)
{
struct qed_dev_info *p_dev_info = &edev->dev_info.common;
u8 buf[QEDE_FW_VER_STR_SIZE];
- size_t left_size;
snprintf(buf, QEDE_FW_VER_STR_SIZE,
"Storm FW %d.%d.%d.%d, Management FW %d.%d.%d.%d",
@@ -1200,10 +1199,8 @@ static void qede_log_probe(struct qede_dev *edev)
(p_dev_info->mfw_rev & QED_MFW_VERSION_0_MASK) >>
QED_MFW_VERSION_0_OFFSET);
- left_size = QEDE_FW_VER_STR_SIZE - strlen(buf);
- if (p_dev_info->mbi_version && left_size)
- snprintf(buf + strlen(buf), left_size,
- " [MBI %d.%d.%d]",
+ if (p_dev_info->mbi_version)
+ scnprintf_append(buf, QEDE_FW_VER_STR_SIZE, " [MBI %d.%d.%d]",
(p_dev_info->mbi_version & QED_MBI_VERSION_2_MASK) >>
QED_MBI_VERSION_2_OFFSET,
(p_dev_info->mbi_version & QED_MBI_VERSION_1_MASK) >>
--
2.51.1.dirty
^ permalink raw reply related [flat|nested] 15+ messages in thread