<<< Breaking change >>>
In the functions unpack() and parse(),
Old behavior: If any parse error is happend, offset is NOT updated.
New behavior: If any parse error is happend, offset is updated to the
position the error happened.

It helps MessagePack format error analysis.

If you want to old behavior, copy the original value of offset and then call unpack()
and/or parse().
This commit is contained in:
Takatoshi Kondo
2017-10-22 17:49:38 +09:00
parent 9513734040
commit 5ece2ef2c7
7 changed files with 338 additions and 37 deletions

View File

@@ -1393,12 +1393,11 @@ inline msgpack::object_handle unpack(
parse_return ret = detail::unpack_imp(
data, len, noff, *z, obj, referenced, f, user_data, limit);
off = noff;
switch(ret) {
case PARSE_SUCCESS:
off = noff;
return msgpack::object_handle(obj, msgpack::move(z));
case PARSE_EXTRA_BYTES:
off = noff;
return msgpack::object_handle(obj, msgpack::move(z));
case PARSE_CONTINUE:
throw msgpack::insufficient_bytes("insufficient bytes");
@@ -1450,14 +1449,13 @@ inline void unpack(
parse_return ret = detail::unpack_imp(
data, len, noff, *z, obj, referenced, f, user_data, limit);
off = noff;
switch(ret) {
case PARSE_SUCCESS:
off = noff;
result.set(obj);
result.zone() = msgpack::move(z);
return;
case PARSE_EXTRA_BYTES:
off = noff;
result.set(obj);
result.zone() = msgpack::move(z);
return;
@@ -1513,12 +1511,11 @@ inline msgpack::object unpack(
parse_return ret = detail::unpack_imp(
data, len, noff, z, obj, referenced, f, user_data, limit);
off = noff;
switch(ret) {
case PARSE_SUCCESS:
off = noff;
return obj;
case PARSE_EXTRA_BYTES:
off = noff;
return obj;
case PARSE_CONTINUE:
throw msgpack::insufficient_bytes("insufficient bytes");

View File

@@ -58,7 +58,6 @@ private:
std::size_t& off) {
typename value<T>::type size;
load<T>(size, load_pos);
++m_current;
if (size == 0) {
if (!sv(size)) {
off = m_current - m_start;
@@ -68,7 +67,7 @@ private:
off = m_current - m_start;
return PARSE_STOP_VISITOR;
}
parse_return ret = m_stack.consume(holder());
parse_return ret = m_stack.consume(holder(), m_current);
if (ret != PARSE_CONTINUE) {
off = m_current - m_start;
return ret;
@@ -85,17 +84,18 @@ private:
return ret;
}
}
++m_current;
m_cs = MSGPACK_CS_HEADER;
return PARSE_CONTINUE;
}
parse_return after_visit_proc(bool visit_result, std::size_t& off) {
++m_current;
if (!visit_result) {
off = m_current - m_start;
return PARSE_STOP_VISITOR;
}
parse_return ret = m_stack.consume(holder());
parse_return ret = m_stack.consume(holder(), m_current);
++m_current;
if (ret != PARSE_CONTINUE) {
off = m_current - m_start;
}
@@ -161,15 +161,21 @@ private:
assert(0);
return PARSE_STOP_VISITOR;
}
parse_return consume(VisitorHolder& visitor_holder) {
parse_return consume(VisitorHolder& visitor_holder, char const*& current) {
while (!m_stack.empty()) {
stack_elem& e = m_stack.back();
switch (e.m_type) {
case MSGPACK_CT_ARRAY_ITEM:
if (!visitor_holder.visitor().end_array_item()) return PARSE_STOP_VISITOR;
if (!visitor_holder.visitor().end_array_item()) {
--current;
return PARSE_STOP_VISITOR;
}
if (--e.m_rest == 0) {
m_stack.pop_back();
if (!visitor_holder.visitor().end_array()) return PARSE_STOP_VISITOR;
if (!visitor_holder.visitor().end_array()) {
--current;
return PARSE_STOP_VISITOR;
}
}
else {
if (!visitor_holder.visitor().start_array_item()) return PARSE_STOP_VISITOR;
@@ -177,15 +183,24 @@ private:
}
break;
case MSGPACK_CT_MAP_KEY:
if (!visitor_holder.visitor().end_map_key()) return PARSE_STOP_VISITOR;
if (!visitor_holder.visitor().end_map_key()) {
--current;
return PARSE_STOP_VISITOR;
}
if (!visitor_holder.visitor().start_map_value()) return PARSE_STOP_VISITOR;
e.m_type = MSGPACK_CT_MAP_VALUE;
return PARSE_CONTINUE;
case MSGPACK_CT_MAP_VALUE:
if (!visitor_holder.visitor().end_map_value()) return PARSE_STOP_VISITOR;
if (!visitor_holder.visitor().end_map_value()) {
--current;
return PARSE_STOP_VISITOR;
}
if (--e.m_rest == 0) {
m_stack.pop_back();
if (!visitor_holder.visitor().end_map()) return PARSE_STOP_VISITOR;
if (!visitor_holder.visitor().end_map()) {
--current;
return PARSE_STOP_VISITOR;
}
}
else {
e.m_type = MSGPACK_CT_MAP_KEY;
@@ -1032,13 +1047,12 @@ parse_imp(const char* data, size_t len, size_t& off, Visitor& v) {
}
detail::parse_helper<Visitor> h(v);
parse_return ret = h.execute(data, len, noff);
off = noff;
switch (ret) {
case PARSE_CONTINUE:
off = noff;
v.insufficient_bytes(noff - 1, noff);
return ret;
case PARSE_SUCCESS:
off = noff;
if(noff < len) {
return PARSE_EXTRA_BYTES;
}

View File

@@ -152,16 +152,13 @@ inline msgpack::object_handle unpack(
msgpack::object obj;
msgpack::unique_ptr<msgpack::zone> z(new msgpack::zone);
referenced = false;
std::size_t noff = off;
parse_return ret = detail::unpack_imp(
data, len, noff, *z, obj, referenced, f, user_data, limit);
data, len, off, *z, obj, referenced, f, user_data, limit);
switch(ret) {
case PARSE_SUCCESS:
off = noff;
return msgpack::object_handle(obj, msgpack::move(z));
case PARSE_EXTRA_BYTES:
off = noff;
return msgpack::object_handle(obj, msgpack::move(z));
default:
break;
@@ -206,18 +203,15 @@ inline void unpack(
msgpack::object obj;
msgpack::unique_ptr<msgpack::zone> z(new msgpack::zone);
referenced = false;
std::size_t noff = off;
parse_return ret = detail::unpack_imp(
data, len, noff, *z, obj, referenced, f, user_data, limit);
data, len, off, *z, obj, referenced, f, user_data, limit);
switch(ret) {
case PARSE_SUCCESS:
off = noff;
result.set(obj);
result.zone() = msgpack::move(z);
return;
case PARSE_EXTRA_BYTES:
off = noff;
result.set(obj);
result.zone() = msgpack::move(z);
return;
@@ -265,17 +259,14 @@ inline msgpack::object unpack(
unpack_limit const& limit)
{
msgpack::object obj;
std::size_t noff = off;
referenced = false;
parse_return ret = detail::unpack_imp(
data, len, noff, z, obj, referenced, f, user_data, limit);
data, len, off, z, obj, referenced, f, user_data, limit);
switch(ret) {
case PARSE_SUCCESS:
off = noff;
return obj;
case PARSE_EXTRA_BYTES:
off = noff;
return obj;
default:
break;