summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2021-12-07 18:05:04 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2021-12-07 18:05:04 (GMT)
commit3ad14e6b9a825cc010e8a15687eb872978f10171 (patch)
tree24ff062b49aab8540c45c87100f68c9192276396
parent4f1573ed0c23f2c753bcaa10b37026da84d353bd (diff)
downloadtcl-3ad14e6b9a825cc010e8a15687eb872978f10171.zip
tcl-3ad14e6b9a825cc010e8a15687eb872978f10171.tar.gz
tcl-3ad14e6b9a825cc010e8a15687eb872978f10171.tar.bz2
Fix [cea2c63928]: Address -fsanitize=shift-exponent complaints in TclParseNumber()
-rw-r--r--generic/tclStrToD.c85
1 files changed, 69 insertions, 16 deletions
diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c
index 35848f7..372fe77 100644
--- a/generic/tclStrToD.c
+++ b/generic/tclStrToD.c
@@ -694,9 +694,9 @@ TclParseNumber(
if (!octalSignificandOverflow) {
/*
- * Shifting by more bits than are in the value being
- * shifted is at least de facto nonportable. Check for
- * too large shifts first.
+ * Shifting by as many or more bits than are in the
+ * value being shifted is undefined behavior. Check
+ * for too large shifts first.
*/
if ((octalSignificandWide != 0)
@@ -710,8 +710,17 @@ TclParseNumber(
}
}
if (!octalSignificandOverflow) {
- octalSignificandWide =
- (octalSignificandWide << shift) + (c - '0');
+ /*
+ * When the significand is 0, it is possible for the
+ * amount to be shifted to equal or exceed the width
+ * of the significand. Do not shift when the
+ * significand is 0 to avoid undefined behavior.
+ */
+
+ if (octalSignificandWide != 0) {
+ octalSignificandWide <<= shift;
+ }
+ octalSignificandWide += c - '0';
} else {
mp_mul_2d(&octalSignificandBig, shift,
&octalSignificandBig);
@@ -813,9 +822,9 @@ TclParseNumber(
shift = 4 * (numTrailZeros + 1);
if (!significandOverflow) {
/*
- * Shifting by more bits than are in the value being
- * shifted is at least de facto nonportable. Check for too
- * large shifts first.
+ * Shifting by as many or more bits than are in the
+ * value being shifted is undefined behavior. Check
+ * for too large shifts first.
*/
if (significandWide != 0 &&
@@ -827,7 +836,17 @@ TclParseNumber(
}
}
if (!significandOverflow) {
- significandWide = (significandWide << shift) + d;
+ /*
+ * When the significand is 0, it is possible for the
+ * amount to be shifted to equal or exceed the width
+ * of the significand. Do not shift when the
+ * significand is 0 to avoid undefined behavior.
+ */
+
+ if (significandWide != 0) {
+ significandWide <<= shift;
+ }
+ significandWide += d;
} else {
mp_mul_2d(&significandBig, shift, &significandBig);
mp_add_d(&significandBig, (mp_digit) d, &significandBig);
@@ -855,9 +874,9 @@ TclParseNumber(
shift = numTrailZeros + 1;
if (!significandOverflow) {
/*
- * Shifting by more bits than are in the value being
- * shifted is at least de facto nonportable. Check for too
- * large shifts first.
+ * Shifting by as many or more bits than are in the
+ * value being shifted is undefined behavior. Check
+ * for too large shifts first.
*/
if (significandWide != 0 &&
@@ -869,7 +888,17 @@ TclParseNumber(
}
}
if (!significandOverflow) {
- significandWide = (significandWide << shift) + 1;
+ /*
+ * When the significand is 0, it is possible for the
+ * amount to be shifted to equal or exceed the width
+ * of the significand. Do not shift when the
+ * significand is 0 to avoid undefined behavior.
+ */
+
+ if (significandWide != 0) {
+ significandWide <<= shift;
+ }
+ significandWide += 1;
} else {
mp_mul_2d(&significandBig, shift, &significandBig);
mp_add_d(&significandBig, (mp_digit) 1, &significandBig);
@@ -1202,7 +1231,15 @@ TclParseNumber(
}
if (shift) {
if (!significandOverflow) {
- significandWide <<= shift;
+ /*
+ * When the significand is 0, it is possible for the
+ * amount to be shifted to equal or exceed the width
+ * of the significand. Do not shift when the
+ * significand is 0 to avoid undefined behavior.
+ */
+ if (significandWide != 0) {
+ significandWide <<= shift;
+ }
} else {
mp_mul_2d(&significandBig, shift, &significandBig);
}
@@ -1223,7 +1260,15 @@ TclParseNumber(
}
if (shift) {
if (!significandOverflow) {
- significandWide <<= shift;
+ /*
+ * When the significand is 0, it is possible for the
+ * amount to be shifted to equal or exceed the width
+ * of the significand. Do not shift when the
+ * significand is 0 to avoid undefined behavior.
+ */
+ if (significandWide != 0) {
+ significandWide <<= shift;
+ }
} else {
mp_mul_2d(&significandBig, shift, &significandBig);
}
@@ -1245,7 +1290,15 @@ TclParseNumber(
}
if (shift) {
if (!octalSignificandOverflow) {
- octalSignificandWide <<= shift;
+ /*
+ * When the significand is 0, it is possible for the
+ * amount to be shifted to equal or exceed the width
+ * of the significand. Do not shift when the
+ * significand is 0 to avoid undefined behavior.
+ */
+ if (octalSignificandWide != 0) {
+ octalSignificandWide <<= shift;
+ }
} else {
mp_mul_2d(&octalSignificandBig, shift,
&octalSignificandBig);