- Added unpack limit.

- Added new exceptions to explain limit over errors.

- Fixed ext maximum size problem.
Problem:
The type of m_trail was uint32_t but when parsing ext, it could be 0xffffffff + 1. +1 means type. See https://github.com/msgpack/msgpack/blob/master/spec.md#ext-format-family

Solution:
Modified the type of m_trail as std::size_t. If sizeof(std::size_t) == 4, 0xffffffff size of ext is an error. If sizeof(std::size_t) == 8, 0xffffffff size of ext is not an error. m_trail is 0xffffffff + 1.

Design cohice:
I chose std::size_t as the m_trail's type instead of uint64_t intentionally. On 64 addressing bit environment, there is no problem. On 32 bit environment, there is no problem except ext with maximum size. There is only one exception in the all msgpack format. Using uint64_t to support that, it's very expensive. On 32 addressing bit environment, allocating 0xffffffff + 1 bytes of memory couldn't succeed, so I believe that throwing an exception is a reasonable design choice in the case.
This commit is contained in:
Takatoshi Kondo 2014-12-13 22:09:32 +09:00
parent 2d61fdf865
commit 309e96087a
4 changed files with 1056 additions and 443 deletions

File diff suppressed because it is too large Load Diff

View File

@ -28,6 +28,7 @@ LIST (APPEND check_PROGRAMS
msgpack_vref.cpp
msgpack_c.cpp
reference.cpp
limit.cpp
)
IF (MSGPACK_CXX11)

View File

@ -24,7 +24,8 @@ check_PROGRAMS = \
msgpack_vref \
msgpack_cpp11 \
reference_cpp11 \
reference
reference \
limit
TESTS = $(check_PROGRAMS)
@ -73,4 +74,6 @@ reference_SOURCES = reference.cpp
reference_cpp11_SOURCES = reference_cpp11.cpp
limit_SOURCES = limit.cpp
EXTRA_DIST = cases.mpac cases_compact.mpac

509
test/limit.cpp Normal file
View File

@ -0,0 +1,509 @@
#include <msgpack.hpp>
#include <gtest/gtest.h>
#include <sstream>
TEST(limit, unpack_array_no_over)
{
std::stringstream ss;
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
msgpack::pack(ss, v);
try {
msgpack::unpacked unp;
msgpack::unpack(unp, ss.str().c_str(), ss.str().size(), nullptr, nullptr,
msgpack::unpack_limit(3, 0, 0, 0, 0));
EXPECT_TRUE(true);
}
catch(msgpack::array_size_overflow const&) {
EXPECT_TRUE(false);
}
catch(...) {
EXPECT_TRUE(false);
}
}
TEST(limit, unpack_array_over)
{
std::stringstream ss;
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
msgpack::pack(ss, v);
try {
msgpack::unpacked unp;
msgpack::unpack(unp, ss.str().c_str(), ss.str().size(), nullptr, nullptr,
msgpack::unpack_limit(2, 0, 0, 0, 0));
EXPECT_TRUE(false);
}
catch(msgpack::array_size_overflow const&) {
EXPECT_TRUE(true);
}
catch(...) {
EXPECT_TRUE(false);
}
}
TEST(limit, unpack_map_no_over)
{
std::stringstream ss;
std::map<int, int> m;
m[1] = 1;
m[2] = 2;
m[3] = 3;
msgpack::pack(ss, m);
try {
msgpack::unpacked unp;
msgpack::unpack(unp, ss.str().c_str(), ss.str().size(), nullptr, nullptr,
msgpack::unpack_limit(0, 3, 0, 0, 0));
EXPECT_TRUE(true);
}
catch(msgpack::map_size_overflow const&) {
EXPECT_TRUE(false);
}
catch(...) {
EXPECT_TRUE(false);
}
}
TEST(limit, unpack_map_over)
{
std::stringstream ss;
std::map<int, int> m;
m[1] = 1;
m[2] = 2;
m[3] = 3;
msgpack::pack(ss, m);
try {
msgpack::unpacked unp;
msgpack::unpack(unp, ss.str().c_str(), ss.str().size(), nullptr, nullptr,
msgpack::unpack_limit(0, 2, 0, 0, 0));
EXPECT_TRUE(false);
}
catch(msgpack::map_size_overflow const&) {
EXPECT_TRUE(true);
}
catch(...) {
EXPECT_TRUE(false);
}
}
TEST(limit, unpack_str_no_over)
{
std::stringstream ss;
std::string s("123");
msgpack::pack(ss, s);
try {
msgpack::unpacked unp;
msgpack::unpack(unp, ss.str().c_str(), ss.str().size(), nullptr, nullptr,
msgpack::unpack_limit(0, 0, 3, 0, 0));
EXPECT_TRUE(true);
}
catch(msgpack::str_size_overflow const&) {
EXPECT_TRUE(false);
}
catch(...) {
EXPECT_TRUE(false);
}
}
TEST(limit, unpack_str_over)
{
std::stringstream ss;
std::string s("123");
msgpack::pack(ss, s);
try {
msgpack::unpacked unp;
msgpack::unpack(unp, ss.str().c_str(), ss.str().size(), nullptr, nullptr,
msgpack::unpack_limit(0, 0, 2, 0, 0));
EXPECT_TRUE(false);
}
catch(msgpack::str_size_overflow const&) {
EXPECT_TRUE(true);
}
catch(...) {
EXPECT_TRUE(false);
}
}
TEST(limit, unpack_bin_no_over)
{
std::stringstream ss;
std::vector<char> v;
v.push_back('1');
v.push_back('2');
v.push_back('3');
msgpack::pack(ss, v);
try {
msgpack::unpacked unp;
msgpack::unpack(unp, ss.str().c_str(), ss.str().size(), nullptr, nullptr,
msgpack::unpack_limit(0, 0, 0, 3, 0));
EXPECT_TRUE(true);
}
catch(msgpack::bin_size_overflow const&) {
EXPECT_TRUE(false);
}
catch(...) {
EXPECT_TRUE(false);
}
}
TEST(limit, unpack_bin_over)
{
std::stringstream ss;
std::vector<char> v;
v.push_back('1');
v.push_back('2');
v.push_back('3');
msgpack::pack(ss, v);
try {
msgpack::unpacked unp;
msgpack::unpack(unp, ss.str().c_str(), ss.str().size(), nullptr, nullptr,
msgpack::unpack_limit(0, 0, 0, 2, 0));
EXPECT_TRUE(false);
}
catch(msgpack::bin_size_overflow const&) {
EXPECT_TRUE(true);
}
catch(...) {
EXPECT_TRUE(false);
}
}
TEST(limit, unpack_ext_no_over)
{
std::stringstream ss;
msgpack::packer<std::stringstream> packer(ss);
char const buf [] = { 1, 2, 3 };
packer.pack_ext(sizeof(buf), 1);
packer.pack_ext_body(buf, sizeof(buf));
try {
msgpack::unpacked unp;
msgpack::unpack(unp, ss.str().c_str(), ss.str().size(), nullptr, nullptr,
msgpack::unpack_limit(0, 0, 0, 0, 3+1));
EXPECT_TRUE(true);
}
catch(msgpack::ext_size_overflow const&) {
EXPECT_TRUE(false);
}
catch(...) {
EXPECT_TRUE(false);
}
}
TEST(limit, unpack_ext_over)
{
std::stringstream ss;
msgpack::packer<std::stringstream> packer(ss);
char const buf [] = { 1, 2, 3 };
packer.pack_ext(sizeof(buf), 1);
packer.pack_ext_body(buf, sizeof(buf));
try {
msgpack::unpacked unp;
msgpack::unpack(unp, ss.str().c_str(), ss.str().size(), nullptr, nullptr,
msgpack::unpack_limit(0, 0, 0, 0, 2+1));
EXPECT_TRUE(false);
}
catch(msgpack::ext_size_overflow const&) {
EXPECT_TRUE(true);
}
catch(...) {
EXPECT_TRUE(false);
}
}
TEST(limit, unpack_ext_over_32_bit)
{
if (sizeof(std::size_t) == 4) {
char const buf [] = {
static_cast<char>(0xc9),
static_cast<char>(0xff),
static_cast<char>(0xff),
static_cast<char>(0xff),
static_cast<char>(0xff),
static_cast<char>(0x01),
};
try {
msgpack::unpacked unp;
msgpack::unpack(unp, buf, sizeof(buf), nullptr, nullptr,
msgpack::unpack_limit(0, 0, 0, 0, 0xffffffff));
EXPECT_TRUE(false);
}
catch(msgpack::ext_size_overflow const&) {
EXPECT_TRUE(true);
}
catch(...) {
EXPECT_TRUE(false);
}
}
}
TEST(limit, unpack_ext_no_over_64_bit)
{
if (sizeof(std::size_t) == 8) {
char const buf [] = {
static_cast<char>(0xc9),
static_cast<char>(0xff),
static_cast<char>(0xff),
static_cast<char>(0xff),
static_cast<char>(0xff),
static_cast<char>(0x01),
};
try {
msgpack::unpacked unp;
msgpack::unpack(unp, buf, sizeof(buf), nullptr, nullptr,
msgpack::unpack_limit(0, 0, 0, 0, 0xffffffff));
EXPECT_TRUE(false);
}
catch(msgpack::ext_size_overflow const&) {
EXPECT_TRUE(false);
}
catch(msgpack::insufficient_bytes const&) {
EXPECT_TRUE(true);
}
catch(...) {
EXPECT_TRUE(false);
}
}
}
#if !defined(MSGPACK_USE_CPP03)
TEST(limit, unpack_array_over_cpp11_no_off_no_ref)
{
std::stringstream ss;
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
msgpack::pack(ss, v);
try {
msgpack::unpacked unp =
msgpack::unpack(ss.str().c_str(), ss.str().size(), nullptr, nullptr,
msgpack::unpack_limit(2, 0, 0, 0, 0));
EXPECT_TRUE(false);
}
catch(msgpack::array_size_overflow const&) {
EXPECT_TRUE(true);
}
catch(...) {
EXPECT_TRUE(false);
}
}
TEST(limit, unpack_array_over_cpp11_no_off_ref)
{
std::stringstream ss;
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
msgpack::pack(ss, v);
try {
bool ref;
msgpack::unpacked unp =
msgpack::unpack(ss.str().c_str(), ss.str().size(), ref, nullptr, nullptr,
msgpack::unpack_limit(2, 0, 0, 0, 0));
EXPECT_TRUE(false);
}
catch(msgpack::array_size_overflow const&) {
EXPECT_TRUE(true);
}
catch(...) {
EXPECT_TRUE(false);
}
}
TEST(limit, unpack_array_over_cpp11_off_no_ref)
{
std::stringstream ss;
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
msgpack::pack(ss, v);
try {
std::size_t off = 0;
msgpack::unpacked unp =
msgpack::unpack(ss.str().c_str(), ss.str().size(), off, nullptr, nullptr,
msgpack::unpack_limit(2, 0, 0, 0, 0));
EXPECT_TRUE(false);
}
catch(msgpack::array_size_overflow const&) {
EXPECT_TRUE(true);
}
catch(...) {
EXPECT_TRUE(false);
}
}
TEST(limit, unpack_array_over_cpp11_off_ref)
{
std::stringstream ss;
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
msgpack::pack(ss, v);
try {
bool ref;
std::size_t off = 0;
msgpack::unpacked unp =
msgpack::unpack(ss.str().c_str(), ss.str().size(), off, ref, nullptr, nullptr,
msgpack::unpack_limit(2, 0, 0, 0, 0));
EXPECT_TRUE(false);
}
catch(msgpack::array_size_overflow const&) {
EXPECT_TRUE(true);
}
catch(...) {
EXPECT_TRUE(false);
}
}
#endif // !defined(MSGPACK_USE_CPP03)
TEST(limit, unpack_array_over_no_off_no_ref)
{
std::stringstream ss;
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
msgpack::pack(ss, v);
try {
msgpack::unpacked unp;
msgpack::unpack(unp, ss.str().c_str(), ss.str().size(), nullptr, nullptr,
msgpack::unpack_limit(2, 0, 0, 0, 0));
EXPECT_TRUE(false);
}
catch(msgpack::array_size_overflow const&) {
EXPECT_TRUE(true);
}
catch(...) {
EXPECT_TRUE(false);
}
}
TEST(limit, unpack_array_over_no_off_ref)
{
std::stringstream ss;
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
msgpack::pack(ss, v);
try {
bool ref;
msgpack::unpacked unp;
msgpack::unpack(unp, ss.str().c_str(), ss.str().size(), ref, nullptr, nullptr,
msgpack::unpack_limit(2, 0, 0, 0, 0));
EXPECT_TRUE(false);
}
catch(msgpack::array_size_overflow const&) {
EXPECT_TRUE(true);
}
catch(...) {
EXPECT_TRUE(false);
}
}
TEST(limit, unpack_array_over_off_no_ref)
{
std::stringstream ss;
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
msgpack::pack(ss, v);
try {
std::size_t off = 0;
msgpack::unpacked unp;
msgpack::unpack(unp, ss.str().c_str(), ss.str().size(), off, nullptr, nullptr,
msgpack::unpack_limit(2, 0, 0, 0, 0));
EXPECT_TRUE(false);
}
catch(msgpack::array_size_overflow const&) {
EXPECT_TRUE(true);
}
catch(...) {
EXPECT_TRUE(false);
}
}
TEST(limit, unpack_array_over_off_ref)
{
std::stringstream ss;
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
msgpack::pack(ss, v);
try {
bool ref;
std::size_t off = 0;
msgpack::unpacked unp;
msgpack::unpack(unp, ss.str().c_str(), ss.str().size(), off, ref, nullptr, nullptr,
msgpack::unpack_limit(2, 0, 0, 0, 0));
EXPECT_TRUE(false);
}
catch(msgpack::array_size_overflow const&) {
EXPECT_TRUE(true);
}
catch(...) {
EXPECT_TRUE(false);
}
}
// obsolete
TEST(limit, unpack_array_over_off_ref_pointer)
{
std::stringstream ss;
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
msgpack::pack(ss, v);
try {
bool ref;
std::size_t off = 0;
msgpack::unpacked unp;
msgpack::unpack(&unp, ss.str().c_str(), ss.str().size(), &off, &ref, nullptr, nullptr,
msgpack::unpack_limit(2, 0, 0, 0, 0));
EXPECT_TRUE(false);
}
catch(msgpack::array_size_overflow const&) {
EXPECT_TRUE(true);
}
catch(...) {
EXPECT_TRUE(false);
}
}
TEST(limit, unpacker_array_over)
{
std::stringstream ss;
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
msgpack::pack(ss, v);
try {
msgpack::unpacker u(nullptr, nullptr, MSGPACK_UNPACKER_INIT_BUFFER_SIZE,
msgpack::unpack_limit(2, 0, 0, 0, 0));
u.reserve_buffer(ss.str().size());
memcpy(u.buffer(), ss.str().c_str(), ss.str().size());
u.buffer_consumed(ss.str().size());
msgpack::unpacked unp;
u.next(unp);
EXPECT_TRUE(false);
}
catch(msgpack::array_size_overflow const&) {
EXPECT_TRUE(true);
}
catch(...) {
EXPECT_TRUE(false);
}
}