* src/factor.c (strtouuint): Return LONGINT_OVERFLOW only if all of the
characters are digits; otherwise, return LONGINT_INVALID.
* tests/factor/factor.pl: Add two test cases.
* NEWS: Mention the bug fix.
Discovered by Anthropic's OSS Scanner, as bug ANT-2026-IZ8PFQ7Q.
---
NEWS | 5 +++++
src/factor.c | 20 ++++++++++++++------
tests/factor/factor.pl | 13 +++++++++++++
3 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/NEWS b/NEWS
index 97986cf13..8c4babc18 100644
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,11 @@ GNU coreutils NEWS -*-
outline -*-
the \u0085 (next line) character as a separator on non-GLIBC platforms.
[bug introduced in coreutils-9.11]
+ 'factor' no longer treats inputs requiring the use of arbitrary-precision
+ integers followed by a non-numeric suffix as zero if the suffix includes
+ non-space characters, or the number itself when followed by spaces.
+ [bugs introduced in coreutils-9.8]
+
'fold' no longer prematurely wraps lines with a wide character towards
the start of a line, followed by multiple backspaces. Also backspaces
after a tab character are accounted for correctly.
diff --git a/src/factor.c b/src/factor.c
index 2bfa18ecc..e08060cba 100644
--- a/src/factor.c
+++ b/src/factor.c
@@ -1635,7 +1635,9 @@ mp_factor (mpz_t t)
}
/* Convert to *U the value represented by S, and return LONGINT_OK.
- However, on error simply return a value other than LONGINT_OK. */
+ Return LONGINT_OVERFLOW if S is composed of all digits but is too
+ large to fit in *U, otherwise LONGINT_INVALID if S is not a valid
+ positive integer. */
static strtol_error
strtouuint (uuint *u, char const *s)
{
@@ -1647,7 +1649,7 @@ strtouuint (uuint *u, char const *s)
for (; LIKELY (0 <= *s - '0' && *s - '0' <= 9); s++)
{
if (UNLIKELY (ckd_mul (&hi, hi, 10)))
- return LONGINT_OVERFLOW;
+ goto overflow;
int lo_carry = (lo >> (W_TYPE_SIZE - 3)) + (lo >> (W_TYPE_SIZE - 1));
lo_carry += 10 * lo < 2 * lo;
@@ -1655,7 +1657,7 @@ strtouuint (uuint *u, char const *s)
lo = 10 * lo;
lo_carry += ckd_add (&lo, lo, *s - '0');
if (UNLIKELY (ckd_add (&hi, hi, lo_carry)))
- return LONGINT_OVERFLOW;
+ goto overflow;
}
if (UNLIKELY (*s))
@@ -1663,6 +1665,11 @@ strtouuint (uuint *u, char const *s)
*u = make_uuint (hi, lo);
return LONGINT_OK;
+
+ overflow:
+ /* Since s[0] caused the overflow, we know it is a valid integer. */
+ s++;
+ return s[strspn (s, "0123456789")] ? LONGINT_INVALID : LONGINT_OVERFLOW;
}
/* FACTOR_PIPE_BUF is chosen to give good performance,
@@ -1892,6 +1899,7 @@ print_factors (char const *input)
way. */
uuint u;
strtol_error err = strtouuint (&u, str);
+ mpz_t t;
switch (err)
{
@@ -1905,7 +1913,9 @@ print_factors (char const *input)
FALLTHROUGH;
case LONGINT_OVERFLOW:
/* Try GMP. */
- break;
+ if (0 <= mpz_init_set_str (t, str, 10))
+ break;
+ FALLTHROUGH;
case LONGINT_INVALID:
case LONGINT_INVALID_SUFFIX_CHAR:
@@ -1916,8 +1926,6 @@ print_factors (char const *input)
}
devmsg ("[using arbitrary-precision arithmetic] ");
- mpz_t t;
- mpz_init_set_str (t, str, 10);
if (MP_FACTOR_USING_POLLARD_RHO_N_MAX < mp_size (t))
xalloc_die ();
diff --git a/tests/factor/factor.pl b/tests/factor/factor.pl
index 524c57baa..8f4963530 100755
--- a/tests/factor/factor.pl
+++ b/tests/factor/factor.pl
@@ -84,6 +84,19 @@ my @Tests =
{OUT => '5 4073 18899 522591721 63874247821'}],
['bug-gmp-2_sup_128', '340282366920938463463374607431768211456',
{OUT => '2 'x127 . '2'}],
+
+ # v9.8 to v9.12 inclusive would treat these as 0.
+ ['bug-gmp-2_sup_128-suffix-char',
+ '340282366920938463463374607431768211456a',
+ {EXIT => 1},
+ {ERR => ("$prog: '340282366920938463463374607431768211456a'"
+ . " is not a valid positive integer\n")}],
+ ['bug-gmp-2_sup_128-suffix-space',
+ '340282366920938463463374607431768211456 ',
+ {EXIT => 1},
+ {ERR => ("$prog: '340282366920938463463374607431768211456 '"
+ . " is not a valid positive integer\n")}],
+
['bug-gmp-2_sup_256',
'115792089237316195423570985008687907853'
. '269984665640564039457584007913129639936',
--
2.56.0