From: Alejandro Colomar <alx@kernel.org>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: linux-mm@kvack.org, linux-hardening@vger.kernel.org,
Kees Cook <kees@kernel.org>,
Christopher Bazley <chris.bazley.wg14@gmail.com>,
shadow <~hallyn/shadow@lists.sr.ht>,
linux-kernel@vger.kernel.org,
Andrew Morton <akpm@linux-foundation.org>,
kasan-dev@googlegroups.com, Dmitry Vyukov <dvyukov@google.com>,
Alexander Potapenko <glider@google.com>,
Marco Elver <elver@google.com>, Christoph Lameter <cl@linux.com>,
David Rientjes <rientjes@google.com>,
Vlastimil Babka <vbabka@suse.cz>,
Roman Gushchin <roman.gushchin@linux.dev>,
Harry Yoo <harry.yoo@oracle.com>,
Andrew Clayton <andrew@digital-domain.net>,
Rasmus Villemoes <linux@rasmusvillemoes.dk>,
Michal Hocko <mhocko@suse.com>,
Al Viro <viro@zeniv.linux.org.uk>,
Martin Uecker <uecker@tugraz.at>, Sam James <sam@gentoo.org>,
Andrew Pinski <pinskia@gmail.com>
Subject: Re: [RFC v5 6/7] sprintf: Add [v]sprintf_array()
Date: Fri, 11 Jul 2025 01:24:44 +0200 [thread overview]
Message-ID: <vgqpplbhg6krsufibrhe4n5agnh7vcrdsmoqd225guiakr3ojs@2dltrftpb3p2> (raw)
In-Reply-To: <krmt6a25gio6ing5mgahl72nvw36jc7u3zyyb5dzbk4nfjnuy4@fex2h7lqmfwt>
[-- Attachment #1: Type: text/plain, Size: 5590 bytes --]
On Fri, Jul 11, 2025 at 01:23:56AM +0200, Alejandro Colomar wrote:
> Hi Linus,
>
> [I'll reply to both of your emails at once]
>
> On Thu, Jul 10, 2025 at 02:58:24PM -0700, Linus Torvalds wrote:
> > You took my suggestion, and then you messed it up.
> >
> > Your version of sprintf_array() is broken. It evaluates 'a' twice.
> > Because unlike ARRAY_SIZE(), your broken ENDOF() macro evaluates the
> > argument.
>
> An array has no issue being evaluated twice (unless it's a VLA). On the
> other hand, I agree it's better to not do that in the first place.
> My bad for forgetting about it. Sorry.
>
> On Thu, Jul 10, 2025 at 03:08:29PM -0700, Linus Torvalds wrote:
> > If you want to return an error on truncation, do it right. Not by
> > returning NULL, but by actually returning an error.
>
> Okay.
>
> > For example, in the kernel, we finally fixed 'strcpy()'. After about a
> > million different versions of 'copy a string' where every single
> > version was complete garbage, we ended up with 'strscpy()'. Yeah, the
> > name isn't lovely, but the *use* of it is:
>
> I have implemented the same thing in shadow, called strtcpy() (T for
> truncation). (With the difference that we read the string twice, since
> we don't care about threads.)
>
> I also plan to propose standardization of that one in ISO C.
>
> > - it returns the length of the result for people who want it - which
> > is by far the most common thing people want
>
> Agree.
>
> > - it returns an actual honest-to-goodness error code if something
> > overflowed, instead of the absoilutely horrible "source length" of the
> > string that strlcpy() does and which is fundamentally broken (because
> > it requires that you walk *past* the end of the source,
> > Christ-on-a-stick what a broken interface)
>
> Agree.
>
> > - it can take an array as an argument (without the need for another
> > name - see my earlier argument about not making up new names by just
> > having generics)
>
> We can't make the same thing with sprintf() variants because they're
> variadic, so you can't count the number of arguments. And since the
> 'end' argument is of the same type as the formatted string, we can't
> do it with _Generic reliably either.
>
> > Now, it has nasty naming (exactly the kind of 'add random character'
> > naming that I was arguing against), and that comes from so many
> > different broken versions until we hit on something that works.
> >
> > strncpy is horrible garbage. strlcpy is even worse. strscpy actually
> > works and so far hasn't caused issues (there's a 'pad' version for the
> > very rare situation where you want 'strncpy-like' padding, but it
> > still guarantees NUL-termination, and still has a good return value).
>
> Agree.
>
> > Let's agree to *not* make horrible garbage when making up new versions
> > of sprintf.
>
> Agree. I indeed introduced the mistake accidentally in v4, after you
> complained of having too many functions, as I was introducing not one
> but two APIs: seprintf() and stprintf(), where seprintf() is what now
> we're calling sprintf_end(), and stprintf() we could call it
> sprintf_trunc(). So I did the mistake by trying to reduce the number of
> functions to just one, which is wrong.
>
> So, maybe I should go back to those functions, and just give them good
> names.
>
> What do you think of the following?
>
> #define sprintf_array(a, ...) sprintf_trunc(a, ARRAY_SIZE(a), __VA_ARGS__)
> #define vsprintf_array(a, ap) vsprintf_trunc(a, ARRAY_SIZE(a), ap)
>
> char *sprintf_end(char *p, const char end[0], const char *fmt, ...);
> char *vsprintf_end(char *p, const char end[0], const char *fmt, va_list args);
> int sprintf_trunc(char *buf, size_t size, const char *fmt, ...);
> int vsprintf_trunc(char *buf, size_t size, const char *fmt, va_list args);
>
> char *sprintf_end(char *p, const char end[0], const char *fmt, ...)
> {
> va_list args;
>
> va_start(args, fmt);
> p = vseprintf(p, end, fmt, args);
Typo here. It's vsprintf_end().
> va_end(args);
>
> return p;
> }
>
> char *vsprintf_end(char *p, const char end[0], const char *fmt, va_list args)
> {
> int len;
>
> if (unlikely(p == NULL))
> return NULL;
>
> len = vsprintf_trunc(p, end - p, fmt, args);
> if (unlikely(len < 0))
> return NULL;
>
> return p + len;
> }
>
> int sprintf_trunc(char *buf, size_t size, const char *fmt, ...)
> {
> va_list args;
> int len;
>
> va_start(args, fmt);
> len = vstprintf(buf, size, fmt, args);
Typo here. It's vsprintf_trunc().
> va_end(args);
>
> return len;
> }
>
> int vsprintf_trunc(char *buf, size_t size, const char *fmt, va_list args)
> {
> int len;
>
> if (WARN_ON_ONCE(size == 0 || size > INT_MAX))
> return -EOVERFLOW;
>
> len = vsnprintf(buf, size, fmt, args);
> if (unlikely(len >= size))
> return -E2BIG;
>
> return len;
> }
>
> sprintf_trunc() is like strscpy(), but with a formatted string. It
> could replace uses of s[c]nprintf() where there's a single call (no
> chained calls).
>
> sprintf_array() is like the 2-argument version of strscpy(). It could
> replace s[c]nprintf() calls where there's no chained calls, where the
> input is an array.
>
> sprintf_end() would replace the chained calls.
>
> Does this sound good to you?
>
>
> Cheers,
> Alex
>
> --
> <https://www.alejandro-colomar.es/>
--
<https://www.alejandro-colomar.es/>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
next prev parent reply other threads:[~2025-07-10 23:24 UTC|newest]
Thread overview: 98+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-05 20:33 [RFC v1 0/3] Add and use seprintf() instead of less ergonomic APIs Alejandro Colomar
2025-07-05 20:33 ` [RFC v1 1/3] vsprintf: Add [v]seprintf(), [v]stprintf() Alejandro Colomar
2025-07-05 20:40 ` Alejandro Colomar
2025-07-07 9:47 ` Alexander Potapenko
2025-07-07 14:59 ` Alejandro Colomar
2025-07-05 20:33 ` [RFC v1 2/3] stacktrace, stackdepot: Add seprintf()-like variants of functions Alejandro Colomar
2025-07-05 20:33 ` [RFC v1 3/3] mm: Use seprintf() instead of less ergonomic APIs Alejandro Colomar
2025-07-05 21:54 ` Alejandro Colomar
2025-07-06 17:37 ` [RFC v2 0/5] Add and use " Alejandro Colomar
2025-07-06 17:37 ` [RFC v2 1/5] vsprintf: Add [v]seprintf(), [v]stprintf() Alejandro Colomar
2025-07-06 17:37 ` [RFC v2 2/5] stacktrace, stackdepot: Add seprintf()-like variants of functions Alejandro Colomar
2025-07-06 17:37 ` [RFC v2 3/5] mm: Use seprintf() instead of less ergonomic APIs Alejandro Colomar
2025-07-06 17:37 ` [RFC v2 4/5] array_size.h: Add ENDOF() Alejandro Colomar
2025-07-06 17:37 ` [RFC v2 5/5] mm: Fix benign off-by-one bugs Alejandro Colomar
2025-07-07 5:06 ` [RFC v3 0/7] Add and use seprintf() instead of less ergonomic APIs Alejandro Colomar
2025-07-07 5:06 ` [RFC v3 1/7] vsprintf: Add [v]seprintf(), [v]stprintf() Alejandro Colomar
2025-07-07 5:06 ` [RFC v3 2/7] stacktrace, stackdepot: Add seprintf()-like variants of functions Alejandro Colomar
2025-07-07 5:06 ` [RFC v3 3/7] mm: Use seprintf() instead of less ergonomic APIs Alejandro Colomar
2025-07-07 7:44 ` Marco Elver
2025-07-07 14:39 ` Alejandro Colomar
2025-07-07 14:58 ` Marco Elver
2025-07-07 18:51 ` Alejandro Colomar
2025-07-07 19:08 ` Marco Elver
2025-07-07 20:53 ` Alejandro Colomar
2025-07-07 19:17 ` Linus Torvalds
2025-07-07 19:35 ` Al Viro
2025-07-07 20:46 ` Linus Torvalds
2025-07-07 20:29 ` Alejandro Colomar
2025-07-07 20:49 ` Linus Torvalds
2025-07-07 21:05 ` Alejandro Colomar
2025-07-07 21:26 ` Alejandro Colomar
2025-07-07 22:17 ` Linus Torvalds
2025-07-08 2:20 ` Alejandro Colomar
2025-07-12 20:58 ` Christopher Bazley
2025-07-14 7:57 ` Christopher Bazley
2025-07-07 5:06 ` [RFC v3 4/7] array_size.h: Add ENDOF() Alejandro Colomar
2025-07-07 5:06 ` [RFC v3 5/7] mm: Fix benign off-by-one bugs Alejandro Colomar
2025-07-07 7:46 ` Marco Elver
2025-07-07 7:53 ` Michal Hocko
2025-07-07 14:42 ` Alejandro Colomar
2025-07-07 15:12 ` Michal Hocko
2025-07-07 15:29 ` Alejandro Colomar
2025-07-07 5:06 ` [RFC v3 6/7] sprintf: Add [V]STPRINTF() Alejandro Colomar
2025-07-07 5:06 ` [RFC v3 7/7] mm: Use [V]STPRINTF() to avoid specifying the array size Alejandro Colomar
2025-07-07 5:11 ` [RFC v3 0/7] Add and use seprintf() instead of less ergonomic APIs Alejandro Colomar
2025-07-10 2:47 ` [RFC v4 0/7] Add and use sprintf_end() " Alejandro Colomar
2025-07-10 2:47 ` alx-0049r2 - add seprintf() Alejandro Colomar
2025-07-10 2:48 ` [RFC v4 1/7] vsprintf: Add [v]sprintf_end() Alejandro Colomar
2025-07-10 2:48 ` [RFC v4 2/7] stacktrace, stackdepot: Add sprintf_end()-like variants of functions Alejandro Colomar
2025-07-10 2:48 ` [RFC v4 3/7] mm: Use sprintf_end() instead of less ergonomic APIs Alejandro Colomar
2025-07-10 2:48 ` [RFC v4 4/7] array_size.h: Add ENDOF() Alejandro Colomar
2025-07-10 2:48 ` [RFC v4 5/7] mm: Fix benign off-by-one bugs Alejandro Colomar
2025-07-10 2:48 ` [RFC v4 6/7] sprintf: Add [V]SPRINTF_END() Alejandro Colomar
2025-07-10 15:52 ` Linus Torvalds
2025-07-10 18:30 ` Alejandro Colomar
2025-07-10 21:21 ` Alejandro Colomar
2025-07-10 22:08 ` Linus Torvalds
2025-07-10 2:49 ` [RFC v4 7/7] mm: Use [V]SPRINTF_END() to avoid specifying the array size Alejandro Colomar
2025-07-10 21:30 ` [RFC v5 0/7] Add and use sprintf_{end,array}() instead of less ergonomic APIs Alejandro Colomar
2025-07-10 21:30 ` [RFC v5 1/7] vsprintf: Add [v]sprintf_end() Alejandro Colomar
2025-07-10 21:30 ` [RFC v5 2/7] stacktrace, stackdepot: Add sprintf_end()-like variants of functions Alejandro Colomar
2025-07-10 21:30 ` [RFC v5 3/7] mm: Use sprintf_end() instead of less ergonomic APIs Alejandro Colomar
2025-07-10 21:31 ` [RFC v5 4/7] array_size.h: Add ENDOF() Alejandro Colomar
2025-07-10 21:31 ` [RFC v5 5/7] mm: Fix benign off-by-one bugs Alejandro Colomar
2025-07-10 21:31 ` [RFC v5 6/7] sprintf: Add [v]sprintf_array() Alejandro Colomar
2025-07-10 21:58 ` Linus Torvalds
2025-07-10 23:23 ` Alejandro Colomar
2025-07-10 23:24 ` Alejandro Colomar [this message]
2025-07-11 0:19 ` Alejandro Colomar
2025-07-11 17:43 ` David Laight
2025-07-11 19:17 ` Alejandro Colomar
2025-07-11 19:21 ` Alejandro Colomar
2025-07-11 6:05 ` Martin Uecker
2025-07-11 6:19 ` Martin Uecker
2025-07-11 17:45 ` David Laight
2025-07-11 17:58 ` Linus Torvalds
2025-07-11 19:24 ` Matthew Wilcox
2025-07-15 5:19 ` Kees Cook
2025-07-15 6:24 ` Martin Uecker
2025-07-17 23:44 ` Kees Cook
2025-07-15 7:08 ` Alejandro Colomar
2025-07-17 23:47 ` Kees Cook
2025-07-18 0:56 ` Alejandro Colomar
2025-07-11 18:01 ` Martin Uecker
2025-07-10 21:31 ` [RFC v5 7/7] mm: Use [v]sprintf_array() to avoid specifying the array size Alejandro Colomar
2025-07-11 1:56 ` [RFC v6 0/8] Add and use sprintf_{end,trunc,array}() instead of less ergonomic APIs Alejandro Colomar
2025-07-11 1:56 ` [RFC v6 1/8] vsprintf: Add [v]sprintf_trunc() Alejandro Colomar
2025-07-11 1:56 ` [RFC v6 2/8] vsprintf: Add [v]sprintf_end() Alejandro Colomar
2025-07-11 1:56 ` [RFC v6 3/8] sprintf: Add [v]sprintf_array() Alejandro Colomar
2025-07-11 1:56 ` [RFC v6 4/8] stacktrace, stackdepot: Add sprintf_end()-like variants of functions Alejandro Colomar
2025-07-11 1:57 ` [RFC v6 5/8] mm: Use sprintf_end() instead of less ergonomic APIs Alejandro Colomar
2025-07-11 1:57 ` [RFC v6 6/8] array_size.h: Add ENDOF() Alejandro Colomar
2025-07-11 1:57 ` [RFC v6 7/8] mm: Fix benign off-by-one bugs Alejandro Colomar
2025-07-11 1:57 ` [RFC v6 8/8] mm: Use [v]sprintf_array() to avoid specifying the array size Alejandro Colomar
2025-07-08 6:43 ` [RFC v1 0/3] Add and use seprintf() instead of less ergonomic APIs Rasmus Villemoes
2025-07-08 11:36 ` Alejandro Colomar
2025-07-08 13:51 ` Rasmus Villemoes
2025-07-08 16:14 ` Alejandro Colomar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=vgqpplbhg6krsufibrhe4n5agnh7vcrdsmoqd225guiakr3ojs@2dltrftpb3p2 \
--to=alx@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=andrew@digital-domain.net \
--cc=chris.bazley.wg14@gmail.com \
--cc=cl@linux.com \
--cc=dvyukov@google.com \
--cc=elver@google.com \
--cc=glider@google.com \
--cc=harry.yoo@oracle.com \
--cc=kasan-dev@googlegroups.com \
--cc=kees@kernel.org \
--cc=linux-hardening@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux@rasmusvillemoes.dk \
--cc=mhocko@suse.com \
--cc=pinskia@gmail.com \
--cc=rientjes@google.com \
--cc=roman.gushchin@linux.dev \
--cc=sam@gentoo.org \
--cc=torvalds@linux-foundation.org \
--cc=uecker@tugraz.at \
--cc=vbabka@suse.cz \
--cc=viro@zeniv.linux.org.uk \
--cc=~hallyn/shadow@lists.sr.ht \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).