]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
dd: fix parsing of numbers with more than two multipliers
authorPádraig Brady <P@draigBrady.com>
Sat, 10 Jun 2023 13:18:00 +0000 (14:18 +0100)
committerPádraig Brady <P@draigBrady.com>
Sun, 11 Jun 2023 22:10:34 +0000 (23:10 +0100)
* src/dd.c (parse_integer): Use recursion to support more than two
multipliers.  Also protect suffix[-1] access to ensure we don't
inspect before the passed string.
* tests/dd/bytes.sh: Add test cases.
* doc/coreutils.texi (dd invocation): Note the support for specifying
many multipliers in a number.
* NEWS: Mention the bug fix.
Fixes https://bugs.debian.org/1037275

NEWS
doc/coreutils.texi
src/dd.c
tests/dd/bytes.sh

diff --git a/NEWS b/NEWS
index e47701962aefb14b509a9321eb6ffecaaea07ddf..7df9ff5b01c54ed88e91ef41887c4b15bbbe0209 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,10 @@ GNU coreutils NEWS                                    -*- outline -*-
   cksum again diagnoses read errors in its default CRC32 mode.
   [bug introduced in coreutils-9.0]
 
+  dd again supports more than two multipliers for numbers.
+  Previously numbers of the form '1024x1024x32' gave "invalid number" errors.
+  [bug introduced in coreutils-9.1]
+
   factor, numfmt, and tsort now diagnose read errors on the input.
   [This bug was present in "the beginning".]
 
index e9d7b8eb49a76c75a6a2443c100ff035b6b423a3..d6918e8ad5ec65c5ccda8799cf9801b1b4431e9a 100644 (file)
@@ -9818,7 +9818,7 @@ can be followed by a multiplier: @samp{b}=512, @samp{c}=1,
 standard block size suffixes like @samp{k}=1024 (@pxref{Block size}).
 These multipliers are GNU extensions to POSIX, except that
 POSIX allows @var{bytes} to be followed by @samp{k}, @samp{b}, and
-@samp{x@var{m}}.
+@samp{x@var{m}}. Note @samp{x@var{m}} can be used more than once in a number.
 Block sizes (i.e., specified by @var{bytes} strings) must be nonzero.
 
 Any block size you specify via @samp{bs=}, @samp{ibs=}, @samp{obs=}, @samp{cbs=}
index 665fc831c50caf217ec25c2458e29c91e5ad9aff..f06d4eba2b27ae4587485e47c54625ecb03c65ff 100644 (file)
--- a/src/dd.c
+++ b/src/dd.c
@@ -1428,7 +1428,7 @@ parse_integer (char const *str, strtol_error *invalid)
   intmax_t result;
 
   if ((e & ~LONGINT_OVERFLOW) == LONGINT_INVALID_SUFFIX_CHAR
-      && suffix[-1] != 'B' && *suffix == 'B')
+      && *suffix == 'B' && str < suffix && suffix[-1] != 'B')
     {
       suffix++;
       if (!*suffix)
@@ -1436,10 +1436,10 @@ parse_integer (char const *str, strtol_error *invalid)
     }
 
   if ((e & ~LONGINT_OVERFLOW) == LONGINT_INVALID_SUFFIX_CHAR
-      && *suffix == 'x' && ! (suffix[-1] == 'B' && strchr (suffix + 1, 'B')))
+      && *suffix == 'x')
     {
-      uintmax_t o;
-      strtol_error f = xstrtoumax (suffix + 1, &suffix, 10, &o, suffixes);
+      strtol_error f = LONGINT_OK;
+      intmax_t o = parse_integer (suffix + 1, &f);
       if ((f & ~LONGINT_OVERFLOW) != LONGINT_OK)
         {
           e = f;
index 01753d6a0e8282bd517527ef2d5e6d45e5b22b54..d6105ccfda749145a8349b22a824c894010e7e1e 100755 (executable)
@@ -60,4 +60,16 @@ for operands in "oseek=8B" "seek=8 oflag=seek_bytes"; do
   compare expected2 out2 || fail=1
 done
 
+# Check recursive integer parsing
+for oseek in '1x2x4 oflag=seek_bytes' '1Bx2x4' '1Bx8' '2Bx4B' '2x4B'; do
+  # seek bytes
+  echo abcdefghijklm |
+    dd oseek=$oseek bs=5 > out 2> /dev/null || fail=1
+  compare expected out || fail=1
+done
+
+# Negative checks for integer parsing
+for count in B B1 Bx1 KBB BB KBb KBx x1 1x 1xx1; do
+  returns_ 1 dd count=$count </dev/null >/dev/null || fail=1
+done
 Exit $fail