1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-03 13:20:26 +02:00

(scm_istr2int): Correction to bignum size calculation for

bases other than 2, 10, 16.  This avoids overflows, in particular in
octal string->number and constants (other bases are undocumented, but
reach here so may as well work).
This commit is contained in:
Kevin Ryde 2004-12-08 22:50:09 +00:00
parent abafc12d3d
commit 0e66d88fa2

View file

@ -2331,12 +2331,42 @@ scm_istr2int (char *str, long len, long radix)
if (len < 6) if (len < 6)
return scm_small_istr2int (str, len, radix); return scm_small_istr2int (str, len, radix);
if (16 == radix) /* table[] is the number of bits used by each digit in the given base,
j = 1 + (4 * len * sizeof (char)) / (SCM_BITSPERDIG); ie. log(base)/log(2). A scale factor of 25 is applied, so eg. base 8
else if (10 <= radix) has 75 for 3 bits per digit. When the number is not exact (any non
j = 1 + (84 * len * sizeof (char)) / (SCM_BITSPERDIG * 25); power-of-2 base) it's rounded up, ensuring the size calculated will be
else no less than what's needed. Eg. 25*log(10)/log(2) is 83.04 which gets
j = 1 + (len * sizeof (char)) / (SCM_BITSPERDIG); rounded up to 84. The following spot of perl generates the table
use POSIX;
foreach $i (2 .. 16) {
print POSIX::ceil(log($i)/log(2)*25),", /","* $i *","/\n";
}
The factor 25 is more or less arbitrary, it gives enough precision and
is what the code had in the past for base 10. */
{
static const unsigned table[] = {
25, /* 2 */
40, /* 3 */
50, /* 4 */
59, /* 5 */
65, /* 6 */
71, /* 7 */
75, /* 8 */
80, /* 9 */
84, /* 10 */
87, /* 11 */
90, /* 12 */
93, /* 13 */
96, /* 14 */
98, /* 15 */
100, /* 16 */
};
/* FIXME: What is sizeof(char) for? */
j = 1 + (table[radix-2] * len * sizeof (char)) / (SCM_BITSPERDIG * 25);
}
switch (str[0]) switch (str[0])
{ /* leading sign */ { /* leading sign */
case '-': case '-':