* 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


Reply via email to