calling code should not rely on this function returning 0
when *INVALID represents a non-overflow error. */
int indeterminate = 0;
- uintmax_t n = indeterminate;
- char *suffix;
static char const suffixes[] = "bcEGkKMPQRTwYZ0";
- strtol_error e = xstrtoumax (str, &suffix, 10, &n, suffixes);
- intmax_t result;
+ intmax_t result = 1;
+ bool overflow = false;
+ bool warn_zero_multiplier = false;
+ strtol_error e;
- if ((e & ~LONGINT_OVERFLOW) == LONGINT_INVALID_SUFFIX_CHAR
- && *suffix == 'B' && str < suffix && suffix[-1] != 'B')
+ while (true)
{
- suffix++;
- if (!*suffix)
- e &= ~LONGINT_INVALID_SUFFIX_CHAR;
- }
+ uintmax_t n = indeterminate;
+ char *suffix;
+ e = xstrtoumax (str, &suffix, 10, &n, suffixes);
- if ((e & ~LONGINT_OVERFLOW) == LONGINT_INVALID_SUFFIX_CHAR
- && *suffix == 'x')
- {
- strtol_error f = LONGINT_OK;
- intmax_t o = parse_integer (suffix + 1, &f);
- if ((f & ~LONGINT_OVERFLOW) != LONGINT_OK)
+ if ((e & ~LONGINT_OVERFLOW) == LONGINT_INVALID_SUFFIX_CHAR
+ && *suffix == 'B' && str < suffix && suffix[-1] != 'B')
{
- e = f;
- result = indeterminate;
+ suffix++;
+ if (!*suffix)
+ e &= ~LONGINT_INVALID_SUFFIX_CHAR;
}
- else if (ckd_mul (&result, n, o)
- || (result != 0 && ((e | f) & LONGINT_OVERFLOW)))
+
+ bool multiply
+ = ((e & ~LONGINT_OVERFLOW) == LONGINT_INVALID_SUFFIX_CHAR
+ && *suffix == 'x');
+ if (multiply)
+ e &= ~LONGINT_INVALID_SUFFIX_CHAR;
+
+ if ((e & ~LONGINT_OVERFLOW) != LONGINT_OK)
{
+ if (! (e & LONGINT_OVERFLOW) && n <= INTMAX_MAX)
+ {
+ *invalid = e;
+ return indeterminate;
+ }
e = LONGINT_OVERFLOW;
- result = INTMAX_MAX;
}
- else
+
+ if (n == 0)
+ result = 0;
+ else if (result != 0)
{
- if (result == 0 && STRPREFIX (str, "0x"))
- diagnose (0, _("warning: %s is a zero multiplier; "
- "use %s if that is intended"),
- quote_n (0, "0x"), quote_n (1, "00x"));
- e = LONGINT_OK;
+ intmax_t product;
+ if ((e & LONGINT_OVERFLOW)
+ || overflow
+ || ckd_mul (&product, result, n))
+ overflow = true;
+ else
+ result = product;
}
+
+ if (multiply && STRPREFIX (str, "0x"))
+ warn_zero_multiplier = true;
+
+ if (! multiply)
+ break;
+ str = suffix + 1;
}
- else if (n <= INTMAX_MAX)
- result = n;
- else
+
+ if (result == 0)
+ {
+ if (warn_zero_multiplier)
+ diagnose (0, _("warning: %s is a zero multiplier; "
+ "use %s if that is intended"),
+ quote_n (0, "0x"), quote_n (1, "00x"));
+ e = LONGINT_OK;
+ }
+ else if (overflow)
{
e = LONGINT_OVERFLOW;
result = INTMAX_MAX;
compare expected2 out2 || fail=1
done
-# Check recursive integer parsing
+# Check multiplicative integer parsing
for oseek in '1x2x4 oflag=seek_bytes' '1Bx2x4' '1Bx8' '2Bx4B' '2x4B'; do
# seek bytes
echo abcdefghijklm |
compare expected out || fail=1
done
+# Check that long multiplier chains don't exhaust a restricted stack.
+if (ulimit -S -s 256 && dd if=/dev/null count=1) 2>/dev/null; then
+ long_multiplier=$(yes 1x | head -n 10000 | tr -d '\n')1 || framework_failure_
+ (ulimit -S -s 256 &&
+ dd count="$long_multiplier" if=/dev/null of=/dev/null status=none) || fail=1
+fi
+
# 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