mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-02 04:40:29 +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)
|
||||
return scm_small_istr2int (str, len, radix);
|
||||
|
||||
if (16 == radix)
|
||||
j = 1 + (4 * len * sizeof (char)) / (SCM_BITSPERDIG);
|
||||
else if (10 <= radix)
|
||||
j = 1 + (84 * len * sizeof (char)) / (SCM_BITSPERDIG * 25);
|
||||
else
|
||||
j = 1 + (len * sizeof (char)) / (SCM_BITSPERDIG);
|
||||
/* table[] is the number of bits used by each digit in the given base,
|
||||
ie. log(base)/log(2). A scale factor of 25 is applied, so eg. base 8
|
||||
has 75 for 3 bits per digit. When the number is not exact (any non
|
||||
power-of-2 base) it's rounded up, ensuring the size calculated will be
|
||||
no less than what's needed. Eg. 25*log(10)/log(2) is 83.04 which gets
|
||||
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])
|
||||
{ /* leading sign */
|
||||
case '-':
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue