diff options
author | Daniel Bertalan <dani@danielbertalan.dev> | 2021-08-06 21:47:49 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-08-08 10:55:36 +0200 |
commit | 1472f6d9865eec67230405522bc0b44a681440dc (patch) | |
tree | ed4a69d9e69f00b199bd58b23b11978e33459fca /AK | |
parent | 12dc2c2079b5c9a23571f6dc01b258e381322f12 (diff) | |
download | serenity-1472f6d9865eec67230405522bc0b44a681440dc.zip |
AK: Add formatting for infinity and NaN
Without this patch, we would end up printing garbage values when we
encountered floating point infinity or NaN values, and also triggered
UBSAN with Clang. This added code models `std::format`'s behavior: the
sign is added the same way as with normal values and the strings 'nan'
and 'inf' are printed.
Diffstat (limited to 'AK')
-rw-r--r-- | AK/Format.cpp | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/AK/Format.cpp b/AK/Format.cpp index 08653293c8..a7dc73f4ff 100644 --- a/AK/Format.cpp +++ b/AK/Format.cpp @@ -19,6 +19,7 @@ # include <Kernel/Process.h> # include <Kernel/Thread.h> #else +# include <math.h> # include <stdio.h> # include <string.h> #endif @@ -344,6 +345,22 @@ void FormatBuilder::put_f64( StringBuilder string_builder; FormatBuilder format_builder { string_builder }; + if (isnan(value) || isinf(value)) [[unlikely]] { + if (value < 0.0) + string_builder.append('-'); + else if (sign_mode == SignMode::Always) + string_builder.append('+'); + else + string_builder.append(' '); + + if (isnan(value)) + string_builder.append(upper_case ? "NAN"sv : "nan"sv); + else + string_builder.append(upper_case ? "INF"sv : "inf"sv); + format_builder.put_string(string_builder.string_view(), align, min_width, NumericLimits<size_t>::max(), fill); + return; + } + bool is_negative = value < 0.0; if (is_negative) value = -value; @@ -394,6 +411,22 @@ void FormatBuilder::put_f80( StringBuilder string_builder; FormatBuilder format_builder { string_builder }; + if (isnan(value) || isinf(value)) [[unlikely]] { + if (value < 0.0l) + string_builder.append('-'); + else if (sign_mode == SignMode::Always) + string_builder.append('+'); + else + string_builder.append(' '); + + if (isnan(value)) + string_builder.append(upper_case ? "NAN"sv : "nan"sv); + else + string_builder.append(upper_case ? "INF"sv : "inf"sv); + format_builder.put_string(string_builder.string_view(), align, min_width, NumericLimits<size_t>::max(), fill); + return; + } + bool is_negative = value < 0.0l; if (is_negative) value = -value; |