mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-03 05:20:16 +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:
parent
abafc12d3d
commit
0e66d88fa2
1 changed files with 36 additions and 6 deletions
|
@ -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 '-':
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue