#1027101 coreutils: wc: -c st_size optimisation broken for files larger than max(size_t)

Package:
coreutils
Source:
coreutils
Description:
GNU core utilities
Submitter:
наб
Date:
2022-12-28 14:15:03 UTC
Severity:
normal
#1027101#5
Date:
2022-12-27 19:38:07 UTC
From:
To:
Dear Maintainer,

This is a regression against 8.32-4+b1 (bullseye).

To repro this, run truncate -s 2E a, then wc -c a;
this completes instantly on bullseye and spins in a read(2) loop on sid.

Found as part of #1027100.

Best,
наб

#1027101#10
Date:
2022-12-28 13:31:12 UTC
From:
To:
I think I see the issue but only on 32 bit size_t.
Ah this is x32, as per your report.
Can you change the end_pos type to off_t like:
index bc52a8c0e..df9770396 100644
--- a/src/wc.c
+++ b/src/wc.c
@@ -431,7 +431,7 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, off_t current_pos)
        if (! fstatus->failed && usable_st_size (&fstatus->st)
            && 0 <= fstatus->st.st_size)
          {
-          size_t end_pos = fstatus->st.st_size;
+          off_t end_pos = fstatus->st.st_size;
            if (current_pos < 0)
              current_pos = lseek (fd, 0, SEEK_CUR);

cheers,
Pádraig

#1027101#15
Date:
2022-12-28 13:31:12 UTC
From:
To:
I think I see the issue but only on 32 bit size_t.
Ah this is x32, as per your report.
Can you change the end_pos type to off_t like:
index bc52a8c0e..df9770396 100644
--- a/src/wc.c
+++ b/src/wc.c
@@ -431,7 +431,7 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, off_t current_pos)
        if (! fstatus->failed && usable_st_size (&fstatus->st)
            && 0 <= fstatus->st.st_size)
          {
-          size_t end_pos = fstatus->st.st_size;
+          off_t end_pos = fstatus->st.st_size;
            if (current_pos < 0)
              current_pos = lseek (fd, 0, SEEK_CUR);

cheers,
Pádraig

#1027101#20
Date:
2022-12-28 13:49:46 UTC
From:
To:
Hi!
I can confirm this behaves as you'd expect for a [iu]64->u32 truncation:
-- >8 --
$ truncate -s $(echo 2^32-1 | bc) a
$ time wc -c a
4294967295 a

real    0m0.002s
user    0m0.002s
sys     0m0.000s
$ truncate -s $(echo 2^32 | bc) a
$ time wc -c a
4294967296 a

real    0m0.718s
user    0m0.092s
sys     0m0.626s
-- >8 --

And I can repro this exact behaviour on i386.

Best,
наб

#1027101#27
Date:
2022-12-28 14:13:45 UTC
From:
To:
Proposed upstream patch attached.

thanks,
Pádraig