From ba239535a3234960eb8cb337ca9197f84499cad3 Mon Sep 17 00:00:00 2001 From: domsoll <76645975+domsoll@users.noreply.github.com> Date: Tue, 29 Dec 2020 18:42:19 +0100 Subject: [PATCH] CHG: explicit size checks and more expressive exceptions for converstion of fixed size containers from json MNT: updated amalgamation header --- .../nlohmann/detail/conversions/from_json.hpp | 32 +++++++++++++++++ single_include/nlohmann/json.hpp | 36 +++++++++++++++++-- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index 438b84a2e..5695fbed3 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -164,6 +164,14 @@ template auto from_json(const BasicJsonType& j, T (&arr)[N]) -> decltype(j.template get(), void()) { + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + if (JSON_HEDLEY_UNLIKELY(j.size() != N)) + { + JSON_THROW(type_error::create(302, "array size must be " + std::to_string(N) + ", but is " + std::to_string(j.size()))); + } for (std::size_t i = 0; i < N; ++i) { arr[i] = j.at(i).template get(); @@ -181,6 +189,14 @@ auto from_json_array_impl(const BasicJsonType& j, std::array& arr, priority_tag<2> /*unused*/) -> decltype(j.template get(), void()) { + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + if (JSON_HEDLEY_UNLIKELY(j.size() != N)) + { + JSON_THROW(type_error::create(302, "array size must be " + std::to_string(N) + ", but is " + std::to_string(j.size()))); + } for (std::size_t i = 0; i < N; ++i) { arr[i] = j.at(i).template get(); @@ -326,12 +342,28 @@ void from_json(const BasicJsonType& j, ArithmeticType& val) template void from_json(const BasicJsonType& j, std::pair& p) { + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + if (JSON_HEDLEY_UNLIKELY(j.size() != 2)) + { + JSON_THROW(type_error::create(302, "array size must be 2, but is " + std::to_string(j.size()))); + } p = {j.at(0).template get(), j.at(1).template get()}; } template void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence /*unused*/) { + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + if (JSON_HEDLEY_UNLIKELY(j.size() != sizeof...(Idx))) + { + JSON_THROW(type_error::create(302, "array size must be " + std::to_string(sizeof...(Idx)) + ", but is " + std::to_string(j.size()))); + } t = std::make_tuple(j.at(Idx).template get::type>()...); } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index a70aaf8cb..e374a3e6b 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -3564,6 +3564,14 @@ template auto from_json(const BasicJsonType& j, T (&arr)[N]) -> decltype(j.template get(), void()) { + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + if (JSON_HEDLEY_UNLIKELY(j.size() != N)) + { + JSON_THROW(type_error::create(302, "array size must be " + std::to_string(N) + ", but is " + std::to_string(j.size()))); + } for (std::size_t i = 0; i < N; ++i) { arr[i] = j.at(i).template get(); @@ -3581,6 +3589,14 @@ auto from_json_array_impl(const BasicJsonType& j, std::array& arr, priority_tag<2> /*unused*/) -> decltype(j.template get(), void()) { + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + if (JSON_HEDLEY_UNLIKELY(j.size() != N)) + { + JSON_THROW(type_error::create(302, "array size must be " + std::to_string(N) + ", but is " + std::to_string(j.size()))); + } for (std::size_t i = 0; i < N; ++i) { arr[i] = j.at(i).template get(); @@ -3726,12 +3742,28 @@ void from_json(const BasicJsonType& j, ArithmeticType& val) template void from_json(const BasicJsonType& j, std::pair& p) { + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + if (JSON_HEDLEY_UNLIKELY(j.size() != 2)) + { + JSON_THROW(type_error::create(302, "array size must be 2, but is " + std::to_string(j.size()))); + } p = {j.at(0).template get(), j.at(1).template get()}; } template void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence /*unused*/) { + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + if (JSON_HEDLEY_UNLIKELY(j.size() != sizeof...(Idx))) + { + JSON_THROW(type_error::create(302, "array size must be " + std::to_string(sizeof...(Idx)) + ", but is " + std::to_string(j.size()))); + } t = std::make_tuple(j.at(Idx).template get::type>()...); } @@ -16686,7 +16718,7 @@ class basic_json detail::parser_callback_tcb = nullptr, const bool allow_exceptions = true, const bool ignore_comments = false - ) + ) { return ::nlohmann::detail::parser(std::move(adapter), std::move(cb), allow_exceptions, ignore_comments); @@ -25227,7 +25259,7 @@ template<> inline void swap(nlohmann::json& j1, nlohmann::json& j2) noexcept( is_nothrow_move_constructible::value&& is_nothrow_move_assignable::value - ) +) { j1.swap(j2); }