Paul Eggert <[email protected]> writes:

> On 2026-10-07 22:15, Collin Funk wrote:
>> Given the preceeding checks in that if statement, I suspect
>> Paul meant to write something like this:
>> ...
>> -                  && 0 <= lseek (fd, hi_pos, SEEK_CUR))
>> +                  && 0 <= lseek (fd, hi_pos - current_pos, SEEK_CUR))
>
> Yes, I should have written either that, or 'lseek (fd, hi_pos, SEEK_SET)'.
>
> Looking into nearby code I see another bug. That "end_pos %
> (STP_BLKSIZE (&fstatus->st) + 1)" is bogus: why add 1 to the
> blocksize? In the unlikely event that end_pos is a multiple of both
> page_size and of (STP_BLKSIZE (&fstatus->st) + 1), this will surely do
> the wrong thing.

I thought it looked a bit strange as well. But I didn't look into it
enough to comment on it. :)

> Also, the two separate calls to lseek are awkward.

Looks good to me.

> I installed the attached patch to fix all this. If someone has the energy to 
> add a test case that would be nice.

I pushed the attached patch adding some tests. Perhaps a bit overkill,
but mistyping a SEEK_* macro seems a bit too easy to do. Hopefully, it
will catch any similar issues in the future.

Closing this report now. Thank you both.

Collin

>From 77e7674add55be35d83e175c116425735b2f1f74 Mon Sep 17 00:00:00 2001
Message-ID: <77e7674add55be35d83e175c116425735b2f1f74.1791445486.git.collin.fu...@gmail.com>
From: Collin Funk <[email protected]>
Date: Thu, 8 Oct 2026 00:39:50 -0700
Subject: [PATCH] tests: wc: add a test for the fix in the previous commit

* tests/wc/page-size.sh: New file.
* tests/local.mk (all_tests): Add the new test.
---
 tests/local.mk        |  1 +
 tests/wc/page-size.sh | 54 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)
 create mode 100755 tests/wc/page-size.sh

diff --git a/tests/local.mk b/tests/local.mk
index c513c0756..06d8f934d 100644
--- a/tests/local.mk
+++ b/tests/local.mk
@@ -312,6 +312,7 @@ all_tests =					\
   tests/cut/bounded-memory.sh			\
   tests/cut/cut-huge-range.sh			\
   tests/wc/mb-non-utf8.sh			\
+  tests/wc/page-size.sh				\
   tests/wc/wc.pl				\
   tests/wc/wc-cpu.sh				\
   tests/wc/wc-files0-from.pl			\
diff --git a/tests/wc/page-size.sh b/tests/wc/page-size.sh
new file mode 100755
index 000000000..562690970
--- /dev/null
+++ b/tests/wc/page-size.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+# Test 'wc' on files with a size that is a multiple of the system's page size.
+
+# Copyright (C) 2026 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ wc
+
+# Get the systems actual page size if possible. Otherwise 4096 is good enough.
+page_size=$(getconf PAGESIZE || echo 4096)
+
+for multiple in $(seq 3); do
+  head -c $page_size /dev/zero >> file || framework_failure_
+  # Count the entire file as a sanity check.
+  wc -c < file > out 2> err || fail=1
+  file_size=$(($multiple * $page_size))
+  cat <<EOF > exp || framework_failure_
+$file_size
+EOF
+  compare exp out || fail=1
+  compare /dev/null err || fail=1
+  # Test 'wc -c' when standard input has a nonzero offset.
+  # This would give an incorrect result from coreutils-8.24
+  # to coreutils-9.12.
+  skip=$(($multiple * 100))
+  (head -c $skip; wc -c > out 2> err) < file || fail=1
+  cat <<EOF > exp || framework_failure_
+$(($file_size - $skip))
+EOF
+  compare exp out || fail=1
+  compare /dev/null err || fail=1
+  # Likewise.
+  (head -c $page_size; wc -c > out 2> err) < file || fail=1
+  cat <<EOF > exp || framework_failure_
+$(($file_size - $page_size))
+EOF
+  compare exp out || fail=1
+  compare /dev/null err || fail=1
+done
+
+Exit $fail
-- 
2.56.0

Reply via email to