Le 03/07/2026 à 8:12 PM, Ian Bridges a écrit : > In preparation for removing the strlcat() API[1], replace its uses in > string-stream. > > string_stream_vadd() appends at most a single newline into space that > was explicitly reserved when the fragment was sized, so a bounded copy > at the end of the string is enough. The return value of strscpy() > keeps the length accounting unchanged. string_stream_get_string() > concatenates a variable number of fragments into a buffer sized to > hold them all, which is what seq_buf is for. > > Link: https://github.com/KSPP/linux/issues/370 [1] > Signed-off-by: Ian Bridges <[email protected]> > --- > Truncation semantics differ between the two APIs. On overflow, > strlcat() keeps whatever prefix of the fragment fits, while > seq_buf_puts() drops any fragment that does not fit whole. Neither > path is reachable here. string_stream_get_string() sizes the buffer > to hold all fragments exactly. The newline lands in a byte that > string_stream_vadd() reserved when it sized the fragment. > > The patch was tested as follows: > - The string-stream KUnit suite passes all 12 tests before and after > the change. The full lib/kunit KUnit config (95 tests) also shows > identical results before and after. > - An x86_64 build of lib/kunit/string-stream.o at W=1 produces no > warnings. > - A userspace comparison of the old and new construction ran > with different fragment lengths for the newline append and with > randomized fragment lists for the concatenation loop. All outputs > were identical. >
Thanks very much (and thanks for testing it so thoroughly!) As much as I find the need for all of the pointer/length arithmetic with strscpy here a little less clear than strlcat, it's definitely not worth the extra loop over the string, so I'm happy with the change. Reviewed-by: David Gow <[email protected]> Cheers, -- David > lib/kunit/string-stream.c | 9 +++++++-- > 1 file changed, 7 insertions(+), 2 deletions(-) > > diff --git a/lib/kunit/string-stream.c b/lib/kunit/string-stream.c > index 0d8f1b30559b..51ba40ebf19f 100644 > --- a/lib/kunit/string-stream.c > +++ b/lib/kunit/string-stream.c > @@ -9,6 +9,7 @@ > #include <kunit/static_stub.h> > #include <kunit/test.h> > #include <linux/list.h> > +#include <linux/seq_buf.h> > #include <linux/slab.h> > > #include "string-stream.h" > @@ -74,7 +75,8 @@ int string_stream_vadd(struct string_stream *stream, > > /* Append newline if necessary. */ > if (frag_container->fragment[result_len - 1] != '\n') > - result_len = strlcat(frag_container->fragment, "\n", > buf_len); > + result_len += strscpy(frag_container->fragment + > result_len, > + "\n", buf_len - result_len); > } else { > result_len = vsnprintf(frag_container->fragment, buf_len, fmt, > args); > } > @@ -118,15 +120,18 @@ char *string_stream_get_string(struct string_stream > *stream) > { > struct string_stream_fragment *frag_container; > size_t buf_len = stream->length + 1; /* +1 for null byte. */ > + struct seq_buf sb; > char *buf; > > buf = kzalloc(buf_len, stream->gfp); > if (!buf) > return NULL; > > + seq_buf_init(&sb, buf, buf_len); > + > spin_lock(&stream->lock); > list_for_each_entry(frag_container, &stream->fragments, node) > - strlcat(buf, frag_container->fragment, buf_len); > + seq_buf_puts(&sb, frag_container->fragment); > spin_unlock(&stream->lock); > > return buf;

