diff options
author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2021-12-07 18:05:04 (GMT) |
---|---|---|
committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2021-12-07 18:05:04 (GMT) |
commit | 3ad14e6b9a825cc010e8a15687eb872978f10171 (patch) | |
tree | 24ff062b49aab8540c45c87100f68c9192276396 | |
parent | 4f1573ed0c23f2c753bcaa10b37026da84d353bd (diff) | |
download | tcl-3ad14e6b9a825cc010e8a15687eb872978f10171.zip tcl-3ad14e6b9a825cc010e8a15687eb872978f10171.tar.gz tcl-3ad14e6b9a825cc010e8a15687eb872978f10171.tar.bz2 |
Fix [cea2c63928]: Address -fsanitize=shift-exponent complaints in TclParseNumber()
-rw-r--r-- | generic/tclStrToD.c | 85 |
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); |