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.

We on purpose don't supply a definition of
remove_sign(number_unsigned_t) as we only need the compiler to see the
declaration but never call the function.
  • Loading branch information
t-b committed Aug 27, 2019
1 parent e170761 commit 8458067
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 2 deletions.
10 changes: 9 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,14 @@ class serializer
return state;
}

number_unsigned_t remove_sign(number_unsigned_t x);

inline number_unsigned_t remove_sign(number_integer_t x) noexcept
{
assert(x < 0 && 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
10 changes: 9 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,14 @@ class serializer
return state;
}

number_unsigned_t remove_sign(number_unsigned_t x);

inline number_unsigned_t remove_sign(number_integer_t x) noexcept
{
assert(x < 0 && 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 8458067

Please sign in to comment.