Просмотр исходного кода

LibWasm: Split SaturatingTruncate conversion function by float/non-float

It's possible to construct a floating point value that when converted to
double is not larger than i64::max(), but when remaining a float is
larger. This patch avoids that edge case with some even less exciting if
constexpr branches to fix a float-cast-overflow UBSAN error on macOS
with llvm 15.0.6.
Andrew Kaster 2 лет назад
Родитель
Сommit
9a66a9ac4a
1 измененных файлов с 8 добавлено и 3 удалено
  1. 8 3
      Userland/Libraries/LibWasm/AbstractMachine/Operators.h

+ 8 - 3
Userland/Libraries/LibWasm/AbstractMachine/Operators.h

@@ -431,11 +431,16 @@ struct SaturatingTruncate {
         // FIXME: This assumes that all values in ResultT are representable in 'double'.
         //        that assumption is not correct, which makes this function yield incorrect values
         //        for 'edge' values of type i64.
-        constexpr auto convert = [](auto truncated_value) {
+        constexpr auto convert = []<typename ConvertT>(ConvertT truncated_value) {
             if (truncated_value < NumericLimits<ResultT>::min())
                 return NumericLimits<ResultT>::min();
-            if (static_cast<double>(truncated_value) > static_cast<double>(NumericLimits<ResultT>::max()))
-                return NumericLimits<ResultT>::max();
+            if constexpr (IsSame<ConvertT, float>) {
+                if (truncated_value >= static_cast<ConvertT>(NumericLimits<ResultT>::max()))
+                    return NumericLimits<ResultT>::max();
+            } else {
+                if (static_cast<double>(truncated_value) >= static_cast<double>(NumericLimits<ResultT>::max()))
+                    return NumericLimits<ResultT>::max();
+            }
             return static_cast<ResultT>(truncated_value);
         };