copying to non-NFS files from NFSv4 files with trivial ACLs.
[bug introduced in coreutils-9.6]
+ od --strings with -N now works correctly. Previously od might
+ write a NUL byte after a heap buffer, or output invalid addresses.
+ [These bugs were present in "the beginning".]
+
sort with key character offsets of SIZE_MAX, could induce
a read of 1 byte before an allocated heap buffer. For example:
'sort +0.18446744073709551615R input' on 64 bit systems.
}
/* STRINGS mode. Find each "string constant" in the input.
- A string constant is a run of at least 'string_min' ASCII
- graphic (or formatting) characters terminated by a null.
+ A string constant is a run of at least STRING_MIN
+ printable characters terminated by a NUL or END_OFFSET.
Based on a function written by Richard Stallman for a
traditional version of od. Return true if successful. */
static bool
dump_strings (void)
{
- idx_t bufsize = MAX (100, string_min);
+ idx_t bufsize = MAX (100, string_min + 1);
char *buf = xmalloc (bufsize);
uintmax_t address = n_bytes_to_skip;
bool ok = true;
while (true)
{
- idx_t i;
- int c;
-
- /* See if the next 'string_min' chars are all printing chars. */
- tryline:
+ idx_t i = 0;
+ int c = 1; /* Init to 1 so can distinguish if NUL read. */
if (limit_bytes_to_format
- && (end_offset < string_min || end_offset - string_min <= address))
+ && (end_offset < string_min || end_offset - string_min < address))
break;
- for (i = 0; i < string_min; i++)
- {
- ok &= read_char (&c);
- address++;
- if (c < 0)
- {
- free (buf);
- return ok;
- }
- if (! isprint (c))
- /* Found a non-printing. Try again starting with next char. */
- goto tryline;
- buf[i] = c;
- }
-
- /* We found a run of 'string_min' printable characters.
- Now see if it is terminated with a null byte. */
+ /* Store consecutive printable characters to BUF. */
while (!limit_bytes_to_format || address < end_offset)
{
- if (i == bufsize)
+ if (i == bufsize - 1)
buf = xpalloc (buf, &bufsize, 1, -1, sizeof *buf);
ok &= read_char (&c);
- address++;
if (c < 0)
{
free (buf);
return ok;
}
+ address++;
+ buf[i++] = c;
if (c == '\0')
- break; /* It is; print this string. */
+ break; /* Print this string. */
if (! isprint (c))
- goto tryline; /* It isn't; give up on this string. */
- buf[i++] = c; /* String continues; store it all. */
+ {
+ c = -1; /* Give up on this string. */
+ break;
+ }
}
- /* If we get here, the string is all printable and null-terminated,
- so print it. It is all in 'buf' and 'i' is its length. */
+ if (c == -1 || i - !c < string_min)
+ continue;
+
buf[i] = 0;
- format_address (address - i - 1, ' ');
+
+ /* If we get here, the string is all printable, so print it. */
+
+ format_address (address - i, ' ');
for (i = 0; (c = buf[i]); i++)
{
print_ver_ od
echo abcdefg > in || framework_failure_
-
-
(od -An -N3 -c; od -An -N3 -c) < in > out
cat <<EOF > exp || framework_failure_
a b c
EOF
compare exp out || fail=1
+# coreutils <= 9.7 would buffer overflow with
+# a single NUL byte after the heap buffer
+printf '%100s' | od -N100 -S1 > out || fail=1
+printf '%07o %100s\n' 0 '' > exp || framework_failure_
+compare exp out || fail=1
+
+# coreutils <= 9.7 would output nothing
+printf '%100s' | od -N10 -S10 > out || fail=1
+printf '%07o %10s\n' 0 '' > exp || framework_failure_
+compare exp out || fail=1
+
+# coreutils <= 9.7 would output an invalid address
+printf '%100s' | od -N10 -S1 > out || fail=1
+printf '%07o %10s\n' 0 '' > exp || framework_failure_
+compare exp out || fail=1
+
+# Ensure -S limits appropriately
+printf '%10s\000' | od -N11 -S11 > out || fail=1
+compare /dev/null out || fail=1
+printf '%10s\000' | od -S11 > out || fail=1
+compare /dev/null out || fail=1
+printf '%10s' | od -S10 > out || fail=1 # Ignore unterminated at EOF?
+compare /dev/null out || fail=1
+printf '\001%10s\000%10s\000' | od -S10 > out || fail=1
+printf '%07o %10s\n' 1 '' 12 '' > exp || framework_failure_
+compare exp out || fail=1
+
Exit $fail