You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi,
I pulled the fix in #1141 (comment) and continued fuzzing. This time it survived for almost a minute!
The title is the theory of what I think is the problem.
For the floating point case, I added internal checks for incoming NaN and/or Inf and throw an exception if one is found. It also checks if any of the seconds or milliseconds are NaN and/or Inf. Looking at https://en.cppreference.com/w/cpp/chrono/duration/duration_cast it seems like it's good to avoid NaN altogether (undefined behaviour).
This was however not sufficient. As revealed by the following:
There is a problem with the calculation of seconds and milliseconds. I think the error is that such a large float value has a granularity larger than a second. The (d-s) expression has cancellation like problems. The new constructor looks like this (the real version is here):
explicitchrono_formatter(FormatContext& ctx, OutputIt o,
std::chrono::duration<Rep, Period> d)
: context(ctx), out(o), val(d.count()) {
constexprbool is_floating_point = std::is_floating_point<Rep>::value;
if (is_floating_point && !std::isfinite(d.count())) {
FMT_THROW(format_error("floating point duration is NaN or Inf"));
}
if (d.count() < 0) {
d = -d;
*out++ = '-';
}
ifconstexpr (is_floating_point) {
auto tmpseconds = std::chrono::duration_cast<seconds>(d);
s = seconds{std::floor(tmpseconds.count())};
ms = std::chrono::duration_cast<milliseconds>(tmpseconds - s);
if (!std::isfinite(s.count()) || !std::isfinite(ms.count())) {
FMT_THROW(format_error("internal overflow of floating point duration"));
}
} else {
s = std::chrono::duration_cast<seconds>(d);
ms = std::chrono::duration_cast<milliseconds>(d - s);
}
}
With these changes, my floating point fuzzers have survived for a cpu hour. They also survive the crashing input I saved the last days when working with this. I will keep it running to see if it finds anything. I know I use C++17 but I couldn't resist using the wonderful constexpr if :-)
The text was updated successfully, but these errors were encountered:
You are right, there is a problem with d - s which is due to limited FP precision. I tried to address it in e9bab6d. The actual output is kinda meaningless for very large numbers (garbage in -> garbage out =)) but at least it shouldn't trigger the assertion.
Hi,
I pulled the fix in #1141 (comment) and continued fuzzing. This time it survived for almost a minute!
The title is the theory of what I think is the problem.
For the floating point case, I added internal checks for incoming NaN and/or Inf and throw an exception if one is found. It also checks if any of the seconds or milliseconds are NaN and/or Inf. Looking at https://en.cppreference.com/w/cpp/chrono/duration/duration_cast it seems like it's good to avoid NaN altogether (undefined behaviour).
This was however not sufficient. As revealed by the following:
There is a problem with the calculation of seconds and milliseconds. I think the error is that such a large float value has a granularity larger than a second. The (d-s) expression has cancellation like problems. The new constructor looks like this (the real version is here):
With these changes, my floating point fuzzers have survived for a cpu hour. They also survive the crashing input I saved the last days when working with this. I will keep it running to see if it finds anything. I know I use C++17 but I couldn't resist using the wonderful constexpr if :-)
The text was updated successfully, but these errors were encountered: