Skip to content

Commit

Permalink
Fix outputting extreme integer values in edge cases
Browse files Browse the repository at this point in the history
For some gcc version (Ubuntu 5.5.0-12ubuntu1~16.04) the existing code
crashes when the minimum value of int64_t is outputted.

Resurrect the code from before 546e2cb (:rotating_light: fixed some warnings,
2019-03-13) but delegate the sign removal so that the compilers don't
complain about taking the negative value of an unsigned value.

In addition we also rewrite the expression so that we first increment
and then negate.
  • Loading branch information
t-b committed Aug 25, 2019
1 parent 13684f2 commit e8ab305
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 2 deletions.
13 changes: 12 additions & 1 deletion include/nlohmann/detail/output/serializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ class serializer
if (is_negative)
{
*buffer_ptr = '-';
abs_value = static_cast<number_unsigned_t>(std::abs(static_cast<std::intmax_t>(x)));
abs_value = remove_sign(x);

// account one more byte for the minus sign
n_chars = 1 + count_digits(abs_value);
Expand Down Expand Up @@ -811,6 +811,17 @@ class serializer
return state;
}

inline number_unsigned_t remove_sign(number_unsigned_t x) noexcept
{
return x;
}

inline number_unsigned_t remove_sign(number_integer_t x) noexcept
{
assert(x < std::numeric_limits<number_integer_t>::max());
return static_cast<number_unsigned_t>(-(x + 1)) + 1;
}

private:
/// the output of the serializer
output_adapter_t<char> o = nullptr;
Expand Down
13 changes: 12 additions & 1 deletion single_include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14264,7 +14264,7 @@ class serializer
if (is_negative)
{
*buffer_ptr = '-';
abs_value = static_cast<number_unsigned_t>(std::abs(static_cast<std::intmax_t>(x)));
abs_value = remove_sign(x);

// account one more byte for the minus sign
n_chars = 1 + count_digits(abs_value);
Expand Down Expand Up @@ -14445,6 +14445,17 @@ class serializer
return state;
}

inline number_unsigned_t remove_sign(number_unsigned_t x) noexcept
{
return x;
}

inline number_unsigned_t remove_sign(number_integer_t x) noexcept
{
assert(x < std::numeric_limits<number_integer_t>::max());
return static_cast<number_unsigned_t>(-(x + 1)) + 1;
}

private:
/// the output of the serializer
output_adapter_t<char> o = nullptr;
Expand Down

0 comments on commit e8ab305

Please sign in to comment.