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;


Reply via email to