diff --git a/include/msgpack/unpack.hpp b/include/msgpack/unpack.hpp index 1621024c..aaa4d05c 100644 --- a/include/msgpack/unpack.hpp +++ b/include/msgpack/unpack.hpp @@ -149,6 +149,15 @@ struct ext_size_overflow : public size_overflow { #endif }; +struct depth_size_overflow : public size_overflow { + depth_size_overflow(const std::string& msg) + :size_overflow(msg) {} +#if !defined(MSGPACK_USE_CPP03) + depth_size_overflow(const char* msg) + :size_overflow(msg) {} +#endif +}; + class unpack_limit { public: unpack_limit( @@ -156,17 +165,20 @@ public: std::size_t map = 0xffffffff, std::size_t str = 0xffffffff, std::size_t bin = 0xffffffff, - std::size_t ext = 0xffffffff) + std::size_t ext = 0xffffffff, + std::size_t depth = 0xffffffff) :array_(array), map_(map), str_(str), bin_(bin), - ext_(ext) {} + ext_(ext), + depth_(depth) {} std::size_t array() const { return array_; } std::size_t map() const { return map_; } std::size_t str() const { return str_; } std::size_t bin() const { return bin_; } std::size_t ext() const { return ext_; } + std::size_t depth() const { return depth_; } private: std::size_t array_; @@ -174,6 +186,7 @@ private: std::size_t str_; std::size_t bin_; std::size_t ext_; + std::size_t depth_; }; namespace detail { @@ -492,7 +505,12 @@ private: else { m_stack.back().set_container_type(container_type); m_stack.back().set_count(tmp); - m_stack.push_back(unpack_stack()); + if (m_stack.size() <= m_user.limit().depth()) { + m_stack.push_back(unpack_stack()); + } + else { + throw msgpack::depth_size_overflow("depth size overflow"); + } m_cs = MSGPACK_CS_HEADER; ++m_current; } diff --git a/test/limit.cpp b/test/limit.cpp index e8483f1a..3f95c2ad 100644 --- a/test/limit.cpp +++ b/test/limit.cpp @@ -269,6 +269,52 @@ TEST(limit, unpack_ext_no_over_64_bit) } } +TEST(limit, unpack_depth_no_over) +{ + std::stringstream ss; + std::vector inner; + inner.push_back(1); + std::vector > outer; + outer.push_back(inner); + msgpack::pack(ss, outer); + try { + msgpack::unpacked unp; + msgpack::unpack(unp, ss.str().c_str(), ss.str().size(), nullptr, nullptr, + msgpack::unpack_limit(1, 0, 0, 0, 0, 2)); + EXPECT_TRUE(true); + } + catch(msgpack::depth_size_overflow const&) { + EXPECT_TRUE(false); + } + catch(...) { + EXPECT_TRUE(false); + } +} + +TEST(limit, unpack_depth_over) +{ + std::stringstream ss; + std::vector inner; + inner.push_back(1); + std::vector > outer; + outer.push_back(inner); + msgpack::pack(ss, outer); + try { + msgpack::unpacked unp; + msgpack::unpack(unp, ss.str().c_str(), ss.str().size(), nullptr, nullptr, + msgpack::unpack_limit(1, 0, 0, 0, 0, 1)); + EXPECT_TRUE(false); + } + catch(msgpack::depth_size_overflow const&) { + EXPECT_TRUE(true); + } + catch(...) { + EXPECT_TRUE(false); + } +} + + + #if !defined(MSGPACK_USE_CPP03) TEST(limit, unpack_array_over_cpp11_no_off_no_ref)