1
0
mirror of https://git.savannah.gnu.org/git/coreutils.git synced 2026-10-24 02:08:57 +03:00

wc: fix buffer boundary calculations

Problem reported by Scott Orme (Bug#82013).
* src/wc.c (wc): Fix calculations of file sizes vs page size
vs block size.
This commit is contained in:
Paul Eggert
2026-10-07 23:14:19 -07:00
parent c00f9f8f99
commit c3709a88f2
3 changed files with 21 additions and 11 deletions

4
NEWS
View File

@@ -33,6 +33,10 @@ GNU coreutils NEWS -*- outline -*-
in GB18030 locales, and word counts in UTF-8 locales.
[bug introduced in coreutils-9.5]
'wc -c' no longer miscounts bytes when stdin has a nonzero offset
into a seekable file whose size is a multiple of the page size.
[bug introduced in coreutils-8.24]
** New Features
'env' and 'printenv' now support the --quoting-style option

View File

@@ -577,6 +577,7 @@ Santiago Vila Doncel sanvila@unex.es
Savochkin Andrey Vladimirovich saw@msu.ru
Scott Harrison scott.gnu.2009@scottrix.co.uk
Scott Lurndal slurn@griffin.engr.sgi.com
Scott Orme scott.orme@gmail.com
Sébastien Maret smaret@umich.edu
Sergei Steshenko sergstesh@yahoo.com
Sergey Vlasov vsu@altlinux.org

View File

@@ -428,7 +428,7 @@ wc (int fd, char const *file_x, struct fstatus *fstatus)
;
else if (end_pos % page_size)
{
/* We only need special handling of /proc and /sys files etc.
/* We need special handling of /proc and /sys files etc. only
when they're a multiple of PAGE_SIZE. In the common case
for files with st_size not a multiple of PAGE_SIZE,
it's more efficient and accurate to use st_size.
@@ -436,20 +436,25 @@ wc (int fd, char const *file_x, struct fstatus *fstatus)
Be careful here. The current position may actually be
beyond the end of the file. As in the example above. */
bytes = end_pos < current_pos ? 0 : end_pos - current_pos;
if (bytes && 0 <= lseek (fd, bytes, SEEK_CUR))
skip_read = true;
else
bytes = 0;
if (current_pos < end_pos)
{
bytes = end_pos - current_pos;
skip_read = true;
}
}
else
else if (0 < end_pos)
{
off_t hi_pos = (end_pos
- end_pos % (STP_BLKSIZE (&fstatus->st) + 1));
if (0 <= current_pos && current_pos < hi_pos
&& 0 <= lseek (fd, hi_pos, SEEK_CUR))
off_t ep_1 = end_pos - 1;
off_t hi_pos = ep_1 - ep_1 % STP_BLKSIZE (&fstatus->st);
if (current_pos < hi_pos)
bytes = hi_pos - current_pos;
}
if (0 < bytes && lseek (fd, bytes, SEEK_CUR) < 0)
{
bytes = 0;
skip_read = false;
}
}
if (! skip_read)