mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-10-20 05:49:06 +02:00
Update PHP Extension
This commit is contained in:
829
php/msgpack_unpack.c
Normal file
829
php/msgpack_unpack.c
Normal file
@@ -0,0 +1,829 @@
|
||||
|
||||
#include "php.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/php_incomplete_class.h"
|
||||
#include "ext/standard/php_var.h"
|
||||
|
||||
#include "php_msgpack.h"
|
||||
#include "msgpack_pack.h"
|
||||
#include "msgpack_unpack.h"
|
||||
|
||||
#include "msgpack/unpack_define.h"
|
||||
|
||||
#define VAR_ENTRIES_MAX 1024
|
||||
|
||||
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3)
|
||||
# define Z_ADDREF_PP(ppz) ZVAL_ADDREF(*(ppz))
|
||||
# define Z_SET_ISREF_PP(ppz) (*(ppz))->is_ref = 1
|
||||
# define Z_UNSET_ISREF_PP(ppz) (*(ppz))->is_ref = 0
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
zval *data[VAR_ENTRIES_MAX];
|
||||
long used_slots;
|
||||
void *next;
|
||||
} var_entries;
|
||||
|
||||
inline static void msgpack_var_push(
|
||||
php_unserialize_data_t *var_hashx, zval **rval)
|
||||
{
|
||||
var_entries *var_hash, *prev = NULL;
|
||||
|
||||
if (!var_hashx)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var_hash = var_hashx->first;
|
||||
|
||||
while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX)
|
||||
{
|
||||
prev = var_hash;
|
||||
var_hash = var_hash->next;
|
||||
}
|
||||
|
||||
if (!var_hash)
|
||||
{
|
||||
var_hash = emalloc(sizeof(var_entries));
|
||||
var_hash->used_slots = 0;
|
||||
var_hash->next = 0;
|
||||
|
||||
if (!var_hashx->first)
|
||||
{
|
||||
var_hashx->first = var_hash;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev->next = var_hash;
|
||||
}
|
||||
}
|
||||
|
||||
var_hash->data[var_hash->used_slots++] = *rval;
|
||||
}
|
||||
|
||||
inline static int msgpack_var_access(
|
||||
php_unserialize_data_t *var_hashx, long id, zval ***store)
|
||||
{
|
||||
var_entries *var_hash = var_hashx->first;
|
||||
|
||||
while (id >= VAR_ENTRIES_MAX &&
|
||||
var_hash && var_hash->used_slots == VAR_ENTRIES_MAX)
|
||||
{
|
||||
var_hash = var_hash->next;
|
||||
id -= VAR_ENTRIES_MAX;
|
||||
}
|
||||
|
||||
if (!var_hash)
|
||||
{
|
||||
return !SUCCESS;
|
||||
}
|
||||
|
||||
if (id < 0 || id >= var_hash->used_slots)
|
||||
{
|
||||
return !SUCCESS;
|
||||
}
|
||||
|
||||
*store = &var_hash->data[id];
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
inline static int msgpack_unserialize_array(
|
||||
zval **return_value, msgpack_unserialize_data *mpsd,
|
||||
ulong ct, php_unserialize_data_t *var_hash TSRMLS_DC)
|
||||
{
|
||||
ulong i;
|
||||
HashTable *ht;
|
||||
|
||||
msgpack_var_push(var_hash, return_value);
|
||||
|
||||
if (Z_TYPE_PP(return_value) != IS_ARRAY)
|
||||
{
|
||||
array_init(*return_value);
|
||||
}
|
||||
|
||||
ht = HASH_OF(*return_value);
|
||||
|
||||
for (i = 0; i < ct; i++)
|
||||
{
|
||||
zval *val;
|
||||
|
||||
/* value */
|
||||
ALLOC_INIT_ZVAL(val);
|
||||
|
||||
if (msgpack_unserialize_zval(&val, mpsd, var_hash TSRMLS_CC) <= 0)
|
||||
{
|
||||
if (MSGPACK_G(error_display))
|
||||
{
|
||||
zend_error(E_WARNING,
|
||||
"[msgpack] (msgpack_unserialize_array) "
|
||||
"Invalid value");
|
||||
}
|
||||
zval_ptr_dtor(&val);
|
||||
|
||||
return MSGPACK_UNPACK_PARSE_ERROR;
|
||||
}
|
||||
|
||||
/* update */
|
||||
zend_hash_index_update(ht, i, &val, sizeof(zval *), NULL);
|
||||
}
|
||||
|
||||
return MSGPACK_UNPACK_SUCCESS;
|
||||
}
|
||||
|
||||
inline static int msgpack_unserialize_object_type(
|
||||
zval **return_value, msgpack_unserialize_data *mpsd,
|
||||
php_unserialize_data_t *var_hash, zend_bool is_ref TSRMLS_DC)
|
||||
{
|
||||
int ret = MSGPACK_UNPACK_SUCCESS;
|
||||
zval *key, *val, **rval;
|
||||
|
||||
ALLOC_INIT_ZVAL(key);
|
||||
|
||||
if (msgpack_unserialize_zval(&key, mpsd, NULL TSRMLS_CC) <= 0)
|
||||
{
|
||||
zval_ptr_dtor(&key);
|
||||
|
||||
ZVAL_BOOL(*return_value, 0);
|
||||
|
||||
return MSGPACK_UNPACK_PARSE_ERROR;
|
||||
}
|
||||
|
||||
ALLOC_INIT_ZVAL(val);
|
||||
|
||||
if (is_ref)
|
||||
{
|
||||
ret = msgpack_unserialize_zval(&val, mpsd, NULL TSRMLS_CC);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = msgpack_unserialize_zval(&val, mpsd, var_hash TSRMLS_CC);
|
||||
}
|
||||
|
||||
if (ret <= 0)
|
||||
{
|
||||
zval_ptr_dtor(&val);
|
||||
zval_ptr_dtor(&key);
|
||||
|
||||
ZVAL_BOOL(*return_value, 0);
|
||||
|
||||
return MSGPACK_UNPACK_PARSE_ERROR;
|
||||
}
|
||||
|
||||
if (!var_hash ||
|
||||
msgpack_var_access(var_hash, Z_LVAL_P(val) - 1, &rval) != SUCCESS)
|
||||
{
|
||||
if (MSGPACK_G(error_display))
|
||||
{
|
||||
zend_error(E_WARNING,
|
||||
"[msgpack] (msgpack_unserialize_object_key) "
|
||||
"Invalid references value: %ld",
|
||||
Z_LVAL_P(val) - 1);
|
||||
}
|
||||
ret = MSGPACK_UNPACK_CONTINUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*return_value != NULL)
|
||||
{
|
||||
zval_ptr_dtor(return_value);
|
||||
}
|
||||
|
||||
*return_value = *rval;
|
||||
|
||||
Z_ADDREF_PP(return_value);
|
||||
|
||||
if (is_ref)
|
||||
{
|
||||
Z_SET_ISREF_PP(return_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Z_UNSET_ISREF_PP(return_value);
|
||||
}
|
||||
}
|
||||
|
||||
zval_ptr_dtor(&key);
|
||||
zval_ptr_dtor(&val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline static int msgpack_unserialize_object(
|
||||
zval **return_value, msgpack_unserialize_data *mpsd,
|
||||
ulong ct, php_unserialize_data_t *var_hash TSRMLS_DC)
|
||||
{
|
||||
int ret = MSGPACK_UNPACK_SUCCESS;
|
||||
|
||||
zend_class_entry *ce, **pce;
|
||||
bool incomplete_class = false;
|
||||
zval *user_func, *retval_ptr, **args[1], *arg_func_name;
|
||||
HashTable *ht;
|
||||
|
||||
zval *key, *val;
|
||||
|
||||
int object = 1;
|
||||
int custom_object = 0;
|
||||
|
||||
/* Get class */
|
||||
ALLOC_INIT_ZVAL(key);
|
||||
|
||||
if (msgpack_unserialize_zval(&key, mpsd, NULL TSRMLS_CC) <= 0)
|
||||
{
|
||||
if (MSGPACK_G(error_display))
|
||||
{
|
||||
zend_error(E_WARNING,
|
||||
"[msgpack] (msgpack_unserialize_object) "
|
||||
"Invalid sign key");
|
||||
}
|
||||
|
||||
zval_ptr_dtor(&key);
|
||||
|
||||
ZVAL_BOOL(*return_value, 0);
|
||||
|
||||
return MSGPACK_UNPACK_PARSE_ERROR;
|
||||
}
|
||||
|
||||
ct--;
|
||||
|
||||
if (Z_TYPE_P(key) == IS_NULL)
|
||||
{
|
||||
ALLOC_INIT_ZVAL(val);
|
||||
|
||||
if (msgpack_unserialize_zval(&val, mpsd, NULL TSRMLS_CC) <= 0)
|
||||
{
|
||||
if (MSGPACK_G(error_display))
|
||||
{
|
||||
zend_error(E_WARNING,
|
||||
"[msgpack] (msgpack_unserialize_object) "
|
||||
"Invalid sign value");
|
||||
}
|
||||
|
||||
zval_ptr_dtor(&val);
|
||||
zval_ptr_dtor(&key);
|
||||
|
||||
ZVAL_BOOL(*return_value, 0);
|
||||
|
||||
return MSGPACK_UNPACK_PARSE_ERROR;
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(val) == IS_LONG)
|
||||
{
|
||||
switch (Z_LVAL_P(val))
|
||||
{
|
||||
case MSGPACK_SERIALIZE_TYPE_REFERENCE:
|
||||
ret = msgpack_unserialize_object_type(
|
||||
return_value, mpsd, var_hash, 1 TSRMLS_CC);
|
||||
|
||||
zval_ptr_dtor(&key);
|
||||
zval_ptr_dtor(&val);
|
||||
|
||||
return ret;
|
||||
case MSGPACK_SERIALIZE_TYPE_OBJECT:
|
||||
ret = msgpack_unserialize_object_type(
|
||||
return_value, mpsd, var_hash, 0 TSRMLS_CC);
|
||||
|
||||
zval_ptr_dtor(&key);
|
||||
zval_ptr_dtor(&val);
|
||||
|
||||
return ret;
|
||||
case MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT:
|
||||
custom_object = 1;
|
||||
|
||||
zval_ptr_dtor(&val);
|
||||
|
||||
ALLOC_INIT_ZVAL(val);
|
||||
|
||||
if (msgpack_unserialize_zval(
|
||||
&val, mpsd, NULL TSRMLS_CC) <= 0)
|
||||
{
|
||||
zval_ptr_dtor(&key);
|
||||
zval_ptr_dtor(&val);
|
||||
|
||||
ZVAL_BOOL(*return_value, 0);
|
||||
|
||||
return MSGPACK_UNPACK_PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
zval_ptr_dtor(&key);
|
||||
zval_ptr_dtor(&val);
|
||||
|
||||
ZVAL_BOOL(*return_value, 0);
|
||||
|
||||
return MSGPACK_UNPACK_PARSE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
object = 0;
|
||||
|
||||
msgpack_var_push(var_hash, return_value);
|
||||
|
||||
if (Z_TYPE_PP(return_value) != IS_ARRAY)
|
||||
{
|
||||
array_init(*return_value);
|
||||
}
|
||||
|
||||
ht = HASH_OF(*return_value);
|
||||
|
||||
ALLOC_INIT_ZVAL(val);
|
||||
|
||||
if (msgpack_unserialize_zval(&val, mpsd, var_hash TSRMLS_CC) <= 0)
|
||||
{
|
||||
if (MSGPACK_G(error_display))
|
||||
{
|
||||
zend_error(E_WARNING,
|
||||
"[msgpack] (msgpack_unserialize_object) "
|
||||
"Invalid sign value");
|
||||
}
|
||||
|
||||
zval_ptr_dtor(&val);
|
||||
zval_ptr_dtor(&key);
|
||||
|
||||
return MSGPACK_UNPACK_PARSE_ERROR;
|
||||
}
|
||||
|
||||
/* update */
|
||||
switch (Z_TYPE_P(key))
|
||||
{
|
||||
case IS_LONG:
|
||||
zend_hash_index_update(
|
||||
ht, Z_LVAL_P(key), &val, sizeof(zval *), NULL);
|
||||
break;
|
||||
case IS_STRING:
|
||||
zend_symtable_update(
|
||||
ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1,
|
||||
&val, sizeof(zval *), NULL);
|
||||
break;
|
||||
default:
|
||||
zval_ptr_dtor(&key);
|
||||
zval_ptr_dtor(&val);
|
||||
|
||||
return MSGPACK_UNPACK_PARSE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
zval_ptr_dtor(&key);
|
||||
|
||||
if (object)
|
||||
{
|
||||
convert_to_string(val);
|
||||
|
||||
do {
|
||||
/* Try to find class directly */
|
||||
if (zend_lookup_class(
|
||||
Z_STRVAL_P(val), Z_STRLEN_P(val), &pce TSRMLS_CC) == SUCCESS)
|
||||
{
|
||||
ce = *pce;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check for unserialize callback */
|
||||
if ((PG(unserialize_callback_func) == NULL) ||
|
||||
(PG(unserialize_callback_func)[0] == '\0'))
|
||||
{
|
||||
incomplete_class = 1;
|
||||
ce = PHP_IC_ENTRY;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Call unserialize callback */
|
||||
ALLOC_INIT_ZVAL(user_func);
|
||||
ZVAL_STRING(user_func, PG(unserialize_callback_func), 1);
|
||||
args[0] = &arg_func_name;
|
||||
ALLOC_INIT_ZVAL(arg_func_name);
|
||||
ZVAL_STRING(arg_func_name, Z_STRVAL_P(val), 1);
|
||||
if (call_user_function_ex(
|
||||
CG(function_table), NULL, user_func, &retval_ptr,
|
||||
1, args, 0, NULL TSRMLS_CC) != SUCCESS)
|
||||
{
|
||||
if (MSGPACK_G(error_display))
|
||||
{
|
||||
zend_error(E_WARNING,
|
||||
"[msgpack] (msgpack_unserialize_object) "
|
||||
"defined (%s) but not found", Z_STRVAL_P(val));
|
||||
}
|
||||
|
||||
incomplete_class = 1;
|
||||
ce = PHP_IC_ENTRY;
|
||||
zval_ptr_dtor(&user_func);
|
||||
zval_ptr_dtor(&arg_func_name);
|
||||
break;
|
||||
}
|
||||
if (retval_ptr)
|
||||
{
|
||||
zval_ptr_dtor(&retval_ptr);
|
||||
}
|
||||
|
||||
/* The callback function may have defined the class */
|
||||
if (zend_lookup_class(
|
||||
Z_STRVAL_P(val), Z_STRLEN_P(val), &pce TSRMLS_CC) == SUCCESS)
|
||||
{
|
||||
ce = *pce;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MSGPACK_G(error_display))
|
||||
{
|
||||
zend_error(E_WARNING,
|
||||
"[msgpack] (msgpack_unserialize_object) "
|
||||
"Function %s() hasn't defined the class"
|
||||
"it was called for", Z_STRVAL_P(val));
|
||||
}
|
||||
|
||||
incomplete_class = true;
|
||||
ce = PHP_IC_ENTRY;
|
||||
}
|
||||
|
||||
zval_ptr_dtor(&user_func);
|
||||
zval_ptr_dtor(&arg_func_name);
|
||||
} while(0);
|
||||
|
||||
if (EG(exception))
|
||||
{
|
||||
if (MSGPACK_G(error_display))
|
||||
{
|
||||
zend_error(E_WARNING,
|
||||
"[msgpack] (msgpack_unserialize_object) "
|
||||
"Exception error");
|
||||
}
|
||||
|
||||
zval_ptr_dtor(&val);
|
||||
|
||||
ZVAL_BOOL(*return_value, 0);
|
||||
|
||||
return MSGPACK_UNPACK_PARSE_ERROR;
|
||||
}
|
||||
|
||||
msgpack_var_push(var_hash, return_value);
|
||||
|
||||
object_init_ex(*return_value, ce);
|
||||
|
||||
/* store incomplete class name */
|
||||
if (incomplete_class)
|
||||
{
|
||||
php_store_class_name(
|
||||
*return_value, Z_STRVAL_P(val), Z_STRLEN_P(val));
|
||||
}
|
||||
|
||||
zval_ptr_dtor(&val);
|
||||
|
||||
/* implementing Serializable */
|
||||
if (custom_object)
|
||||
{
|
||||
zval *rval;
|
||||
|
||||
if (ce->unserialize == NULL)
|
||||
{
|
||||
if (MSGPACK_G(error_display))
|
||||
{
|
||||
zend_error(E_WARNING,
|
||||
"[msgpack] (msgpack_unserialize_object) "
|
||||
"Class %s has no unserializer", ce->name);
|
||||
}
|
||||
|
||||
return MSGPACK_UNPACK_PARSE_ERROR;
|
||||
}
|
||||
|
||||
/* value */
|
||||
ALLOC_INIT_ZVAL(rval);
|
||||
|
||||
if (msgpack_unserialize_zval(&rval, mpsd, var_hash TSRMLS_CC) <= 0)
|
||||
{
|
||||
zval_ptr_dtor(&rval);
|
||||
|
||||
return MSGPACK_UNPACK_PARSE_ERROR;
|
||||
}
|
||||
|
||||
ce->unserialize(
|
||||
return_value, ce,
|
||||
(const unsigned char *)Z_STRVAL_P(rval), Z_STRLEN_P(rval) + 1,
|
||||
(zend_unserialize_data *)var_hash TSRMLS_CC);
|
||||
|
||||
zval_ptr_dtor(&key);
|
||||
zval_ptr_dtor(&rval);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ht = HASH_OF(*return_value);
|
||||
}
|
||||
|
||||
/* object property */
|
||||
while (ct-- > 0)
|
||||
{
|
||||
zval *rval;
|
||||
|
||||
/* key */
|
||||
ALLOC_INIT_ZVAL(key);
|
||||
|
||||
if (msgpack_unserialize_zval(&key, mpsd, NULL TSRMLS_CC) <= 0)
|
||||
{
|
||||
zval_ptr_dtor(&key);
|
||||
|
||||
return MSGPACK_UNPACK_PARSE_ERROR;
|
||||
}
|
||||
|
||||
/* value */
|
||||
ALLOC_INIT_ZVAL(rval);
|
||||
|
||||
if (msgpack_unserialize_zval(&rval, mpsd, var_hash TSRMLS_CC) <= 0)
|
||||
{
|
||||
zval_ptr_dtor(&rval);
|
||||
zval_ptr_dtor(&key);
|
||||
|
||||
return MSGPACK_UNPACK_PARSE_ERROR;
|
||||
|
||||
}
|
||||
|
||||
/* update */
|
||||
switch (Z_TYPE_P(key))
|
||||
{
|
||||
case IS_LONG:
|
||||
zend_hash_index_update(
|
||||
ht, Z_LVAL_P(key), &rval, sizeof(zval *), NULL);
|
||||
break;
|
||||
case IS_STRING:
|
||||
zend_symtable_update(
|
||||
ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1,
|
||||
&rval, sizeof(zval *), NULL);
|
||||
break;
|
||||
default:
|
||||
zval_ptr_dtor(&key);
|
||||
zval_ptr_dtor(&rval);
|
||||
|
||||
return MSGPACK_UNPACK_PARSE_ERROR;
|
||||
}
|
||||
|
||||
zval_ptr_dtor(&key);
|
||||
}
|
||||
|
||||
/* wakeup */
|
||||
if (object && Z_OBJCE_PP(return_value) != PHP_IC_ENTRY &&
|
||||
zend_hash_exists(&Z_OBJCE_PP(return_value)->function_table,
|
||||
"__wakeup", sizeof("__wakeup")))
|
||||
{
|
||||
zval f, *h = NULL;
|
||||
|
||||
INIT_PZVAL(&f);
|
||||
ZVAL_STRINGL(&f, "__wakeup", sizeof("__wakeup") - 1, 0);
|
||||
call_user_function_ex(
|
||||
CG(function_table), return_value, &f, &h, 0, 0, 1, NULL TSRMLS_CC);
|
||||
if (h)
|
||||
{
|
||||
zval_ptr_dtor(&h);
|
||||
}
|
||||
|
||||
if (EG(exception))
|
||||
{
|
||||
ret = MSGPACK_UNPACK_PARSE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int msgpack_unserialize_zval(
|
||||
zval **return_value, msgpack_unserialize_data *mpsd,
|
||||
php_unserialize_data_t *var_hash TSRMLS_DC)
|
||||
{
|
||||
const unsigned char* data = mpsd->data;
|
||||
const unsigned char* const pe = mpsd->data + mpsd->length;
|
||||
const void* n = NULL;
|
||||
|
||||
unsigned int trail = 0;
|
||||
unsigned int cs = CS_HEADER;
|
||||
|
||||
int ret;
|
||||
unsigned int ct;
|
||||
|
||||
#define next_cs(p) ((unsigned int)*p & 0x1f)
|
||||
|
||||
#define finish_zval_long(val_) \
|
||||
msgpack_var_push(var_hash, return_value); \
|
||||
ZVAL_LONG(*return_value, val_); \
|
||||
goto _finish
|
||||
|
||||
#define finish_zval_null() \
|
||||
msgpack_var_push(var_hash, return_value); \
|
||||
ZVAL_NULL(*return_value); \
|
||||
goto _finish
|
||||
|
||||
#define finish_zval_bool(val_) \
|
||||
msgpack_var_push(var_hash, return_value); \
|
||||
ZVAL_BOOL(*return_value, val_); \
|
||||
goto _finish
|
||||
|
||||
#define finish_zval_double(val_) \
|
||||
msgpack_var_push(var_hash, return_value); \
|
||||
ZVAL_DOUBLE(*return_value, val_); \
|
||||
goto _finish
|
||||
|
||||
#define finish_zval_string(val_, len_) \
|
||||
msgpack_var_push(var_hash, return_value); \
|
||||
if (len_ == 0) { ZVAL_STRINGL(*return_value, "", 0, 1); } \
|
||||
else { ZVAL_STRINGL(*return_value, val_, len_, 1); } \
|
||||
goto _finish
|
||||
|
||||
#define finish_zval_array(count_) \
|
||||
ct = count_; \
|
||||
cs = CS_HEADER; \
|
||||
++(mpsd->data); \
|
||||
mpsd->length = (pe - mpsd->data); \
|
||||
if (msgpack_unserialize_array(return_value, mpsd, ct, var_hash TSRMLS_CC) <= 0) { goto _failed; } \
|
||||
goto _finish_end
|
||||
|
||||
#define finish_zval_object(count_) \
|
||||
ct = count_; \
|
||||
cs = CS_HEADER; \
|
||||
++(mpsd->data); \
|
||||
mpsd->length = (pe - mpsd->data); \
|
||||
if (msgpack_unserialize_object(return_value, mpsd, ct, var_hash TSRMLS_CC) <= 0) { goto _failed; } \
|
||||
goto _finish_end
|
||||
|
||||
#define again_fixed_trail(_cs, trail_len) \
|
||||
trail = trail_len; \
|
||||
cs = _cs; \
|
||||
goto _fixed_trail_again
|
||||
|
||||
#define again_fixed_trail_if_zero(_cs, trail_len, ifzero) \
|
||||
trail = trail_len; \
|
||||
if(trail == 0) { goto ifzero; } \
|
||||
cs = _cs; \
|
||||
goto _fixed_trail_again
|
||||
|
||||
if (mpsd->length <= 0)
|
||||
{
|
||||
goto _failed;
|
||||
}
|
||||
|
||||
if (mpsd->data == pe)
|
||||
{
|
||||
goto _out;
|
||||
}
|
||||
do
|
||||
{
|
||||
switch (cs)
|
||||
{
|
||||
case CS_HEADER:
|
||||
switch (*(mpsd->data))
|
||||
{
|
||||
case 0x00 ... 0x7f: /* Positive Fixnum */
|
||||
finish_zval_long(*(uint8_t*)mpsd->data);
|
||||
case 0xe0 ... 0xff: /* Negative Fixnum */
|
||||
finish_zval_long(*(int8_t*)mpsd->data);
|
||||
case 0xc0 ... 0xdf: /* Variable */
|
||||
switch (*(mpsd->data))
|
||||
{
|
||||
case 0xc0: /* nil */
|
||||
finish_zval_null();
|
||||
case 0xc2: /* false */
|
||||
finish_zval_bool(0);
|
||||
case 0xc3: /* true */
|
||||
finish_zval_bool(1);
|
||||
case 0xca: /* float */
|
||||
case 0xcb: /* double */
|
||||
case 0xcc: /* unsigned int 8 */
|
||||
case 0xcd: /* unsigned int 16 */
|
||||
case 0xce: /* unsigned int 32 */
|
||||
case 0xcf: /* unsigned int 64 */
|
||||
case 0xd0: /* signed int 8 */
|
||||
case 0xd1: /* signed int 16 */
|
||||
case 0xd2: /* signed int 32 */
|
||||
case 0xd3: /* signed int 64 */
|
||||
again_fixed_trail(
|
||||
next_cs(mpsd->data),
|
||||
1 << (((unsigned int)*(mpsd->data)) & 0x03));
|
||||
case 0xda: /* raw 16 */
|
||||
case 0xdb: /* raw 32 */
|
||||
case 0xdc: /* array 16 */
|
||||
case 0xdd: /* array 32 */
|
||||
case 0xde: /* map 16 */
|
||||
case 0xdf: /* map 32 */
|
||||
again_fixed_trail(
|
||||
next_cs(mpsd->data),
|
||||
2 << (((unsigned int)*(mpsd->data)) & 0x01));
|
||||
default:
|
||||
goto _failed;
|
||||
}
|
||||
case 0xa0 ... 0xbf: /* FixRaw */
|
||||
again_fixed_trail_if_zero(
|
||||
ACS_RAW_VALUE, (unsigned int)*(mpsd->data) & 0x1f,
|
||||
_raw_zero);
|
||||
case 0x90 ... 0x9f: /* FixArray */
|
||||
finish_zval_array(((unsigned int)*(mpsd->data)) & 0x0f);
|
||||
case 0x80 ... 0x8f: /* FixMap */
|
||||
finish_zval_object(((unsigned int)*(mpsd->data)) & 0x0f);
|
||||
default:
|
||||
goto _failed;
|
||||
}
|
||||
_fixed_trail_again:
|
||||
++(mpsd->data);
|
||||
default:
|
||||
if ((size_t)(pe - (mpsd->data)) < trail)
|
||||
{
|
||||
goto _out;
|
||||
}
|
||||
n = (mpsd->data);
|
||||
mpsd->data += trail - 1;
|
||||
switch (cs)
|
||||
{
|
||||
case CS_FLOAT:
|
||||
{
|
||||
union { uint32_t i; float f; } mem;
|
||||
mem.i = _msgpack_load32(uint32_t, n);
|
||||
finish_zval_double(mem.f);
|
||||
}
|
||||
case CS_DOUBLE:
|
||||
{
|
||||
union { uint64_t i; double f; } mem;
|
||||
mem.i = _msgpack_load64(uint64_t, n);
|
||||
finish_zval_double(mem.f);
|
||||
}
|
||||
case CS_UINT_8:
|
||||
finish_zval_long(*(uint8_t*)n);
|
||||
case CS_UINT_16:
|
||||
finish_zval_long(_msgpack_load16(uint16_t, n));
|
||||
case CS_UINT_32:
|
||||
finish_zval_long(_msgpack_load32(uint32_t, n));
|
||||
case CS_UINT_64:
|
||||
finish_zval_long(_msgpack_load64(uint64_t, n));
|
||||
case CS_INT_8:
|
||||
finish_zval_long(*(int8_t*)n);
|
||||
case CS_INT_16:
|
||||
finish_zval_long(_msgpack_load16(int16_t, n));
|
||||
case CS_INT_32:
|
||||
finish_zval_long(_msgpack_load32(int32_t, n));
|
||||
case CS_INT_64:
|
||||
finish_zval_long(_msgpack_load64(int64_t, n));
|
||||
case CS_RAW_16:
|
||||
again_fixed_trail_if_zero(
|
||||
ACS_RAW_VALUE, _msgpack_load16(uint16_t, n),
|
||||
_raw_zero);
|
||||
case CS_RAW_32:
|
||||
again_fixed_trail_if_zero(
|
||||
ACS_RAW_VALUE, _msgpack_load32(uint32_t, n),
|
||||
_raw_zero);
|
||||
case ACS_RAW_VALUE:
|
||||
_raw_zero:
|
||||
finish_zval_string(n, trail);
|
||||
case CS_ARRAY_16:
|
||||
finish_zval_array(_msgpack_load16(uint16_t, n));
|
||||
case CS_ARRAY_32:
|
||||
finish_zval_array(_msgpack_load32(uint32_t, n));
|
||||
/* FIXME security guard */
|
||||
case CS_MAP_16:
|
||||
finish_zval_object(_msgpack_load16(uint16_t, n));
|
||||
case CS_MAP_32:
|
||||
finish_zval_object(_msgpack_load32(uint32_t, n));
|
||||
/* FIXME security guard */
|
||||
default:
|
||||
goto _failed;
|
||||
}
|
||||
}
|
||||
cs = CS_HEADER;
|
||||
++(mpsd->data);
|
||||
}
|
||||
while (mpsd->data != pe);
|
||||
goto _out;
|
||||
|
||||
_finish:
|
||||
++(mpsd->data);
|
||||
_finish_end:
|
||||
ret = MSGPACK_UNPACK_EXTRA_BYTES;
|
||||
goto _end;
|
||||
|
||||
_failed:
|
||||
ret = MSGPACK_UNPACK_PARSE_ERROR;
|
||||
goto _end;
|
||||
|
||||
_out:
|
||||
ret = MSGPACK_UNPACK_CONTINUE;
|
||||
goto _end;
|
||||
|
||||
_end:
|
||||
mpsd->offset = mpsd->data - data;
|
||||
mpsd->length = pe - mpsd->data;
|
||||
|
||||
if (ret == MSGPACK_UNPACK_EXTRA_BYTES && mpsd->length == 0)
|
||||
{
|
||||
ret = MSGPACK_UNPACK_SUCCESS;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef finish_zval_long
|
||||
#undef finish_zval_null
|
||||
#undef finish_zval_bool
|
||||
#undef finish_zval_double
|
||||
#undef finish_zval_string
|
||||
#undef finish_zval_array
|
||||
#undef finish_zval_object
|
||||
#undef again_fixed_trail
|
||||
#undef again_fixed_trail_if_zero
|
||||
|
||||
#undef next_cs
|
Reference in New Issue
Block a user