1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-04-19 10:15:48 +02:00

factor: fix integer validation and GMP fallback

In the recent factor rewrite, the GMP code
wasn't actually used; just an error was printed
on integer overflow.  While fixing that it was noticed
that correct input validation wasn't done in all cases
when falling back to the GMP code.

* src/factor.c (print_factors) Fallback to GMP on overflow.
(strto2uintmax): Scan the string for invalid characters,
so that case can be detected independently of overflow.
Return an error when an empty string is passed.
Also allow leading spaces and '+' in input numbers.
* tests/misc/factor.pl: Ensure the GMP code is exercised
when compiled in. Also add a test to verify leading
spaces and '+' are allowed.
This commit is contained in:
Pádraig Brady
2012-10-08 15:48:43 +01:00
parent cf9cd8958b
commit 024a1d572c
2 changed files with 45 additions and 6 deletions

View File

@@ -2222,14 +2222,30 @@ static strtol_error
strto2uintmax (uintmax_t *hip, uintmax_t *lop, const char *s)
{
unsigned int lo_carry;
uintmax_t hi, lo;
uintmax_t hi = 0, lo = 0;
strtol_error err;
strtol_error err = LONGINT_INVALID;
hi = lo = 0;
/* Skip initial spaces and '+'. */
for (;;)
{
unsigned int c = *s++;
char c = *s;
if (c == ' ')
s++;
else if (c == '+')
{
s++;
break;
}
else
break;
}
/* Initial scan for invalid digits. */
const char *p = s;
for (;;)
{
unsigned int c = *p++;
if (c == 0)
break;
@@ -2238,9 +2254,17 @@ strto2uintmax (uintmax_t *hip, uintmax_t *lop, const char *s)
err = LONGINT_INVALID;
break;
}
c -= '0';
err = LONGINT_OK; /* we've seen at least one valid digit */
}
for (;err == LONGINT_OK;)
{
unsigned int c = *s++;
if (c == 0)
break;
c -= '0';
if (UNLIKELY (hi > ~(uintmax_t)0 / 10))
{
@@ -2343,6 +2367,10 @@ print_factors (const char *input)
}
break;
case LONGINT_OVERFLOW:
/* Try GMP. */
break;
default:
error (0, 0, _("%s is not a valid positive integer"), quote (input));
return false;

View File

@@ -28,6 +28,7 @@ my @Tests =
(
['1', '9', {OUT => '3 3'}],
['1a', '7', {OUT => '7'}],
['1b', ' +7', {OUT => '7'}],
['2', '4294967291', {OUT => '4294967291'}],
['3', '4294967292', {OUT => '2 2 3 3 7 11 31 151 331'}],
['4', '4294967293', {OUT => '9241 464773'}],
@@ -74,6 +75,16 @@ my @Tests =
['bug-2012-e', '17754345703', {OUT => '94219 188437'}],
);
# If we have GMP support, append tests to exercise it.
system "grep -w HAVE_GMP $ENV{CONFIG_HEADER} > /dev/null" == 0
and push (@Tests,
['bug-gmp-2_sup_128', '340282366920938463463374607431768211456',
{OUT => '2 'x127 . '2'}],
['bug-gmp-2_sup_256',
'115792089237316195423570985008687907853'
. '269984665640564039457584007913129639936',
{OUT => '2 'x255 . '2'}]);
# Prepend the command line argument and append a newline to end
# of each expected 'OUT' string.
my $t;
@@ -81,7 +92,7 @@ my $t;
Test:
foreach $t (@Tests)
{
my $arg1 = $t->[1];
(my $arg1 = $t->[1]) =~ s| *\+?||;
# Don't fiddle with expected OUT string if there's a nonzero exit status.
foreach my $e (@$t)