Merge pull request #175 from redboltz/add_limit

- Added unpack limit.
This commit is contained in:
Nobuyuki Kubota 2015-01-02 12:22:03 -08:00
commit ce96ca8bfc
4 changed files with 1091 additions and 443 deletions

View File

@ -63,12 +63,122 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
typedef bool (*unpack_reference_func)(type::object_type, std::size_t, void*);
struct unpack_error : public std::runtime_error {
explicit unpack_error(const std::string& msg)
:std::runtime_error(msg) {}
#if !defined(MSGPACK_USE_CPP03)
explicit unpack_error(const char* msg):
std::runtime_error(msg) {}
#endif // !defined(MSGPACK_USE_CPP03)
};
struct parse_error : public unpack_error {
explicit parse_error(const std::string& msg)
:unpack_error(msg) {}
#if !defined(MSGPACK_USE_CPP03)
explicit parse_error(const char* msg)
:unpack_error(msg) {}
#endif // !defined(MSGPACK_USE_CPP03)
};
struct insufficient_bytes : public unpack_error {
explicit insufficient_bytes(const std::string& msg)
:unpack_error(msg) {}
#if !defined(MSGPACK_USE_CPP03)
explicit insufficient_bytes(const char* msg)
:unpack_error(msg) {}
#endif // !defined(MSGPACK_USE_CPP03)
};
struct size_overflow : public unpack_error {
explicit size_overflow(const std::string& msg)
:unpack_error(msg) {}
#if !defined(MSGPACK_USE_CPP03)
explicit size_overflow(const char* msg)
:unpack_error(msg) {}
#endif
};
struct array_size_overflow : public size_overflow {
array_size_overflow(const std::string& msg)
:size_overflow(msg) {}
#if !defined(MSGPACK_USE_CPP03)
array_size_overflow(const char* msg)
:size_overflow(msg) {}
#endif
};
struct map_size_overflow : public size_overflow {
map_size_overflow(const std::string& msg)
:size_overflow(msg) {}
#if !defined(MSGPACK_USE_CPP03)
map_size_overflow(const char* msg)
:size_overflow(msg) {}
#endif
};
struct str_size_overflow : public size_overflow {
str_size_overflow(const std::string& msg)
:size_overflow(msg) {}
#if !defined(MSGPACK_USE_CPP03)
str_size_overflow(const char* msg)
:size_overflow(msg) {}
#endif
};
struct bin_size_overflow : public size_overflow {
bin_size_overflow(const std::string& msg)
:size_overflow(msg) {}
#if !defined(MSGPACK_USE_CPP03)
bin_size_overflow(const char* msg)
:size_overflow(msg) {}
#endif
};
struct ext_size_overflow : public size_overflow {
ext_size_overflow(const std::string& msg)
:size_overflow(msg) {}
#if !defined(MSGPACK_USE_CPP03)
ext_size_overflow(const char* msg)
:size_overflow(msg) {}
#endif
};
class unpack_limit {
public:
unpack_limit(
std::size_t array = 0xffffffff,
std::size_t map = 0xffffffff,
std::size_t str = 0xffffffff,
std::size_t bin = 0xffffffff,
std::size_t ext = 0xffffffff)
:array_(array),
map_(map),
str_(str),
bin_(bin),
ext_(ext) {}
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_; }
private:
std::size_t array_;
std::size_t map_;
std::size_t str_;
std::size_t bin_;
std::size_t ext_;
};
namespace detail {
class unpack_user {
public:
unpack_user(unpack_reference_func f = nullptr, void* user_data = nullptr)
:m_func(f), m_user_data(user_data) {}
unpack_user(unpack_reference_func f = nullptr,
void* user_data = nullptr,
unpack_limit const& limit = unpack_limit())
:m_func(f), m_user_data(user_data), m_limit(limit) {}
msgpack::zone const& zone() const { return *m_zone; }
msgpack::zone& zone() { return *m_zone; }
void set_zone(msgpack::zone& zone) { m_zone = &zone; }
@ -76,11 +186,15 @@ public:
void set_referenced(bool referenced) { m_referenced = referenced; }
unpack_reference_func reference_func() const { return m_func; }
void* user_data() const { return m_user_data; }
unpack_limit const& limit() const { return m_limit; }
unpack_limit& limit() { return m_limit; }
private:
msgpack::zone* m_zone;
bool m_referenced;
unpack_reference_func m_func;
void* m_user_data;
unpack_limit m_limit;
};
inline void unpack_uint8(uint8_t d, object& o)
@ -128,6 +242,7 @@ inline void unpack_false(object& o)
struct unpack_array {
void operator()(unpack_user& u, uint32_t n, object& o) const {
if (n > u.limit().array()) throw array_size_overflow("array size overflow");
o.type = type::ARRAY;
o.via.array.size = 0;
o.via.array.ptr = static_cast<object*>(u.zone().allocate_align(n*sizeof(object)));
@ -145,6 +260,7 @@ inline void unpack_array_item(object& c, object const& o)
struct unpack_map {
void operator()(unpack_user& u, uint32_t n, object& o) const {
if (n > u.limit().map()) throw map_size_overflow("map size overflow");
o.type = type::MAP;
o.via.map.size = 0;
o.via.map.ptr = static_cast<object_kv*>(u.zone().allocate_align(n*sizeof(object_kv)));
@ -171,6 +287,7 @@ inline void unpack_str(unpack_user& u, const char* p, uint32_t l, object& o)
u.set_referenced(true);
}
else {
if (l > u.limit().str()) throw str_size_overflow("str size overflow");
char* tmp = static_cast<char*>(u.zone().allocate_align(l));
std::memcpy(tmp, p, l);
o.via.str.ptr = tmp;
@ -186,6 +303,7 @@ inline void unpack_bin(unpack_user& u, const char* p, uint32_t l, object& o)
u.set_referenced(true);
}
else {
if (l > u.limit().bin()) throw bin_size_overflow("bin size overflow");
char* tmp = static_cast<char*>(u.zone().allocate_align(l));
std::memcpy(tmp, p, l);
o.via.bin.ptr = tmp;
@ -193,7 +311,7 @@ inline void unpack_bin(unpack_user& u, const char* p, uint32_t l, object& o)
o.via.bin.size = l;
}
inline void unpack_ext(unpack_user& u, const char* p, uint32_t l, object& o)
inline void unpack_ext(unpack_user& u, const char* p, std::size_t l, object& o)
{
o.type = type::EXT;
if (u.reference_func() && u.reference_func()(o.type, l, u.user_data())) {
@ -201,6 +319,7 @@ inline void unpack_ext(unpack_user& u, const char* p, uint32_t l, object& o)
u.set_referenced(true);
}
else {
if (l > u.limit().ext()) throw ext_size_overflow("ext size overflow");
char* tmp = static_cast<char*>(u.zone().allocate_align(l));
std::memcpy(tmp, p, l);
o.via.ext.ptr = tmp;
@ -290,7 +409,8 @@ inline void load(T& dst, const char* n, typename msgpack::enable_if<sizeof(T) ==
class context {
public:
context(unpack_reference_func f, void* user_data):m_trail(0), m_user(f, user_data), m_cs(CS_HEADER), m_top(0)
context(unpack_reference_func f, void* user_data, unpack_limit const& limit)
:m_trail(0), m_user(f, user_data, limit), m_cs(CS_HEADER), m_top(0)
{
m_stack[0].set_obj(object());
}
@ -318,7 +438,130 @@ public:
return m_user;
}
int execute(const char* data, std::size_t len, std::size_t& off)
int execute(const char* data, std::size_t len, std::size_t& off);
private:
template <typename T>
static uint32_t next_cs(T p)
{
return static_cast<uint32_t>(*p) & 0x1f;
}
template <typename T, typename Func>
int push_aggregate(
Func const& f,
uint32_t container_type,
object& obj,
const char* load_pos,
std::size_t& off) {
if(m_top < MSGPACK_EMBED_STACK_SIZE /* FIXME */) {
typename value<T>::type tmp;
load<T>(tmp, load_pos);
f(m_user, tmp, m_stack[m_top].obj());
if(tmp == 0) {
obj = m_stack[m_top].obj();
int ret = push_proc(obj, off);
if (ret != 0) return ret;
}
else {
m_stack[m_top].set_container_type(container_type);
m_stack[m_top].set_count(tmp);
++m_top;
m_cs = CS_HEADER;
++m_current;
}
}
else {
off = m_current - m_start;
return -1;
}
return 0;
}
int push_item(object& obj) {
bool finish = false;
while (!finish) {
if(m_top == 0) {
return 1;
}
m_stack_idx = m_top - 1;
unpack_stack* sp = &m_stack[m_stack_idx];
switch(sp->container_type()) {
case CT_ARRAY_ITEM:
unpack_array_item(sp->obj(), obj);
if(sp->decl_count() == 0) {
obj = sp->obj();
--m_top;
/*printf("stack pop %d\n", m_top);*/
}
else {
finish = true;
}
break;
case CT_MAP_KEY:
sp->set_map_key(obj);
sp->set_container_type(CT_MAP_VALUE);
finish = true;
break;
case CT_MAP_VALUE:
unpack_map_item(sp->obj(), sp->map_key(), obj);
if(sp->decl_count() == 0) {
obj = sp->obj();
--m_top;
/*printf("stack pop %d\n", m_top);*/
}
else {
sp->set_container_type(CT_MAP_KEY);
finish = true;
}
break;
default:
return -1;
}
}
return 0;
}
int push_proc(object& obj, std::size_t& off) {
int ret = push_item(obj);
if (ret > 0) {
m_stack[0].set_obj(obj);
++m_current;
/*printf("-- finish --\n"); */
off = m_current - m_start;
}
else if (ret < 0) {
off = m_current - m_start;
}
else {
m_cs = CS_HEADER;
++m_current;
}
return ret;
}
template <std::size_t N>
static void check_ext_size(std::size_t size) {
}
private:
char const* m_start;
char const* m_current;
std::size_t m_trail;
unpack_user m_user;
uint32_t m_cs;
uint32_t m_top;
uint32_t m_stack_idx;
unpack_stack m_stack[MSGPACK_EMBED_STACK_SIZE];
};
template <>
inline void context::check_ext_size<4>(std::size_t size) {
if (size == 0xffffffff) throw ext_size_overflow("ext size overflow");
}
inline int context::execute(const char* data, std::size_t len, std::size_t& off)
{
assert(len >= off);
@ -647,7 +890,9 @@ public:
case CS_EXT_32: {
uint32_t tmp;
load<uint32_t>(tmp, n);
m_trail = tmp + 1;
check_ext_size<sizeof(std::size_t)>(tmp);
m_trail = tmp;
++m_trail;
if(m_trail == 0) {
unpack_ext(m_user, n, m_trail, obj);
int ret = push_proc(obj, off);
@ -706,132 +951,9 @@ public:
return 0;
}
private:
template <typename T>
static uint32_t next_cs(T p)
{
return static_cast<uint32_t>(*p) & 0x1f;
}
template <typename T, typename Func>
int push_aggregate(
Func const& f,
uint32_t container_type,
object& obj,
const char* load_pos,
std::size_t& off) {
if(m_top < MSGPACK_EMBED_STACK_SIZE /* FIXME */) {
typename value<T>::type tmp;
load<T>(tmp, load_pos);
f(m_user, tmp, m_stack[m_top].obj());
if(tmp == 0) {
obj = m_stack[m_top].obj();
int ret = push_proc(obj, off);
if (ret != 0) return ret;
}
else {
m_stack[m_top].set_container_type(container_type);
m_stack[m_top].set_count(tmp);
++m_top;
m_cs = CS_HEADER;
++m_current;
}
}
else {
off = m_current - m_start;
return -1;
}
return 0;
}
int push_item(object& obj) {
bool finish = false;
while (!finish) {
if(m_top == 0) {
return 1;
}
m_stack_idx = m_top - 1;
unpack_stack* sp = &m_stack[m_stack_idx];
switch(sp->container_type()) {
case CT_ARRAY_ITEM:
unpack_array_item(sp->obj(), obj);
if(sp->decl_count() == 0) {
obj = sp->obj();
--m_top;
/*printf("stack pop %d\n", m_top);*/
}
else {
finish = true;
}
break;
case CT_MAP_KEY:
sp->set_map_key(obj);
sp->set_container_type(CT_MAP_VALUE);
finish = true;
break;
case CT_MAP_VALUE:
unpack_map_item(sp->obj(), sp->map_key(), obj);
if(sp->decl_count() == 0) {
obj = sp->obj();
--m_top;
/*printf("stack pop %d\n", m_top);*/
}
else {
sp->set_container_type(CT_MAP_KEY);
finish = true;
}
break;
default:
return -1;
}
}
return 0;
}
int push_proc(object& obj, std::size_t& off) {
int ret = push_item(obj);
if (ret > 0) {
m_stack[0].set_obj(obj);
++m_current;
/*printf("-- finish --\n"); */
off = m_current - m_start;
}
else if (ret < 0) {
off = m_current - m_start;
}
else {
m_cs = CS_HEADER;
++m_current;
}
return ret;
}
private:
char const* m_start;
char const* m_current;
uint32_t m_trail;
unpack_user m_user;
uint32_t m_cs;
uint32_t m_top;
uint32_t m_stack_idx;
unpack_stack m_stack[MSGPACK_EMBED_STACK_SIZE];
};
} // detail
struct unpack_error : public std::runtime_error {
#if defined(MSGPACK_USE_CPP03)
unpack_error(const std::string& msg) :
std::runtime_error(msg) { }
#else
unpack_error(const char* msg) :
std::runtime_error(msg) { }
#endif
};
class unpacked {
public:
unpacked() {}
@ -861,7 +983,8 @@ class unpacker {
public:
unpacker(unpack_reference_func f = &unpacker::default_reference_func,
void* user_data = nullptr,
std::size_t init_buffer_size = MSGPACK_UNPACKER_INIT_BUFFER_SIZE);
std::size_t init_buffer_size = MSGPACK_UNPACKER_INIT_BUFFER_SIZE,
unpack_limit const& limit = unpack_limit());
#if !defined(MSGPACK_USE_CPP03)
unpacker(unpacker&& other);
@ -987,37 +1110,47 @@ private:
inline unpacked unpack(
const char* data, std::size_t len, std::size_t& off, bool& referenced,
unpack_reference_func f = nullptr, void* user_data = nullptr);
unpack_reference_func f = nullptr, void* user_data = nullptr,
unpack_limit const& limit = unpack_limit());
inline unpacked unpack(
const char* data, std::size_t len, std::size_t& off,
unpack_reference_func f = nullptr, void* user_data = nullptr);
unpack_reference_func f = nullptr, void* user_data = nullptr,
unpack_limit const& limit = unpack_limit());
inline unpacked unpack(
const char* data, std::size_t len, bool& referenced,
unpack_reference_func f = nullptr, void* user_data = nullptr);
unpack_reference_func f = nullptr, void* user_data = nullptr,
unpack_limit const& limit = unpack_limit());
inline unpacked unpack(
const char* data, std::size_t len,
unpack_reference_func f = nullptr, void* user_data = nullptr);
unpack_reference_func f = nullptr, void* user_data = nullptr,
unpack_limit const& limit = unpack_limit());
#endif // !defined(MSGPACK_USE_CPP03)
inline void unpack(unpacked& result,
const char* data, std::size_t len, std::size_t& off, bool& referenced,
unpack_reference_func f = nullptr, void* user_data = nullptr);
unpack_reference_func f = nullptr, void* user_data = nullptr,
unpack_limit const& limit = unpack_limit());
inline void unpack(unpacked& result,
const char* data, std::size_t len, std::size_t& off,
unpack_reference_func f = nullptr, void* user_data = nullptr);
unpack_reference_func f = nullptr, void* user_data = nullptr,
unpack_limit const& limit = unpack_limit());
inline void unpack(unpacked& result,
const char* data, std::size_t len, bool& referenced,
unpack_reference_func f = nullptr, void* user_data = nullptr);
unpack_reference_func f = nullptr, void* user_data = nullptr,
unpack_limit const& limit = unpack_limit());
inline void unpack(unpacked& result,
const char* data, std::size_t len,
unpack_reference_func f = nullptr, void* user_data = nullptr);
unpack_reference_func f = nullptr, void* user_data = nullptr,
unpack_limit const& limit = unpack_limit());
// obsolete
inline void unpack(unpacked* result,
const char* data, std::size_t len, std::size_t* off = nullptr, bool* referenced = nullptr,
unpack_reference_func f = nullptr, void* user_data = nullptr);
unpack_reference_func f = nullptr, void* user_data = nullptr,
unpack_limit const& limit = unpack_limit());
// for internal use
@ -1030,8 +1163,9 @@ typedef enum {
inline unpacker::unpacker(unpack_reference_func f,
void* user_data,
std::size_t initial_buffer_size)
:m_z(new zone), m_ctx(f, user_data)
std::size_t initial_buffer_size,
unpack_limit const& limit)
:m_z(new zone), m_ctx(f, user_data, limit)
{
if(initial_buffer_size < COUNTER_SIZE) {
initial_buffer_size = COUNTER_SIZE;
@ -1181,7 +1315,7 @@ inline bool unpacker::next(unpacked& result, bool& referenced)
referenced = false;
int ret = execute_imp();
if(ret < 0) {
throw unpack_error("parse error");
throw parse_error("parse error");
}
if(ret == 0) {
@ -1214,7 +1348,7 @@ inline bool unpacker::execute()
{
int ret = execute_imp();
if(ret < 0) {
throw unpack_error("parse error");
throw parse_error("parse error");
} else if(ret == 0) {
return false;
} else {
@ -1314,7 +1448,8 @@ namespace detail {
inline unpack_return
unpack_imp(const char* data, std::size_t len, std::size_t& off,
zone& result_zone, object& result, bool& referenced,
unpack_reference_func f = nullptr, void* user_data = nullptr)
unpack_reference_func f = nullptr, void* user_data = nullptr,
unpack_limit const& limit = unpack_limit())
{
std::size_t noff = off;
@ -1323,7 +1458,7 @@ unpack_imp(const char* data, std::size_t len, std::size_t& off,
return UNPACK_CONTINUE;
}
detail::context ctx(f, user_data);
detail::context ctx(f, user_data, limit);
ctx.init();
ctx.user().set_zone(result_zone);
@ -1359,13 +1494,13 @@ unpack_imp(const char* data, std::size_t len, std::size_t& off,
inline unpacked unpack(
const char* data, std::size_t len, std::size_t& off, bool& referenced,
unpack_reference_func f, void* user_data)
unpack_reference_func f, void* user_data, unpack_limit const& limit)
{
object obj;
msgpack::unique_ptr<zone> z(new zone);
referenced = false;
unpack_return ret = detail::unpack_imp(
data, len, off, *z, obj, referenced, f, user_data);
data, len, off, *z, obj, referenced, f, user_data, limit);
switch(ret) {
case UNPACK_SUCCESS:
@ -1373,37 +1508,37 @@ inline unpacked unpack(
case UNPACK_EXTRA_BYTES:
return unpacked(obj, msgpack::move(z));
case UNPACK_CONTINUE:
throw unpack_error("insufficient bytes");
throw insufficient_bytes("insufficient bytes");
case UNPACK_PARSE_ERROR:
default:
throw unpack_error("parse error");
throw parse_error("parse error");
}
return unpacked();
}
inline unpacked unpack(
const char* data, std::size_t len, std::size_t& off,
unpack_reference_func f, void* user_data)
unpack_reference_func f, void* user_data, unpack_limit const& limit)
{
bool referenced;
return unpack(data, len, off, referenced, f, user_data);
return unpack(data, len, off, referenced, f, user_data, limit);
}
inline unpacked unpack(
const char* data, std::size_t len, bool& referenced,
unpack_reference_func f, void* user_data)
unpack_reference_func f, void* user_data, unpack_limit const& limit)
{
std::size_t off = 0;
return unpack(data, len, off, referenced, f, user_data);
return unpack(data, len, off, referenced, f, user_data, limit);
}
inline unpacked unpack(
const char* data, std::size_t len,
unpack_reference_func f, void* user_data)
unpack_reference_func f, void* user_data, unpack_limit const& limit)
{
bool referenced;
std::size_t off = 0;
return unpack(data, len, off, referenced, f, user_data);
return unpack(data, len, off, referenced, f, user_data, limit);
}
#endif // !defined(MSGPACK_USE_CPP03)
@ -1411,13 +1546,13 @@ inline unpacked unpack(
inline void unpack(unpacked& result,
const char* data, std::size_t len, std::size_t& off, bool& referenced,
unpack_reference_func f, void* user_data)
unpack_reference_func f, void* user_data, unpack_limit const& limit)
{
object obj;
msgpack::unique_ptr<zone> z(new zone);
referenced = false;
unpack_return ret = detail::unpack_imp(
data, len, off, *z, obj, referenced, f, user_data);
data, len, off, *z, obj, referenced, f, user_data, limit);
switch(ret) {
case UNPACK_SUCCESS:
@ -1429,50 +1564,50 @@ inline void unpack(unpacked& result,
result.zone() = msgpack::move(z);
return;
case UNPACK_CONTINUE:
throw unpack_error("insufficient bytes");
throw insufficient_bytes("insufficient bytes");
case UNPACK_PARSE_ERROR:
default:
throw unpack_error("parse error");
throw parse_error("parse error");
}
}
inline void unpack(unpacked& result,
const char* data, std::size_t len, std::size_t& off,
unpack_reference_func f, void* user_data)
unpack_reference_func f, void* user_data, unpack_limit const& limit)
{
bool referenced;
unpack(result, data, len, off, referenced, f, user_data);
unpack(result, data, len, off, referenced, f, user_data, limit);
}
inline void unpack(unpacked& result,
const char* data, std::size_t len, bool& referenced,
unpack_reference_func f, void* user_data)
unpack_reference_func f, void* user_data, unpack_limit const& limit)
{
std::size_t off = 0;
unpack(result, data, len, off, referenced, f, user_data);
unpack(result, data, len, off, referenced, f, user_data, limit);
}
inline void unpack(unpacked& result,
const char* data, std::size_t len,
unpack_reference_func f, void* user_data)
unpack_reference_func f, void* user_data, unpack_limit const& limit)
{
bool referenced;
std::size_t off = 0;
unpack(result, data, len, off, referenced, f, user_data);
unpack(result, data, len, off, referenced, f, user_data, limit);
}
// obsolete
// pointer version
inline void unpack(unpacked* result,
const char* data, std::size_t len, std::size_t* off, bool* referenced,
unpack_reference_func f, void* user_data)
unpack_reference_func f, void* user_data, unpack_limit const& limit)
{
if (off)
if (referenced) unpack(*result, data, len, *off, *referenced, f, user_data);
else unpack(*result, data, len, *off, f, user_data);
if (referenced) unpack(*result, data, len, *off, *referenced, f, user_data, limit);
else unpack(*result, data, len, *off, f, user_data, limit);
else
if (referenced) unpack(*result, data, len, *referenced, f, user_data);
else unpack(*result, data, len, f, user_data);
if (referenced) unpack(*result, data, len, *referenced, f, user_data, limit);
else unpack(*result, data, len, f, user_data, limit);
}
inline bool unpacker::default_reference_func(type::object_type /*type*/, std::size_t /*len*/, void*)

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