Skip to content

Commit 15b7e0a

Browse files
authored
Check exponent overflow/underflow strictly in AddExponent (#368)
BigDecimal's exponent should not overflow/underflow long. To check, BigDecimal restricts the range of vp->exponent. The calculation is complicated and not correct when BASE_FIG is 4.
1 parent 3005344 commit 15b7e0a

1 file changed

Lines changed: 13 additions & 18 deletions

File tree

ext/bigdecimal/bigdecimal.c

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@
3939
#define SIGNED_VALUE_MIN INTPTR_MIN
4040
#define MUL_OVERFLOW_SIGNED_VALUE_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, SIGNED_VALUE_MIN, SIGNED_VALUE_MAX)
4141

42+
/* max_value = 0.9999_9999_9999E[exponent], exponent <= SIGNED_VALUE_MAX */
43+
#define VP_EXPONENT_MAX (SIGNED_VALUE_MAX / BASE_FIG)
44+
/* min_value = 0.0001_0000_0000E[exponent], exponent-(BASE_FIG-1) >= SIGNED_VALUE_MIN */
45+
#define VP_EXPONENT_MIN ((SIGNED_VALUE_MIN + BASE_FIG - 1) / BASE_FIG)
46+
4247
VALUE rb_cBigDecimal;
4348
VALUE rb_mBigMath;
4449

@@ -5084,24 +5089,14 @@ AddExponent(Real *a, SIGNED_VALUE n)
50845089
{
50855090
SIGNED_VALUE e = a->exponent;
50865091
SIGNED_VALUE m = e+n;
5087-
SIGNED_VALUE eb, mb;
5088-
if (e > 0) {
5089-
if (n > 0) {
5090-
if (MUL_OVERFLOW_SIGNED_VALUE_P(m, (SIGNED_VALUE)BASE_FIG) ||
5091-
MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG))
5092-
goto overflow;
5093-
mb = m*(SIGNED_VALUE)BASE_FIG;
5094-
eb = e*(SIGNED_VALUE)BASE_FIG;
5095-
if (eb - mb > 0) goto overflow;
5096-
}
5097-
}
5098-
else if (n < 0) {
5099-
if (MUL_OVERFLOW_SIGNED_VALUE_P(m, (SIGNED_VALUE)BASE_FIG) ||
5100-
MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG))
5101-
goto underflow;
5102-
mb = m*(SIGNED_VALUE)BASE_FIG;
5103-
eb = e*(SIGNED_VALUE)BASE_FIG;
5104-
if (mb - eb > 0) goto underflow;
5092+
if (e > 0 && n > 0) {
5093+
if (n > VP_EXPONENT_MAX - e) goto overflow;
5094+
} else if (e < 0 && n < 0) {
5095+
if (n < VP_EXPONENT_MIN - e) goto underflow;
5096+
} else if (m > VP_EXPONENT_MAX) {
5097+
goto overflow;
5098+
} else if (m < VP_EXPONENT_MIN) {
5099+
goto underflow;
51055100
}
51065101
a->exponent = m;
51075102
return 1;

0 commit comments

Comments
 (0)