diff --git a/include/msgpack/unpack.hpp b/include/msgpack/unpack.hpp index 8bd2f510..8ebc1b00 100644 --- a/include/msgpack/unpack.hpp +++ b/include/msgpack/unpack.hpp @@ -1534,13 +1534,16 @@ inline unpacked unpack( msgpack::object obj; msgpack::unique_ptr z(new msgpack::zone); referenced = false; + std::size_t noff = off; unpack_return ret = detail::unpack_imp( - data, len, off, *z, obj, referenced, f, user_data, limit); + data, len, noff, *z, obj, referenced, f, user_data, limit); switch(ret) { case UNPACK_SUCCESS: + off = noff; return unpacked(obj, msgpack::move(z)); case UNPACK_EXTRA_BYTES: + off = noff; return unpacked(obj, msgpack::move(z)); case UNPACK_CONTINUE: throw msgpack::insufficient_bytes("insufficient bytes"); @@ -1583,15 +1586,18 @@ inline void unpack(unpacked& result, msgpack::object obj; msgpack::unique_ptr z(new msgpack::zone); referenced = false; + std::size_t noff = off; unpack_return ret = detail::unpack_imp( - data, len, off, *z, obj, referenced, f, user_data, limit); + data, len, noff, *z, obj, referenced, f, user_data, limit); switch(ret) { case UNPACK_SUCCESS: + off = noff; result.set(obj); result.zone() = msgpack::move(z); return; case UNPACK_EXTRA_BYTES: + off = noff; result.set(obj); result.zone() = msgpack::move(z); return; @@ -1635,14 +1641,17 @@ inline msgpack::object unpack( unpack_reference_func f, void* user_data, unpack_limit const& limit) { msgpack::object obj; + std::size_t noff = off; referenced = false; unpack_return ret = detail::unpack_imp( - data, len, off, z, obj, referenced, f, user_data, limit); + data, len, noff, z, obj, referenced, f, user_data, limit); switch(ret) { case UNPACK_SUCCESS: + off = noff; return obj; case UNPACK_EXTRA_BYTES: + off = noff; return obj; case UNPACK_CONTINUE: throw msgpack::insufficient_bytes("insufficient bytes"); diff --git a/src/unpack.c b/src/unpack.c index 446497c6..c5a6667c 100644 --- a/src/unpack.c +++ b/src/unpack.c @@ -618,12 +618,13 @@ msgpack_unpack_next(msgpack_unpacked* result, return MSGPACK_UNPACK_PARSE_ERROR; } - if(off != NULL) { *off = noff; } if(e == 0) { return MSGPACK_UNPACK_CONTINUE; } + if(off != NULL) { *off = noff; } + result->data = template_data(&ctx); return MSGPACK_UNPACK_SUCCESS; diff --git a/test/pack_unpack.cpp b/test/pack_unpack.cpp index 9e02e0e1..afcceda0 100644 --- a/test/pack_unpack.cpp +++ b/test/pack_unpack.cpp @@ -317,3 +317,58 @@ TEST(unpack, convert_to_object_handle_direct_implicit) EXPECT_EQ(1, oh.get().as()); } + +TEST(unpack, insufficient_bytes_ref) +{ + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, 255); // uint8 (2bytes) + + std::size_t off = 0; + + msgpack::unpacked msg; + try { + msgpack::unpack(msg, sbuf.data(), 1, off); + EXPECT_TRUE(false); + } + catch (msgpack::insufficient_bytes const&) { + EXPECT_TRUE(true); + EXPECT_EQ(off, 0); + } +} + +TEST(unpack, insufficient_bytes_object_handle) +{ + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, 255); // uint8 (2bytes) + + std::size_t off = 0; + + msgpack::unpacked msg; + try { + msgpack::object_handle oh(msgpack::unpack(sbuf.data(), 1, off)); + EXPECT_TRUE(false); + } + catch (msgpack::insufficient_bytes const&) { + EXPECT_TRUE(true); + EXPECT_EQ(off, 0); + } +} + +TEST(unpack, insufficient_bytes_zone) +{ + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, 255); // uint8 (2bytes) + + std::size_t off = 0; + + msgpack::unpacked msg; + try { + msgpack::zone z; + msgpack::unpack(z, sbuf.data(), 1, off); + EXPECT_TRUE(false); + } + catch (msgpack::insufficient_bytes const&) { + EXPECT_TRUE(true); + EXPECT_EQ(off, 0); + } +} diff --git a/test/pack_unpack_c.cpp b/test/pack_unpack_c.cpp index 82147290..3bc35b57 100644 --- a/test/pack_unpack_c.cpp +++ b/test/pack_unpack_c.cpp @@ -68,3 +68,25 @@ TEST(unpack, sequence) msgpack_unpacked_destroy(&msg); } +TEST(pack, insufficient) +{ + msgpack_sbuffer* sbuf = msgpack_sbuffer_new(); + msgpack_packer* pk = msgpack_packer_new(sbuf, msgpack_sbuffer_write); + + EXPECT_EQ(0, msgpack_pack_int(pk, 255)); // uint8 (2bytes) + + msgpack_unpack_return success; + size_t offset = 0; + + msgpack_unpacked msg; + msgpack_unpacked_init(&msg); + + success = msgpack_unpack_next(&msg, sbuf->data, 1, &offset); + EXPECT_EQ(MSGPACK_UNPACK_CONTINUE, success); + EXPECT_EQ(0, offset); + + msgpack_unpacked_destroy(&msg); + + msgpack_sbuffer_free(sbuf); + msgpack_packer_free(pk); +}