-
Notifications
You must be signed in to change notification settings - Fork 14.2k
[libc][math][c23] Fix bounds checking and add FE_INVALID raising in {,u}fromfp{,x}* #86892
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc][math][c23] Fix bounds checking and add FE_INVALID raising in {,u}fromfp{,x}* #86892
Conversation
@llvm/pr-subscribers-libc Author: OverMighty (overmighty) ChangesSee cc @lntue @nickdesaulniers Full diff: https://github.com/llvm/llvm-project/pull/86892.diff 1 Files Affected:
diff --git a/libc/src/__support/FPUtil/NearestIntegerOperations.h b/libc/src/__support/FPUtil/NearestIntegerOperations.h
index 579584076b1258..8265f1f77c7656 100644
--- a/libc/src/__support/FPUtil/NearestIntegerOperations.h
+++ b/libc/src/__support/FPUtil/NearestIntegerOperations.h
@@ -247,6 +247,11 @@ round_using_current_rounding_mode(T x) {
template <bool IsSigned, typename T>
LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, T>
fromfp(T x, int rnd, unsigned int width) {
+ using StorageType = typename FPBits<T>::StorageType;
+
+ constexpr StorageType EXPLICIT_BIT =
+ FPBits<T>::SIG_MASK - FPBits<T>::FRACTION_MASK;
+
if (width == 0U)
return FPBits<T>::quiet_nan().get_val();
@@ -256,18 +261,38 @@ fromfp(T x, int rnd, unsigned int width) {
// T can't hold a finite number >= 2.0 * 2^EXP_BIAS.
if (width - 1 > FPBits<T>::EXP_BIAS)
return rounded_value;
- if (rounded_value < -T(1U << (width - 1U)))
+
+ StorageType range_exp = width - 1U + FPBits<T>::EXP_BIAS;
+ // rounded_value < -2^(width - 1)
+ T range_min =
+ FPBits<T>::create_value(Sign::NEG, range_exp, EXPLICIT_BIT).get_val();
+ if (rounded_value < range_min)
return FPBits<T>::quiet_nan().get_val();
- if (rounded_value > T((1U << (width - 1U)) - 1U))
+ // rounded_value > 2^(width - 1) - 1
+ T range_max =
+ FPBits<T>::create_value(Sign::POS, range_exp, EXPLICIT_BIT).get_val() -
+ T(1.0);
+ if (rounded_value > range_max)
return FPBits<T>::quiet_nan().get_val();
+
return rounded_value;
}
if (rounded_value < T(0.0))
return FPBits<T>::quiet_nan().get_val();
+
// T can't hold a finite number >= 2.0 * 2^EXP_BIAS.
- if (width <= FPBits<T>::EXP_BIAS && rounded_value > T(1U << width) - 1U)
+ if (width > FPBits<T>::EXP_BIAS)
+ return rounded_value;
+
+ StorageType range_exp = width + FPBits<T>::EXP_BIAS;
+ // rounded_value > 2^width - 1
+ T range_max =
+ FPBits<T>::create_value(Sign::POS, range_exp, EXPLICIT_BIT).get_val() -
+ T(1.0);
+ if (rounded_value > range_max)
return FPBits<T>::quiet_nan().get_val();
+
return rounded_value;
}
|
|
||
constexpr StorageType EXPLICIT_BIT = | ||
FPBits<T>::SIG_MASK - FPBits<T>::FRACTION_MASK; | ||
|
||
if (width == 0U) | ||
return FPBits<T>::quiet_nan().get_val(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just re-read section F.10.6.10 and F.10.6.11 in N3096, it looks like we will need to raise FE_INVALID
for those out-of-range cases.
…fromfp{,x}* (llvm#86692)" This reverts commit 8a07167. The test failure on 32-bit Arm should have been fixed by llvm#86892.
…fromfp{,x}* (llvm#86692)" (llvm#88567) This reverts commit 8a07167. The test failure on 32-bit Arm should have been fixed by llvm#86892. cc @nickdesaulniers @lntue
See
#86692 (comment)
and
#86892 (comment).
cc @lntue @nickdesaulniers