summaryrefslogtreecommitdiffstats
path: root/generic/tclStrToD.c
diff options
context:
space:
mode:
authoroehhar <harald.oehlmann@elmicron.de>2025-05-05 14:30:52 (GMT)
committeroehhar <harald.oehlmann@elmicron.de>2025-05-05 14:30:52 (GMT)
commit7ece2cabd34bf7cb59593ca06aadd43a5c3330f5 (patch)
tree18d483a5af6e2616096e6aaf9eb94d578aed3713 /generic/tclStrToD.c
parentb1b52b01438376c0a34e39fcbfea95172f7918ab (diff)
parent075a14cd434896a7f50d0e50b40ab7068db6a10c (diff)
downloadtcl-7ece2cabd34bf7cb59593ca06aadd43a5c3330f5.zip
tcl-7ece2cabd34bf7cb59593ca06aadd43a5c3330f5.tar.gz
tcl-7ece2cabd34bf7cb59593ca06aadd43a5c3330f5.tar.bz2
[42d14c495a] Parsing long floating point strings
Diffstat (limited to 'generic/tclStrToD.c')
-rw-r--r--generic/tclStrToD.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c
index ed49474..1cfadf0 100644
--- a/generic/tclStrToD.c
+++ b/generic/tclStrToD.c
@@ -1756,6 +1756,8 @@ MakeHighPrecisionDouble(
TCL_IEEE_DOUBLE_ROUNDING_DECL
int machexp; /* Machine exponent of a power of 10. */
+ int shift, n;
+ mp_int bntmp;
/*
* With gcc on x86, the floating point rounding mode is double-extended.
@@ -1803,6 +1805,35 @@ MakeHighPrecisionDouble(
* for overflow. Convert back to a double, and test for underflow.
*/
+ /*
+ * TCL bug ca62367d61: the following two if-conditions handle the case,
+ * if the mantissa is to long to be represented.
+ * Very high numbers are returned, if this is not handled
+ */
+
+
+ if (exponent < -511) {
+ mp_init_copy(&bntmp, significand);
+ shift = -exponent - 511;
+ exponent += shift;
+ while (shift > 0) {
+ n = (shift > 9) ? 9 : shift;
+ mp_div_d(&bntmp, (mp_digit) pow10_wide[n], &bntmp, NULL);
+ shift -= n;
+ }
+ significand = &bntmp;
+ } else if (exponent > 511) {
+ mp_init_copy(&bntmp, significand);
+ shift = exponent - 511;
+ exponent -= shift;
+ while (shift > 0) {
+ n = (shift > 9) ? 9 : shift;
+ mp_mul_d(&bntmp, (mp_digit) pow10_wide[n], &bntmp);
+ shift -= n;
+ }
+ significand = &bntmp;
+ }
+
retval = BignumToBiasedFrExp(significand, &machexp);
retval = Pow10TimesFrExp(exponent, retval, &machexp);
if (machexp > DBL_MAX_EXP*log2FLT_RADIX) {
@@ -1830,6 +1861,9 @@ MakeHighPrecisionDouble(
*/
returnValue:
+ if (significand == &bntmp) {
+ mp_clear(&bntmp);
+ }
if (signum) {
retval = -retval;
}