* src/factor.c (mulredc2): Add the carry to p1, which is the high word of a two-word integer created by summing two single-word integers and is therefore unable to overflow, instead of using a low word r0, which may wrap around by adding the carry. * tests/factor/mulredc2-infloop.sh: New file. * tests/local.mk (all_tests): Add the new test. * NEWS: Mention the bug fix.
Discovered by Anthropic's OSS Scanner, as bug ANT-2026-CFUR0JKW. --- NEWS | 4 ++++ src/factor.c | 4 ++-- tests/factor/mulredc2-infloop.sh | 30 ++++++++++++++++++++++++++++++ tests/local.mk | 1 + 4 files changed, 37 insertions(+), 2 deletions(-) create mode 100755 tests/factor/mulredc2-infloop.sh diff --git a/NEWS b/NEWS index b315ce7f4..e5e81191f 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,10 @@ GNU coreutils NEWS -*- outline -*- non-space characters, or the number itself when followed by spaces. [bugs introduced in coreutils-9.8] + 'factor' no longer infinite loops with certain large numbers, e.g., + 146077762747232966952776282887314548659. + [bugs introduced in coreutils-8.20] + '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 e08060cba..7dd22a310 100644 --- a/src/factor.c +++ b/src/factor.c @@ -1122,7 +1122,7 @@ mulredc2 (mp_limb_t *r1p, q = mi * t0; umul_ppmm (p1, p0, q, m0); umul_ppmm (s1, s0, q, m1); - r0 += (t0 != 0); /* Carry */ + p1 += (t0 != 0); /* Carry */ add_ssaaaa (r1, r0, r1, r0, 0, p1); add_ssaaaa (r1, r0, r1, r0, 0, t1); add_ssaaaa (r1, r0, r1, r0, s1, s0); @@ -1149,7 +1149,7 @@ mulredc2 (mp_limb_t *r1p, add_ssaaaa (r1, r0, s1, s0, 0, r1); umul_ppmm (p1, p0, q, m0); umul_ppmm (s1, s0, q, m1); - r0 += (t0 != 0); /* Carry */ + p1 += (t0 != 0); /* Carry */ add_ssaaaa (r1, r0, r1, r0, 0, p1); add_ssaaaa (r1, r0, r1, r0, 0, t1); add_ssaaaa (r1, r0, r1, r0, s1, s0); diff --git a/tests/factor/mulredc2-infloop.sh b/tests/factor/mulredc2-infloop.sh new file mode 100755 index 000000000..1c05ce561 --- /dev/null +++ b/tests/factor/mulredc2-infloop.sh @@ -0,0 +1,30 @@ +#!/bin/sh +# Test an invocation that would infinite loop due to a missing +# overflow check in mulredc2. + +# Copyright (C) 2026 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src +print_ver_ factor + + +printf '%s: %s %s\n' 146077762747232966952776282887314548659 37853 \ + 3859080198325970648370704643946703 >exp || framework_failure_ +timeout 10 factor 146077762747232966952776282887314548659 >err >out || fail=1 +compare exp out || fail=1 +compare /dev/null err || fail=1 + +Exit $fail diff --git a/tests/local.mk b/tests/local.mk index 7d75b4b5a..3cac910af 100644 --- a/tests/local.mk +++ b/tests/local.mk @@ -375,6 +375,7 @@ all_tests = \ tests/expr/expr-multibyte.pl \ tests/factor/factor.pl \ tests/factor/factor-parallel.sh \ + tests/factor/mulredc2-infloop.sh \ tests/misc/false-status.sh \ tests/fold/fold-characters.sh \ tests/fold/fold-nbsp.sh \ -- 2.56.0
