msgpack/test/limit.cpp
Takatoshi Kondo 309e96087a - 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.
2014-12-14 19:10:46 +09:00

510 lines
12 KiB
C++

#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);
}
}