mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-05-29 23:42:40 +02:00
malloc/realloc the stack when its length becomes > MSGPACK_EMBED_STACK_SIZE
This commit is contained in:
parent
87835a4e60
commit
a6ec726ed7
22
c/unpack.c
22
c/unpack.c
@ -44,6 +44,7 @@ struct template_context;
|
|||||||
typedef struct template_context template_context;
|
typedef struct template_context template_context;
|
||||||
|
|
||||||
static void template_init(template_context* ctx);
|
static void template_init(template_context* ctx);
|
||||||
|
static void template_destroy(template_context* ctx);
|
||||||
|
|
||||||
static msgpack_object template_data(template_context* ctx);
|
static msgpack_object template_data(template_context* ctx);
|
||||||
|
|
||||||
@ -215,6 +216,7 @@ bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size)
|
|||||||
void msgpack_unpacker_destroy(msgpack_unpacker* mpac)
|
void msgpack_unpacker_destroy(msgpack_unpacker* mpac)
|
||||||
{
|
{
|
||||||
msgpack_zone_free(mpac->z);
|
msgpack_zone_free(mpac->z);
|
||||||
|
template_destroy(mpac->ctx);
|
||||||
free(mpac->ctx);
|
free(mpac->ctx);
|
||||||
decl_count(mpac->buffer);
|
decl_count(mpac->buffer);
|
||||||
}
|
}
|
||||||
@ -368,6 +370,7 @@ msgpack_unpack_return
|
|||||||
msgpack_unpack(const char* data, size_t len, size_t* off,
|
msgpack_unpack(const char* data, size_t len, size_t* off,
|
||||||
msgpack_zone* z, msgpack_object* result)
|
msgpack_zone* z, msgpack_object* result)
|
||||||
{
|
{
|
||||||
|
msgpack_unpack_return ret = MSGPACK_UNPACK_SUCCESS;
|
||||||
template_context ctx;
|
template_context ctx;
|
||||||
template_init(&ctx);
|
template_init(&ctx);
|
||||||
|
|
||||||
@ -377,23 +380,28 @@ msgpack_unpack(const char* data, size_t len, size_t* off,
|
|||||||
size_t noff = 0;
|
size_t noff = 0;
|
||||||
if(off != NULL) { noff = *off; }
|
if(off != NULL) { noff = *off; }
|
||||||
|
|
||||||
int ret = template_execute(&ctx, data, len, &noff);
|
int e = template_execute(&ctx, data, len, &noff);
|
||||||
if(ret < 0) {
|
if(e < 0) {
|
||||||
return MSGPACK_UNPACK_PARSE_ERROR;
|
ret = MSGPACK_UNPACK_PARSE_ERROR;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(off != NULL) { *off = noff; }
|
if(off != NULL) { *off = noff; }
|
||||||
|
|
||||||
if(ret == 0) {
|
if(e == 0) {
|
||||||
return MSGPACK_UNPACK_CONTINUE;
|
ret = MSGPACK_UNPACK_CONTINUE;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
*result = template_data(&ctx);
|
*result = template_data(&ctx);
|
||||||
|
|
||||||
if(noff < len) {
|
if(noff < len) {
|
||||||
return MSGPACK_UNPACK_EXTRA_BYTES;
|
ret = MSGPACK_UNPACK_EXTRA_BYTES;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
return MSGPACK_UNPACK_SUCCESS;
|
out:
|
||||||
|
template_destroy(&ctx);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,9 +87,15 @@ struct object {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
void convert(T* v) const;
|
void convert(T* v) const;
|
||||||
|
|
||||||
object();
|
|
||||||
object(msgpack_object obj);
|
|
||||||
operator msgpack_object();
|
operator msgpack_object();
|
||||||
|
object(msgpack_object obj);
|
||||||
|
|
||||||
|
object();
|
||||||
|
object(bool v);
|
||||||
|
object(uint64_t v);
|
||||||
|
object(int64_t v);
|
||||||
|
object(double v);
|
||||||
|
object(const char* ptr, size_t size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct implicit_type;
|
struct implicit_type;
|
||||||
@ -184,7 +190,46 @@ inline bool operator!=(const object x, const object y)
|
|||||||
{ return !(x == y); }
|
{ return !(x == y); }
|
||||||
|
|
||||||
|
|
||||||
inline object::object() { }
|
inline object::object()
|
||||||
|
{
|
||||||
|
type = type::NIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object::object(bool v)
|
||||||
|
{
|
||||||
|
type = type::BOOLEAN;
|
||||||
|
via.boolean = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object::object(uint64_t v)
|
||||||
|
{
|
||||||
|
type = type::POSITIVE_INTEGER;
|
||||||
|
via.u64 = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object::object(int64_t v)
|
||||||
|
{
|
||||||
|
if(v >= 0) {
|
||||||
|
type = type::POSITIVE_INTEGER;
|
||||||
|
via.u64 = v;
|
||||||
|
} else {
|
||||||
|
type = type::NEGATIVE_INTEGER;
|
||||||
|
via.i64 = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object::object(double v)
|
||||||
|
{
|
||||||
|
type = type::DOUBLE;
|
||||||
|
via.dec = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object::object(const char* ptr, size_t size)
|
||||||
|
{
|
||||||
|
type = type::RAW;
|
||||||
|
via.raw.size = size;
|
||||||
|
via.raw.ptr = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
inline object::object(msgpack_object obj)
|
inline object::object(msgpack_object obj)
|
||||||
{
|
{
|
||||||
@ -200,7 +245,6 @@ inline object::operator msgpack_object()
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline object::implicit_type object::convert() const
|
inline object::implicit_type object::convert() const
|
||||||
{
|
{
|
||||||
return implicit_type(*this);
|
return implicit_type(*this);
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#define MSGPACK_UNPACK_DEFINE_H__
|
#define MSGPACK_UNPACK_DEFINE_H__
|
||||||
|
|
||||||
#include "msgpack/sysdep.h"
|
#include "msgpack/sysdep.h"
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -28,8 +29,8 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef MSGPACK_MAX_STACK_SIZE
|
#ifndef MSGPACK_EMBED_STACK_SIZE
|
||||||
#define MSGPACK_MAX_STACK_SIZE 16
|
#define MSGPACK_EMBED_STACK_SIZE 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,7 +58,9 @@ msgpack_unpack_struct_decl(_context) {
|
|||||||
unsigned int cs;
|
unsigned int cs;
|
||||||
unsigned int trail;
|
unsigned int trail;
|
||||||
unsigned int top;
|
unsigned int top;
|
||||||
msgpack_unpack_struct(_stack) stack[MSGPACK_MAX_STACK_SIZE];
|
msgpack_unpack_struct(_stack)* stack;
|
||||||
|
unsigned int stack_size;
|
||||||
|
msgpack_unpack_struct(_stack) embed_stack[MSGPACK_EMBED_STACK_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -67,9 +69,18 @@ msgpack_unpack_func(void, _init)(msgpack_unpack_struct(_context)* ctx)
|
|||||||
ctx->cs = CS_HEADER;
|
ctx->cs = CS_HEADER;
|
||||||
ctx->trail = 0;
|
ctx->trail = 0;
|
||||||
ctx->top = 0;
|
ctx->top = 0;
|
||||||
|
ctx->stack = ctx->embed_stack;
|
||||||
|
ctx->stack_size = MSGPACK_EMBED_STACK_SIZE;
|
||||||
ctx->stack[0].obj = msgpack_unpack_callback(_root)(&ctx->user);
|
ctx->stack[0].obj = msgpack_unpack_callback(_root)(&ctx->user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msgpack_unpack_func(void, _destroy)(msgpack_unpack_struct(_context)* ctx)
|
||||||
|
{
|
||||||
|
if(ctx->stack_size != MSGPACK_EMBED_STACK_SIZE) {
|
||||||
|
free(ctx->stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
msgpack_unpack_func(msgpack_unpack_object, _data)(msgpack_unpack_struct(_context)* ctx)
|
msgpack_unpack_func(msgpack_unpack_object, _data)(msgpack_unpack_struct(_context)* ctx)
|
||||||
{
|
{
|
||||||
return (ctx)->stack[0].obj;
|
return (ctx)->stack[0].obj;
|
||||||
@ -119,12 +130,28 @@ msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const c
|
|||||||
#define start_container(func, count_, ct_) \
|
#define start_container(func, count_, ct_) \
|
||||||
if(msgpack_unpack_callback(func)(user, count_, &stack[top].obj) < 0) { goto _failed; } \
|
if(msgpack_unpack_callback(func)(user, count_, &stack[top].obj) < 0) { goto _failed; } \
|
||||||
if((count_) == 0) { obj = stack[top].obj; goto _push; } \
|
if((count_) == 0) { obj = stack[top].obj; goto _push; } \
|
||||||
if(top >= MSGPACK_MAX_STACK_SIZE) { goto _failed; } \
|
|
||||||
stack[top].ct = ct_; \
|
stack[top].ct = ct_; \
|
||||||
stack[top].count = count_; \
|
stack[top].count = count_; \
|
||||||
|
++top; \
|
||||||
/*printf("container %d count %d stack %d\n",stack[top].obj,count_,top);*/ \
|
/*printf("container %d count %d stack %d\n",stack[top].obj,count_,top);*/ \
|
||||||
/*printf("stack push %d\n", top);*/ \
|
/*printf("stack push %d\n", top);*/ \
|
||||||
++top; \
|
if(top >= ctx->stack_size) { \
|
||||||
|
if(ctx->stack_size == MSGPACK_EMBED_STACK_SIZE) { \
|
||||||
|
size_t csize = sizeof(msgpack_unpack_struct(_stack)) * MSGPACK_EMBED_STACK_SIZE; \
|
||||||
|
size_t nsize = csize * 2; \
|
||||||
|
msgpack_unpack_struct(_stack)* tmp = (msgpack_unpack_struct(_stack)*)malloc(nsize); \
|
||||||
|
if(tmp == NULL) { goto _failed; } \
|
||||||
|
memcpy(tmp, ctx->stack, csize); \
|
||||||
|
ctx->stack = tmp; \
|
||||||
|
ctx->stack_size = MSGPACK_EMBED_STACK_SIZE * 2; \
|
||||||
|
} else { \
|
||||||
|
size_t nsize = sizeof(msgpack_unpack_struct(_stack)) * ctx->stack_size * 2; \
|
||||||
|
msgpack_unpack_struct(_stack)* tmp = (msgpack_unpack_struct(_stack)*)realloc(ctx->stack, nsize); \
|
||||||
|
if(tmp == NULL) { goto _failed; } \
|
||||||
|
ctx->stack = tmp; \
|
||||||
|
ctx->stack_size *= 2; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
goto _header_again
|
goto _header_again
|
||||||
|
|
||||||
#define NEXT_CS(p) \
|
#define NEXT_CS(p) \
|
||||||
|
@ -53,6 +53,7 @@ struct template_context;
|
|||||||
typedef struct template_context msgpack_unpack_t;
|
typedef struct template_context msgpack_unpack_t;
|
||||||
|
|
||||||
static void template_init(msgpack_unpack_t* u);
|
static void template_init(msgpack_unpack_t* u);
|
||||||
|
static void template_destroy(msgpack_unpack_t* u);
|
||||||
|
|
||||||
static SV* template_data(msgpack_unpack_t* u);
|
static SV* template_data(msgpack_unpack_t* u);
|
||||||
|
|
||||||
@ -132,6 +133,7 @@ SV* _msgpack_unpack(SV* data, int limit) {
|
|||||||
size_t from = 0;
|
size_t from = 0;
|
||||||
STRLEN dlen;
|
STRLEN dlen;
|
||||||
const char * dptr = SvPV_const(data, dlen);
|
const char * dptr = SvPV_const(data, dlen);
|
||||||
|
SV* obj;
|
||||||
|
|
||||||
template_init(&mp);
|
template_init(&mp);
|
||||||
mp.user = u;
|
mp.user = u;
|
||||||
@ -140,6 +142,9 @@ SV* _msgpack_unpack(SV* data, int limit) {
|
|||||||
ret = template_execute(&mp, dptr, (size_t)dlen, &from);
|
ret = template_execute(&mp, dptr, (size_t)dlen, &from);
|
||||||
mp.user.source = &PL_sv_undef;
|
mp.user.source = &PL_sv_undef;
|
||||||
|
|
||||||
|
obj = template_data(&mp);
|
||||||
|
template_destroy(&mp);
|
||||||
|
|
||||||
if(ret < 0) {
|
if(ret < 0) {
|
||||||
Perl_croak(aTHX_ "parse error.");
|
Perl_croak(aTHX_ "parse error.");
|
||||||
} else if(ret == 0) {
|
} else if(ret == 0) {
|
||||||
@ -148,7 +153,7 @@ SV* _msgpack_unpack(SV* data, int limit) {
|
|||||||
if(from < dlen) {
|
if(from < dlen) {
|
||||||
Perl_croak(aTHX_ "extra bytes.");
|
Perl_croak(aTHX_ "extra bytes.");
|
||||||
}
|
}
|
||||||
return template_data(&mp);
|
return obj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,6 +316,7 @@ XS(xs_unpacker_destroy) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UNPACKER(ST(0), mp);
|
UNPACKER(ST(0), mp);
|
||||||
|
template_destroy(mp);
|
||||||
Safefree(mp);
|
Safefree(mp);
|
||||||
|
|
||||||
XSRETURN(0);
|
XSRETURN(0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user