Skip to content

Commit

Permalink
Allow much larger exponent for explicitly exact numbers
Browse files Browse the repository at this point in the history
Addresses #898
We do set a somewhat arbitrary limit for the exponent (65535 now)
to avoid accidentally put such numbers (or potential DoS attack)
that will cause to hog large amount of memory.
  • Loading branch information
shirok committed Jan 1, 2025
1 parent 547e669 commit 1460767
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 7 deletions.
5 changes: 5 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
2024-12-31 Shiro Kawai <[email protected]>

* src/number.c (read_real): Allow much larger exponent for explicitly
exact numbers. https://github.com/shirok/Gauche/issues/898

2024-12-29 Shiro Kawai <[email protected]>

* src/read.c (read_number): Propagate numeric parser error message.
Expand Down
14 changes: 11 additions & 3 deletions src/number.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ int Scm_IsInf(double x)
memory. So I assume it is reasonable to limit its range. */
#define MAX_EXPONENT 325

/* If the number if explicitly exact, we can allow much larger exponent---
theoretically as much as the memory can hold. In reality, though,
exact numbers too big are too heavy to handle. This is somewhat
arbitrary limitaition:
*/
#define MAX_EXACT_EXPONENT 65535

/* Linux gcc have those, but the declarations aren't included unless
__USE_ISOC9X is defined. Just in case. */
#ifdef HAVE_TRUNC
Expand Down Expand Up @@ -4723,10 +4730,12 @@ static ScmObj read_real(const char **strp, int *lenp,
if (!isdigit(c)) break;
underscore = FALSE;
if (!exp_overflow) {
/* We limit the range of exponent, so this never overflow. */
exponent = exponent * 10 + (c - '0');
/* Check obviously wrong exponent range. More subtle check
will be done later. */
if (exponent >= MAX_EXPONENT) {
if ((ctx->exactness == EXACT && exponent >= MAX_EXACT_EXPONENT)
|| (ctx->exactness != EXACT && exponent >= MAX_EXPONENT)) {
exp_overflow = TRUE;
}
}
Expand All @@ -4739,8 +4748,7 @@ static ScmObj read_real(const char **strp, int *lenp,
ratnum, such large (or small) exponent is highly unusual
and we assume we can report implementation limitation
violation. */
return numerr("Such an exact number is out of implementation limitation",
ctx);
return numerr("Exact number exponent is too big", ctx);
}
if (exp_minusp || SCM_EQ(fraction, SCM_MAKE_INT(0))) {
return Scm_MakeFlonum(minusp? -0.0:0.0);
Expand Down
10 changes: 6 additions & 4 deletions test/number.scm
Original file line number Diff line number Diff line change
Expand Up @@ -474,11 +474,13 @@
(test* "exact fractonal number" (- (real-expt 10 296))
(string->number "#e-0.0001e300"))

;; This depends on MAX_EXACT_EXPONENT in number.c
(test* "exact fractonal number" (real-expt 10 1000)
(read-from-string "#e1e1000"))
(test* "exact fractonal number" (real-expt 10 -10000)
(read-from-string "#e1e-10000"))
(test* "exact fractonal number" (test-error)
(read-from-string "#e1e330"))
(test* "exact fractonal number" (test-error)
(read-from-string "#e1e-330"))

(read-from-string "#e1e-100000"))

;;------------------------------------------------------------------
(test-section "complex reader")
Expand Down

0 comments on commit 1460767

Please sign in to comment.