mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-07-03 17:17:13 +02:00
- 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:
parent
2d61fdf865
commit
309e96087a
@ -63,12 +63,87 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
|
|||||||
|
|
||||||
typedef bool (*unpack_reference_func)(type::object_type, std::size_t, void*);
|
typedef bool (*unpack_reference_func)(type::object_type, std::size_t, void*);
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
struct parse_error : public unpack_error {
|
||||||
|
parse_error():unpack_error("parse error") {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct insufficient_bytes : public unpack_error {
|
||||||
|
insufficient_bytes():unpack_error("insufficient bytes") {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct size_overflow : public unpack_error {
|
||||||
|
#if defined(MSGPACK_USE_CPP03)
|
||||||
|
size_overflow(const std::string& msg):unpack_error(msg) {}
|
||||||
|
#else
|
||||||
|
size_overflow(const char* msg):unpack_error(msg) {}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
struct array_size_overflow : public size_overflow {
|
||||||
|
array_size_overflow():size_overflow("array size overflow") {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct map_size_overflow : public size_overflow {
|
||||||
|
map_size_overflow():size_overflow("map size overflow") {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct str_size_overflow : public size_overflow {
|
||||||
|
str_size_overflow():size_overflow("str size overflow") {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bin_size_overflow : public size_overflow {
|
||||||
|
bin_size_overflow():size_overflow("bin size overflow") {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ext_size_overflow : public size_overflow {
|
||||||
|
ext_size_overflow():size_overflow("ext size overflow") {}
|
||||||
|
};
|
||||||
|
|
||||||
|
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 {
|
namespace detail {
|
||||||
|
|
||||||
class unpack_user {
|
class unpack_user {
|
||||||
public:
|
public:
|
||||||
unpack_user(unpack_reference_func f = nullptr, void* user_data = nullptr)
|
unpack_user(unpack_reference_func f = nullptr,
|
||||||
:m_func(f), m_user_data(user_data) {}
|
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 const& zone() const { return *m_zone; }
|
||||||
msgpack::zone& zone() { return *m_zone; }
|
msgpack::zone& zone() { return *m_zone; }
|
||||||
void set_zone(msgpack::zone& zone) { m_zone = &zone; }
|
void set_zone(msgpack::zone& zone) { m_zone = &zone; }
|
||||||
@ -76,11 +151,15 @@ public:
|
|||||||
void set_referenced(bool referenced) { m_referenced = referenced; }
|
void set_referenced(bool referenced) { m_referenced = referenced; }
|
||||||
unpack_reference_func reference_func() const { return m_func; }
|
unpack_reference_func reference_func() const { return m_func; }
|
||||||
void* user_data() const { return m_user_data; }
|
void* user_data() const { return m_user_data; }
|
||||||
|
unpack_limit const& limit() const { return m_limit; }
|
||||||
|
unpack_limit& limit() { return m_limit; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
msgpack::zone* m_zone;
|
msgpack::zone* m_zone;
|
||||||
bool m_referenced;
|
bool m_referenced;
|
||||||
unpack_reference_func m_func;
|
unpack_reference_func m_func;
|
||||||
void* m_user_data;
|
void* m_user_data;
|
||||||
|
unpack_limit m_limit;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void unpack_uint8(uint8_t d, object& o)
|
inline void unpack_uint8(uint8_t d, object& o)
|
||||||
@ -128,6 +207,7 @@ inline void unpack_false(object& o)
|
|||||||
|
|
||||||
struct unpack_array {
|
struct unpack_array {
|
||||||
void operator()(unpack_user& u, uint32_t n, object& o) const {
|
void operator()(unpack_user& u, uint32_t n, object& o) const {
|
||||||
|
if (n > u.limit().array()) throw array_size_overflow();
|
||||||
o.type = type::ARRAY;
|
o.type = type::ARRAY;
|
||||||
o.via.array.size = 0;
|
o.via.array.size = 0;
|
||||||
o.via.array.ptr = static_cast<object*>(u.zone().allocate_align(n*sizeof(object)));
|
o.via.array.ptr = static_cast<object*>(u.zone().allocate_align(n*sizeof(object)));
|
||||||
@ -145,6 +225,7 @@ inline void unpack_array_item(object& c, object const& o)
|
|||||||
|
|
||||||
struct unpack_map {
|
struct unpack_map {
|
||||||
void operator()(unpack_user& u, uint32_t n, object& o) const {
|
void operator()(unpack_user& u, uint32_t n, object& o) const {
|
||||||
|
if (n > u.limit().map()) throw map_size_overflow();
|
||||||
o.type = type::MAP;
|
o.type = type::MAP;
|
||||||
o.via.map.size = 0;
|
o.via.map.size = 0;
|
||||||
o.via.map.ptr = static_cast<object_kv*>(u.zone().allocate_align(n*sizeof(object_kv)));
|
o.via.map.ptr = static_cast<object_kv*>(u.zone().allocate_align(n*sizeof(object_kv)));
|
||||||
@ -171,6 +252,7 @@ inline void unpack_str(unpack_user& u, const char* p, uint32_t l, object& o)
|
|||||||
u.set_referenced(true);
|
u.set_referenced(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (l > u.limit().str()) throw str_size_overflow();
|
||||||
char* tmp = static_cast<char*>(u.zone().allocate_align(l));
|
char* tmp = static_cast<char*>(u.zone().allocate_align(l));
|
||||||
std::memcpy(tmp, p, l);
|
std::memcpy(tmp, p, l);
|
||||||
o.via.str.ptr = tmp;
|
o.via.str.ptr = tmp;
|
||||||
@ -186,6 +268,7 @@ inline void unpack_bin(unpack_user& u, const char* p, uint32_t l, object& o)
|
|||||||
u.set_referenced(true);
|
u.set_referenced(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (l > u.limit().bin()) throw bin_size_overflow();
|
||||||
char* tmp = static_cast<char*>(u.zone().allocate_align(l));
|
char* tmp = static_cast<char*>(u.zone().allocate_align(l));
|
||||||
std::memcpy(tmp, p, l);
|
std::memcpy(tmp, p, l);
|
||||||
o.via.bin.ptr = tmp;
|
o.via.bin.ptr = tmp;
|
||||||
@ -193,7 +276,7 @@ inline void unpack_bin(unpack_user& u, const char* p, uint32_t l, object& o)
|
|||||||
o.via.bin.size = l;
|
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;
|
o.type = type::EXT;
|
||||||
if (u.reference_func() && u.reference_func()(o.type, l, u.user_data())) {
|
if (u.reference_func() && u.reference_func()(o.type, l, u.user_data())) {
|
||||||
@ -201,6 +284,7 @@ inline void unpack_ext(unpack_user& u, const char* p, uint32_t l, object& o)
|
|||||||
u.set_referenced(true);
|
u.set_referenced(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (l > u.limit().ext()) throw ext_size_overflow();
|
||||||
char* tmp = static_cast<char*>(u.zone().allocate_align(l));
|
char* tmp = static_cast<char*>(u.zone().allocate_align(l));
|
||||||
std::memcpy(tmp, p, l);
|
std::memcpy(tmp, p, l);
|
||||||
o.via.ext.ptr = tmp;
|
o.via.ext.ptr = tmp;
|
||||||
@ -290,7 +374,8 @@ inline void load(T& dst, const char* n, typename msgpack::enable_if<sizeof(T) ==
|
|||||||
|
|
||||||
class context {
|
class context {
|
||||||
public:
|
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());
|
m_stack[0].set_obj(object());
|
||||||
}
|
}
|
||||||
@ -318,8 +403,131 @@ public:
|
|||||||
return m_user;
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int context::execute(const char* data, std::size_t len, std::size_t& off)
|
||||||
|
{
|
||||||
assert(len >= off);
|
assert(len >= off);
|
||||||
|
|
||||||
m_start = data;
|
m_start = data;
|
||||||
@ -647,7 +855,9 @@ public:
|
|||||||
case CS_EXT_32: {
|
case CS_EXT_32: {
|
||||||
uint32_t tmp;
|
uint32_t tmp;
|
||||||
load<uint32_t>(tmp, n);
|
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) {
|
if(m_trail == 0) {
|
||||||
unpack_ext(m_user, n, m_trail, obj);
|
unpack_ext(m_user, n, m_trail, obj);
|
||||||
int ret = push_proc(obj, off);
|
int ret = push_proc(obj, off);
|
||||||
@ -704,134 +914,11 @@ public:
|
|||||||
|
|
||||||
off = m_current - m_start;
|
off = m_current - m_start;
|
||||||
return 0;
|
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
|
} // 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 {
|
class unpacked {
|
||||||
public:
|
public:
|
||||||
unpacked() {}
|
unpacked() {}
|
||||||
@ -861,7 +948,8 @@ class unpacker {
|
|||||||
public:
|
public:
|
||||||
unpacker(unpack_reference_func f = &unpacker::default_reference_func,
|
unpacker(unpack_reference_func f = &unpacker::default_reference_func,
|
||||||
void* user_data = nullptr,
|
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)
|
#if !defined(MSGPACK_USE_CPP03)
|
||||||
unpacker(unpacker&& other);
|
unpacker(unpacker&& other);
|
||||||
@ -987,37 +1075,47 @@ private:
|
|||||||
|
|
||||||
inline unpacked unpack(
|
inline unpacked unpack(
|
||||||
const char* data, std::size_t len, std::size_t& off, bool& referenced,
|
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(
|
inline unpacked unpack(
|
||||||
const char* data, std::size_t len, std::size_t& off,
|
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(
|
inline unpacked unpack(
|
||||||
const char* data, std::size_t len, bool& referenced,
|
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(
|
inline unpacked unpack(
|
||||||
const char* data, std::size_t len,
|
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)
|
#endif // !defined(MSGPACK_USE_CPP03)
|
||||||
|
|
||||||
|
|
||||||
inline void unpack(unpacked& result,
|
inline void unpack(unpacked& result,
|
||||||
const char* data, std::size_t len, std::size_t& off, bool& referenced,
|
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,
|
inline void unpack(unpacked& result,
|
||||||
const char* data, std::size_t len, std::size_t& off,
|
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,
|
inline void unpack(unpacked& result,
|
||||||
const char* data, std::size_t len, bool& referenced,
|
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,
|
inline void unpack(unpacked& result,
|
||||||
const char* data, std::size_t len,
|
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
|
// obsolete
|
||||||
inline void unpack(unpacked* result,
|
inline void unpack(unpacked* result,
|
||||||
const char* data, std::size_t len, std::size_t* off = nullptr, bool* referenced = nullptr,
|
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
|
// for internal use
|
||||||
@ -1030,8 +1128,9 @@ typedef enum {
|
|||||||
|
|
||||||
inline unpacker::unpacker(unpack_reference_func f,
|
inline unpacker::unpacker(unpack_reference_func f,
|
||||||
void* user_data,
|
void* user_data,
|
||||||
std::size_t initial_buffer_size)
|
std::size_t initial_buffer_size,
|
||||||
:m_z(new zone), m_ctx(f, user_data)
|
unpack_limit const& limit)
|
||||||
|
:m_z(new zone), m_ctx(f, user_data, limit)
|
||||||
{
|
{
|
||||||
if(initial_buffer_size < COUNTER_SIZE) {
|
if(initial_buffer_size < COUNTER_SIZE) {
|
||||||
initial_buffer_size = COUNTER_SIZE;
|
initial_buffer_size = COUNTER_SIZE;
|
||||||
@ -1181,7 +1280,7 @@ inline bool unpacker::next(unpacked& result, bool& referenced)
|
|||||||
referenced = false;
|
referenced = false;
|
||||||
int ret = execute_imp();
|
int ret = execute_imp();
|
||||||
if(ret < 0) {
|
if(ret < 0) {
|
||||||
throw unpack_error("parse error");
|
throw parse_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ret == 0) {
|
if(ret == 0) {
|
||||||
@ -1214,7 +1313,7 @@ inline bool unpacker::execute()
|
|||||||
{
|
{
|
||||||
int ret = execute_imp();
|
int ret = execute_imp();
|
||||||
if(ret < 0) {
|
if(ret < 0) {
|
||||||
throw unpack_error("parse error");
|
throw parse_error();
|
||||||
} else if(ret == 0) {
|
} else if(ret == 0) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@ -1314,7 +1413,8 @@ namespace detail {
|
|||||||
inline unpack_return
|
inline unpack_return
|
||||||
unpack_imp(const char* data, std::size_t len, std::size_t& off,
|
unpack_imp(const char* data, std::size_t len, std::size_t& off,
|
||||||
zone& result_zone, object& result, bool& referenced,
|
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;
|
std::size_t noff = off;
|
||||||
|
|
||||||
@ -1323,7 +1423,7 @@ unpack_imp(const char* data, std::size_t len, std::size_t& off,
|
|||||||
return UNPACK_CONTINUE;
|
return UNPACK_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::context ctx(f, user_data);
|
detail::context ctx(f, user_data, limit);
|
||||||
ctx.init();
|
ctx.init();
|
||||||
|
|
||||||
ctx.user().set_zone(result_zone);
|
ctx.user().set_zone(result_zone);
|
||||||
@ -1359,13 +1459,13 @@ unpack_imp(const char* data, std::size_t len, std::size_t& off,
|
|||||||
|
|
||||||
inline unpacked unpack(
|
inline unpacked unpack(
|
||||||
const char* data, std::size_t len, std::size_t& off, bool& referenced,
|
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;
|
object obj;
|
||||||
msgpack::unique_ptr<zone> z(new zone);
|
msgpack::unique_ptr<zone> z(new zone);
|
||||||
referenced = false;
|
referenced = false;
|
||||||
unpack_return ret = detail::unpack_imp(
|
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) {
|
switch(ret) {
|
||||||
case UNPACK_SUCCESS:
|
case UNPACK_SUCCESS:
|
||||||
@ -1373,37 +1473,37 @@ inline unpacked unpack(
|
|||||||
case UNPACK_EXTRA_BYTES:
|
case UNPACK_EXTRA_BYTES:
|
||||||
return unpacked(obj, msgpack::move(z));
|
return unpacked(obj, msgpack::move(z));
|
||||||
case UNPACK_CONTINUE:
|
case UNPACK_CONTINUE:
|
||||||
throw unpack_error("insufficient bytes");
|
throw insufficient_bytes();
|
||||||
case UNPACK_PARSE_ERROR:
|
case UNPACK_PARSE_ERROR:
|
||||||
default:
|
default:
|
||||||
throw unpack_error("parse error");
|
throw parse_error();
|
||||||
}
|
}
|
||||||
return unpacked();
|
return unpacked();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unpacked unpack(
|
inline unpacked unpack(
|
||||||
const char* data, std::size_t len, std::size_t& off,
|
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;
|
bool referenced;
|
||||||
return unpack(data, len, off, referenced, f, user_data);
|
return unpack(data, len, off, referenced, f, user_data, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unpacked unpack(
|
inline unpacked unpack(
|
||||||
const char* data, std::size_t len, bool& referenced,
|
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;
|
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(
|
inline unpacked unpack(
|
||||||
const char* data, std::size_t len,
|
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;
|
bool referenced;
|
||||||
std::size_t off = 0;
|
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)
|
#endif // !defined(MSGPACK_USE_CPP03)
|
||||||
@ -1411,13 +1511,13 @@ inline unpacked unpack(
|
|||||||
|
|
||||||
inline void unpack(unpacked& result,
|
inline void unpack(unpacked& result,
|
||||||
const char* data, std::size_t len, std::size_t& off, bool& referenced,
|
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;
|
object obj;
|
||||||
msgpack::unique_ptr<zone> z(new zone);
|
msgpack::unique_ptr<zone> z(new zone);
|
||||||
referenced = false;
|
referenced = false;
|
||||||
unpack_return ret = detail::unpack_imp(
|
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) {
|
switch(ret) {
|
||||||
case UNPACK_SUCCESS:
|
case UNPACK_SUCCESS:
|
||||||
@ -1429,50 +1529,50 @@ inline void unpack(unpacked& result,
|
|||||||
result.zone() = msgpack::move(z);
|
result.zone() = msgpack::move(z);
|
||||||
return;
|
return;
|
||||||
case UNPACK_CONTINUE:
|
case UNPACK_CONTINUE:
|
||||||
throw unpack_error("insufficient bytes");
|
throw insufficient_bytes();
|
||||||
case UNPACK_PARSE_ERROR:
|
case UNPACK_PARSE_ERROR:
|
||||||
default:
|
default:
|
||||||
throw unpack_error("parse error");
|
throw parse_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void unpack(unpacked& result,
|
inline void unpack(unpacked& result,
|
||||||
const char* data, std::size_t len, std::size_t& off,
|
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;
|
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,
|
inline void unpack(unpacked& result,
|
||||||
const char* data, std::size_t len, bool& referenced,
|
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;
|
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,
|
inline void unpack(unpacked& result,
|
||||||
const char* data, std::size_t len,
|
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;
|
bool referenced;
|
||||||
std::size_t off = 0;
|
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
|
// obsolete
|
||||||
// pointer version
|
// pointer version
|
||||||
inline void unpack(unpacked* result,
|
inline void unpack(unpacked* result,
|
||||||
const char* data, std::size_t len, std::size_t* off, bool* referenced,
|
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 (off)
|
||||||
if (referenced) unpack(*result, data, len, *off, *referenced, f, user_data);
|
if (referenced) unpack(*result, data, len, *off, *referenced, f, user_data, limit);
|
||||||
else unpack(*result, data, len, *off, f, user_data);
|
else unpack(*result, data, len, *off, f, user_data, limit);
|
||||||
else
|
else
|
||||||
if (referenced) unpack(*result, data, len, *referenced, f, user_data);
|
if (referenced) unpack(*result, data, len, *referenced, f, user_data, limit);
|
||||||
else unpack(*result, data, len, f, user_data);
|
else unpack(*result, data, len, f, user_data, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool unpacker::default_reference_func(type::object_type /*type*/, std::size_t /*len*/, void*)
|
inline bool unpacker::default_reference_func(type::object_type /*type*/, std::size_t /*len*/, void*)
|
||||||
|
@ -28,6 +28,7 @@ LIST (APPEND check_PROGRAMS
|
|||||||
msgpack_vref.cpp
|
msgpack_vref.cpp
|
||||||
msgpack_c.cpp
|
msgpack_c.cpp
|
||||||
reference.cpp
|
reference.cpp
|
||||||
|
limit.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
IF (MSGPACK_CXX11)
|
IF (MSGPACK_CXX11)
|
||||||
|
@ -24,7 +24,8 @@ check_PROGRAMS = \
|
|||||||
msgpack_vref \
|
msgpack_vref \
|
||||||
msgpack_cpp11 \
|
msgpack_cpp11 \
|
||||||
reference_cpp11 \
|
reference_cpp11 \
|
||||||
reference
|
reference \
|
||||||
|
limit
|
||||||
|
|
||||||
TESTS = $(check_PROGRAMS)
|
TESTS = $(check_PROGRAMS)
|
||||||
|
|
||||||
@ -73,4 +74,6 @@ reference_SOURCES = reference.cpp
|
|||||||
|
|
||||||
reference_cpp11_SOURCES = reference_cpp11.cpp
|
reference_cpp11_SOURCES = reference_cpp11.cpp
|
||||||
|
|
||||||
|
limit_SOURCES = limit.cpp
|
||||||
|
|
||||||
EXTRA_DIST = cases.mpac cases_compact.mpac
|
EXTRA_DIST = cases.mpac cases_compact.mpac
|
||||||
|
509
test/limit.cpp
Normal file
509
test/limit.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user