Re: [PATCH] paste: fix output when file lengths differ

Denys Vlasenko via busybox <[email protected]>
Newsgroups gmane.linux.busybox
Message-ID <CAK1hOcMcGpABA9y9EU3Jt6Akfg6WXVJf+7yavxh_fsKoYBbngg@mail.gmail.com>
Applied, thank you.

On Thu, Nov 13, 2025 at 8:56 AM Ron Yorston <[email protected]> wrote:
>
> If the files being pasted had different numbers of lines the
> output was incorrect.
>
> Rewrite the loop over all lines to allow for this.  Add tests for
> such conditions.
>
> function                                             old     new   delta
> paste_main                                           448     528     +80
> ------------------------------------------------------------------------------
> (add/remove: 0/0 grow/shrink: 1/0 up/down: 80/0)               Total: 80 bytes
>
> Signed-off-by: Ron Yorston <[email protected]>
> ---
>  coreutils/paste.c                | 36 +++++++++++++++++++++-----------
>  testsuite/paste/paste-long-short | 19 +++++++++++++++++
>  testsuite/paste/paste-short-long | 19 +++++++++++++++++
>  3 files changed, 62 insertions(+), 12 deletions(-)
>  create mode 100644 testsuite/paste/paste-long-short
>  create mode 100644 testsuite/paste/paste-short-long
>
> diff --git a/coreutils/paste.c b/coreutils/paste.c
> index 3e5f20158..363340e3d 100644
> --- a/coreutils/paste.c
> +++ b/coreutils/paste.c
> @@ -34,27 +34,38 @@
>
>  static void paste_files(FILE** files, int file_cnt, char* delims, int del_cnt)
>  {
> -       char *line;
> +       char **line = xmalloc(file_cnt * sizeof(char *));
>         char delim;
>         int active_files = file_cnt;
>         int i;
>
>         while (active_files > 0) {
>                 int del_idx = 0;
> +               int got_line = FALSE;
>
>                 for (i = 0; i < file_cnt; ++i) {
> -                       if (files[i] == NULL)
> -                               continue;
> -
> -                       line = xmalloc_fgetline(files[i]);
> -                       if (!line) {
> -                               fclose_if_not_stdin(files[i]);
> -                               files[i] = NULL;
> -                               --active_files;
> -                               continue;
> +                       if (files[i]) {
> +                               line[i] = xmalloc_fgetline(files[i]);
> +                               if (!line[i]) {
> +                                       fclose_if_not_stdin(files[i]);
> +                                       files[i] = NULL;
> +                                       --active_files;
> +                               } else {
> +                                       got_line = TRUE;
> +                               }
> +                       } else {
> +                               line[i] = NULL;
> +                       }
> +               }
> +
> +               if (!got_line)
> +                       break;
> +
> +               for (i = 0; i < file_cnt; ++i) {
> +                       if (line[i]) {
> +                               fputs_stdout(line[i]);
> +                               free(line[i]);
>                         }
> -                       fputs_stdout(line);
> -                       free(line);
>                         delim = '\n';
>                         if (i != file_cnt - 1) {
>                                 delim = delims[del_idx++];
> @@ -65,6 +76,7 @@ static void paste_files(FILE** files, int file_cnt, char* delims, int del_cnt)
>                                 fputc(delim, stdout);
>                 }
>         }
> +       free(line);
>  }
>
>  static void paste_files_separate(FILE** files, char* delims, int del_cnt)
> diff --git a/testsuite/paste/paste-long-short b/testsuite/paste/paste-long-short
> new file mode 100644
> index 000000000..e626d730e
> --- /dev/null
> +++ b/testsuite/paste/paste-long-short
> @@ -0,0 +1,19 @@
> +cat > foo <<EOF
> +foo1
> +foo2
> +foo3
> +EOF
> +
> +cat > bar <<EOF
> +bar1
> +bar2
> +EOF
> +
> +cat > baz <<EOF
> +foo1   bar1
> +foo2   bar2
> +foo3
> +EOF
> +
> +busybox paste foo bar > qux
> +diff -u baz qux
> diff --git a/testsuite/paste/paste-short-long b/testsuite/paste/paste-short-long
> new file mode 100644
> index 000000000..785da60a7
> --- /dev/null
> +++ b/testsuite/paste/paste-short-long
> @@ -0,0 +1,19 @@
> +cat > foo <<EOF
> +foo1
> +foo2
> +EOF
> +
> +cat > bar <<EOF
> +bar1
> +bar2
> +bar3
> +EOF
> +
> +cat > baz <<EOF
> +foo1   bar1
> +foo2   bar2
> +       bar3
> +EOF
> +
> +busybox paste foo bar > qux
> +diff -u baz qux
> --
> 2.51.1
>
> _______________________________________________
> busybox mailing list
> [email protected]
> https://lists.busybox.net/mailman/listinfo/busybox
_______________________________________________
busybox mailing list
[email protected]
https://lists.busybox.net/mailman/listinfo/busybox
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.