diff --git a/include/msgpack/v1/adaptor/cpp11/array.hpp b/include/msgpack/v1/adaptor/cpp11/array.hpp index e816d64a4..c32351128 100644 --- a/include/msgpack/v1/adaptor/cpp11/array.hpp +++ b/include/msgpack/v1/adaptor/cpp11/array.hpp @@ -76,7 +76,7 @@ template struct as, typename std::enable_if::value>::type> { std::array operator()(msgpack::object const& o) const { if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } - if(o.via.array.size > N) { throw msgpack::type_error(); } + if(o.via.array.size != N) { throw msgpack::type_error(); } return detail::array::as_impl::as(o); } }; diff --git a/test/security_fixes_cpp11.cpp b/test/security_fixes_cpp11.cpp index 17bc3d60c..b574eba5a 100644 --- a/test/security_fixes_cpp11.cpp +++ b/test/security_fixes_cpp11.cpp @@ -65,6 +65,19 @@ BOOST_AUTO_TEST_CASE(array_char_str_no_overread) BOOST_CHECK_EQUAL(a[2], 'Z'); // untouched } +// A5: as> reads exactly N elements through as_impl, so a wire +// array shorter than N (or empty) must throw instead of reading past the end. +BOOST_AUTO_TEST_CASE(array_as_short_array_throws) +{ + using tp = std::chrono::system_clock::time_point; + msgpack::object_handle oh0 = msgpack::unpack("\x90", 1); // [] -> would deref null + BOOST_CHECK_THROW((oh0.get().as >()), msgpack::type_error); + + const char b1[] = "\x91\xd6\xff\x00\x00\x00\x00"; // [ts32] -> would read ptr[1..2] + msgpack::object_handle oh1 = msgpack::unpack(b1, sizeof(b1) - 1); + BOOST_CHECK_THROW((oh1.get().as >()), msgpack::type_error); +} + // B1: moving a (v2) unpacker must not leave the parser referencing the // moved-from object's buffer hook. BOOST_AUTO_TEST_CASE(unpacker_move_buffer_hook)