summaryrefslogtreecommitdiff
path: root/php/msgpack_unpack.c
diff options
context:
space:
mode:
Diffstat (limited to 'php/msgpack_unpack.c')
-rw-r--r--php/msgpack_unpack.c1070
1 files changed, 472 insertions, 598 deletions
diff --git a/php/msgpack_unpack.c b/php/msgpack_unpack.c
index c6b9b3f..f3b610d 100644
--- a/php/msgpack_unpack.c
+++ b/php/msgpack_unpack.c
@@ -2,31 +2,69 @@
#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
+#define VAR_ENTRIES_MAX 1024
+
typedef struct
{
zval *data[VAR_ENTRIES_MAX];
long used_slots;
+ long value_slots;
+ long access_slots[VAR_ENTRIES_MAX];
+ bool alloc_slots[VAR_ENTRIES_MAX];
void *next;
} var_entries;
+#define MSGPACK_UNSERIALIZE_ALLOC(_unpack) \
+ if (_unpack->deps <= 0) { \
+ *obj = _unpack->retval; \
+ msgpack_var_push(_unpack->var_hash, obj, true, false); \
+ } else { \
+ ALLOC_INIT_ZVAL(*obj); \
+ msgpack_var_push(_unpack->var_hash, obj, false, true); \
+ }
+
+#define MSGPACK_UNSERIALIZE_ALLOC_VALUE(_unpack) \
+ if (_unpack->deps <= 0) { \
+ *obj = _unpack->retval; \
+ msgpack_var_push(_unpack->var_hash, obj, true, false); \
+ } else { \
+ ALLOC_INIT_ZVAL(*obj); \
+ msgpack_var_push(_unpack->var_hash, obj, true, true); \
+ }
+
+#define MSGPACK_UNSERIALIZE_PUSH_ITEM(_unpack, _count, _val) \
+ msgpack_var_alloc(_unpack->var_hash, _count); \
+ if (Z_TYPE_P(_val) != IS_ARRAY && Z_TYPE_P(_val) != IS_OBJECT) { \
+ msgpack_var_push(_unpack->var_hash, &_val, true, false); \
+ }
+
+#define MSGPACK_UNSERIALIZE_FINISH_ITEM(_unpack) \
+ long deps = _unpack->deps - 1; \
+ _unpack->stack[deps]--; \
+ if (_unpack->stack[deps] == 0) { \
+ _unpack->deps--; \
+ }
+
+#define MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(_unpack, _key, _val) \
+ zval_ptr_dtor(&_key); \
+ zval_ptr_dtor(&_val); \
+ msgpack_var_alloc(_unpack->var_hash, 2); \
+ MSGPACK_UNSERIALIZE_FINISH_ITEM(_unpack);
+
+
inline static void msgpack_var_push(
- php_unserialize_data_t *var_hashx, zval **rval)
+ php_unserialize_data_t *var_hashx, zval **rval, bool value, bool alloc)
{
var_entries *var_hash, *prev = NULL;
@@ -47,6 +85,7 @@ inline static void msgpack_var_push(
{
var_hash = emalloc(sizeof(var_entries));
var_hash->used_slots = 0;
+ var_hash->value_slots = 0;
var_hash->next = 0;
if (!var_hashx->first)
@@ -59,9 +98,45 @@ inline static void msgpack_var_push(
}
}
+ var_hash->alloc_slots[var_hash->used_slots] = alloc;
+
+ if (value)
+ {
+ var_hash->access_slots[var_hash->value_slots++] = var_hash->used_slots;
+ }
+
var_hash->data[var_hash->used_slots++] = *rval;
}
+inline static void msgpack_var_alloc(
+ php_unserialize_data_t *var_hashx, long count)
+{
+ long i;
+ var_entries *var_hash = var_hashx->first;
+
+ while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX)
+ {
+ var_hash = var_hash->next;
+ }
+
+ if (!var_hash || count <= 0)
+ {
+ return;
+ }
+
+ for (i = var_hash->used_slots - 1; i >= 0; i--)
+ {
+ if (var_hash->alloc_slots[i])
+ {
+ var_hash->alloc_slots[i] = false;
+ if (--count <= 0)
+ {
+ break;
+ }
+ }
+ }
+}
+
inline static int msgpack_var_access(
php_unserialize_data_t *var_hashx, long id, zval ***store)
{
@@ -79,6 +154,13 @@ inline static int msgpack_var_access(
return !SUCCESS;
}
+ if (id < 0 || id >= var_hash->value_slots)
+ {
+ return !SUCCESS;
+ }
+
+ id = var_hash->access_slots[id];
+
if (id < 0 || id >= var_hash->used_slots)
{
return !SUCCESS;
@@ -89,741 +171,533 @@ inline static int msgpack_var_access(
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)
+inline static zend_class_entry* msgpack_unserialize_class(
+ zval **container, char *class_name, size_t name_len)
{
- ulong i;
- HashTable *ht;
-
- msgpack_var_push(var_hash, return_value);
+ zend_class_entry *ce, **pce;
+ bool incomplete_class = false;
+ zval *user_func, *retval_ptr, **args[1], *arg_func_name;
+ TSRMLS_FETCH();
- if (Z_TYPE_PP(return_value) != IS_ARRAY)
+ do
{
- array_init(*return_value);
- }
+ /* Try to find class directly */
+ if (zend_lookup_class(class_name, name_len, &pce TSRMLS_CC) == SUCCESS)
+ {
+ ce = *pce;
+ break;
+ }
- ht = HASH_OF(*return_value);
+ /* Check for unserialize callback */
+ if ((PG(unserialize_callback_func) == NULL) ||
+ (PG(unserialize_callback_func)[0] == '\0'))
+ {
+ incomplete_class = 1;
+ ce = PHP_IC_ENTRY;
+ break;
+ }
- for (i = 0; i < ct; i++)
- {
- zval *val;
+ /* 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, class_name, 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_class) "
+ "defined (%s) but not found", class_name);
+ }
- /* value */
- ALLOC_INIT_ZVAL(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);
+ }
- if (msgpack_unserialize_zval(&val, mpsd, var_hash TSRMLS_CC) <= 0)
+ /* The callback function may have defined the class */
+ if (zend_lookup_class(class_name, name_len, &pce TSRMLS_CC) == SUCCESS)
+ {
+ ce = *pce;
+ }
+ else
{
if (MSGPACK_G(error_display))
{
zend_error(E_WARNING,
- "[msgpack] (msgpack_unserialize_array) "
- "Invalid value");
+ "[msgpack] (msgpack_unserialize_class) "
+ "Function %s() hasn't defined the class "
+ "it was called for", class_name);
}
- zval_ptr_dtor(&val);
- return MSGPACK_UNPACK_PARSE_ERROR;
+ incomplete_class = true;
+ ce = PHP_IC_ENTRY;
}
- /* update */
- zend_hash_index_update(ht, i, &val, sizeof(zval *), NULL);
+ zval_ptr_dtor(&user_func);
+ zval_ptr_dtor(&arg_func_name);
}
+ while(0);
- 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)
+ if (EG(exception))
{
- zval_ptr_dtor(&key);
-
- ZVAL_BOOL(*return_value, 0);
+ if (MSGPACK_G(error_display))
+ {
+ zend_error(E_WARNING,
+ "[msgpack] (msgpack_unserialize_class) "
+ "Exception error");
+ }
- return MSGPACK_UNPACK_PARSE_ERROR;
+ return NULL;
}
- ALLOC_INIT_ZVAL(val);
+ object_init_ex(*container, ce);
- if (is_ref)
- {
- ret = msgpack_unserialize_zval(&val, mpsd, NULL TSRMLS_CC);
- }
- else
+ /* store incomplete class name */
+ if (incomplete_class)
{
- ret = msgpack_unserialize_zval(&val, mpsd, var_hash TSRMLS_CC);
+ php_store_class_name(*container, class_name, name_len);
}
- if (ret <= 0)
- {
- zval_ptr_dtor(&val);
- zval_ptr_dtor(&key);
+ return ce;
+}
- ZVAL_BOOL(*return_value, 0);
+void msgpack_unserialize_var_init(php_unserialize_data_t *var_hashx)
+{
+ var_hashx->first = 0;
+ var_hashx->first_dtor = 0;
+}
- return MSGPACK_UNPACK_PARSE_ERROR;
- }
+void msgpack_unserialize_var_destroy(php_unserialize_data_t *var_hashx)
+{
+ void *next;
+ long i;
+ var_entries *var_hash = var_hashx->first;
- if (!var_hash ||
- msgpack_var_access(var_hash, Z_LVAL_P(val) - 1, &rval) != SUCCESS)
+ while (var_hash)
{
- if (MSGPACK_G(error_display))
+ for (i = 0; i < var_hash->used_slots; i++)
{
- zend_error(E_WARNING,
- "[msgpack] (msgpack_unserialize_object_key) "
- "Invalid references value: %ld",
- Z_LVAL_P(val) - 1);
+ if (var_hash->alloc_slots[i] && var_hash->data[i])
+ {
+ zval_ptr_dtor(&var_hash->data[i]);
+ }
}
- ret = MSGPACK_UNPACK_CONTINUE;
+
+ next = var_hash->next;
+ efree(var_hash);
+ var_hash = next;
}
- else
+
+ /*
+ var_hash = var_hashx->first_dtor;
+
+ while (var_hash)
{
- if (*return_value != NULL)
+ for (i = 0; i < var_hash->used_slots; i++)
{
- zval_ptr_dtor(return_value);
+ zval_ptr_dtor(&var_hash->data[i]);
}
+ next = var_hash->next;
+ efree(var_hash);
+ var_hash = next;
+ }
+ */
+}
- *return_value = *rval;
+void msgpack_unserialize_init(msgpack_unserialize_data *unpack)
+{
+ unpack->deps = 0;
+ unpack->type = MSGPACK_SERIALIZE_TYPE_NONE;
+}
- Z_ADDREF_PP(return_value);
+int msgpack_unserialize_uint8(
+ msgpack_unserialize_data *unpack, uint8_t data, zval **obj)
+{
+ MSGPACK_UNSERIALIZE_ALLOC(unpack);
- if (is_ref)
- {
- Z_SET_ISREF_PP(return_value);
- }
- else
- {
- Z_UNSET_ISREF_PP(return_value);
- }
- }
+ ZVAL_LONG(*obj, data);
- zval_ptr_dtor(&key);
- zval_ptr_dtor(&val);
+ return 0;
+}
+
+int msgpack_unserialize_uint16(
+ msgpack_unserialize_data *unpack, uint16_t data, zval **obj)
+{
+ MSGPACK_UNSERIALIZE_ALLOC(unpack);
- return ret;
+ ZVAL_LONG(*obj, data);
+
+ return 0;
}
-inline static int msgpack_unserialize_object(
- zval **return_value, msgpack_unserialize_data *mpsd,
- ulong ct, php_unserialize_data_t *var_hash TSRMLS_DC)
+int msgpack_unserialize_uint32(
+ msgpack_unserialize_data *unpack, uint32_t data, zval **obj)
{
- int ret = MSGPACK_UNPACK_SUCCESS;
+ MSGPACK_UNSERIALIZE_ALLOC(unpack);
- zend_class_entry *ce, **pce;
- bool incomplete_class = false;
- zval *user_func, *retval_ptr, **args[1], *arg_func_name;
- HashTable *ht;
+ ZVAL_LONG(*obj, data);
- zval *key, *val;
+ return 0;
+}
- int object = 1;
- int custom_object = 0;
+int msgpack_unserialize_uint64(
+ msgpack_unserialize_data *unpack, uint64_t data, zval **obj)
+{
+ MSGPACK_UNSERIALIZE_ALLOC(unpack);
- /* Get class */
- ALLOC_INIT_ZVAL(key);
+ ZVAL_LONG(*obj, data);
- 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");
- }
+ return 0;
+}
- zval_ptr_dtor(&key);
+int msgpack_unserialize_int8(
+ msgpack_unserialize_data *unpack, int8_t data, zval **obj)
+{
+ MSGPACK_UNSERIALIZE_ALLOC(unpack);
- ZVAL_BOOL(*return_value, 0);
+ ZVAL_LONG(*obj, data);
- return MSGPACK_UNPACK_PARSE_ERROR;
- }
+ return 0;
+}
- ct--;
+int msgpack_unserialize_int16(
+ msgpack_unserialize_data *unpack, int16_t data, zval **obj)
+{
+ MSGPACK_UNSERIALIZE_ALLOC(unpack);
- if (Z_TYPE_P(key) == IS_NULL)
- {
- ALLOC_INIT_ZVAL(val);
+ ZVAL_LONG(*obj, data);
- 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");
- }
+ return 0;
+}
- zval_ptr_dtor(&val);
- zval_ptr_dtor(&key);
+int msgpack_unserialize_int32(
+ msgpack_unserialize_data *unpack, int32_t data, zval **obj)
+{
+ MSGPACK_UNSERIALIZE_ALLOC(unpack);
- ZVAL_BOOL(*return_value, 0);
+ ZVAL_LONG(*obj, data);
- return MSGPACK_UNPACK_PARSE_ERROR;
- }
+ return 0;
+}
- 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);
+int msgpack_unserialize_int64(
+ msgpack_unserialize_data *unpack, int64_t data, zval **obj)
+{
+ MSGPACK_UNSERIALIZE_ALLOC(unpack);
- zval_ptr_dtor(&key);
- zval_ptr_dtor(&val);
+ ZVAL_LONG(*obj, data);
- return ret;
- case MSGPACK_SERIALIZE_TYPE_OBJECT:
- ret = msgpack_unserialize_object_type(
- return_value, mpsd, var_hash, 0 TSRMLS_CC);
+ return 0;
+}
- zval_ptr_dtor(&key);
- zval_ptr_dtor(&val);
+int msgpack_unserialize_float(
+ msgpack_unserialize_data *unpack, float data, zval **obj)
+{
+ MSGPACK_UNSERIALIZE_ALLOC(unpack);
- return ret;
- case MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT:
- custom_object = 1;
+ ZVAL_DOUBLE(*obj, data);
- zval_ptr_dtor(&val);
+ return 0;
+}
- ALLOC_INIT_ZVAL(val);
+int msgpack_unserialize_double(
+ msgpack_unserialize_data *unpack, double data, zval **obj)
+{
+ MSGPACK_UNSERIALIZE_ALLOC(unpack);
- if (msgpack_unserialize_zval(
- &val, mpsd, NULL TSRMLS_CC) <= 0)
- {
- zval_ptr_dtor(&key);
- zval_ptr_dtor(&val);
+ ZVAL_DOUBLE(*obj, data);
- ZVAL_BOOL(*return_value, 0);
+ return 0;
+}
- return MSGPACK_UNPACK_PARSE_ERROR;
- }
- break;
- default:
- zval_ptr_dtor(&key);
- zval_ptr_dtor(&val);
+int msgpack_unserialize_nil(msgpack_unserialize_data *unpack, zval **obj)
+{
+ MSGPACK_UNSERIALIZE_ALLOC(unpack);
- ZVAL_BOOL(*return_value, 0);
+ ZVAL_NULL(*obj);
- return MSGPACK_UNPACK_PARSE_ERROR;
- }
- }
+ return 0;
+}
+
+int msgpack_unserialize_true(msgpack_unserialize_data *unpack, zval **obj)
+{
+ MSGPACK_UNSERIALIZE_ALLOC(unpack);
+
+ ZVAL_BOOL(*obj, 1);
+
+ return 0;
+}
+
+int msgpack_unserialize_false(msgpack_unserialize_data *unpack, zval **obj)
+{
+ MSGPACK_UNSERIALIZE_ALLOC(unpack);
+
+ ZVAL_BOOL(*obj, 0);
+
+ return 0;
+}
+
+int msgpack_unserialize_raw(
+ msgpack_unserialize_data *unpack, const char* base,
+ const char* data, unsigned int len, zval **obj)
+{
+ MSGPACK_UNSERIALIZE_ALLOC(unpack);
+
+ if (len == 0)
+ {
+ ZVAL_STRINGL(*obj, "", 0, 1);
}
else
{
- object = 0;
+ ZVAL_STRINGL(*obj, data, len, 1);
+ }
- msgpack_var_push(var_hash, return_value);
+ return 0;
+}
- if (Z_TYPE_PP(return_value) != IS_ARRAY)
- {
- array_init(*return_value);
- }
+int msgpack_unserialize_array(
+ msgpack_unserialize_data *unpack, unsigned int count, zval **obj)
+{
+ MSGPACK_UNSERIALIZE_ALLOC_VALUE(unpack);
- ht = HASH_OF(*return_value);
+ array_init(*obj);
- ALLOC_INIT_ZVAL(val);
+ unpack->stack[unpack->deps++] = count;
- 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");
- }
+ return 0;
+}
- zval_ptr_dtor(&val);
- zval_ptr_dtor(&key);
+int msgpack_unserialize_array_item(
+ msgpack_unserialize_data *unpack, zval **container, zval *obj)
+{
+ MSGPACK_UNSERIALIZE_PUSH_ITEM(unpack, 1, obj);
- return MSGPACK_UNPACK_PARSE_ERROR;
- }
+ add_next_index_zval(*container, obj);
- /* 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);
+ MSGPACK_UNSERIALIZE_FINISH_ITEM(unpack);
- return MSGPACK_UNPACK_PARSE_ERROR;
- }
- }
+ return 0;
+}
- zval_ptr_dtor(&key);
+int msgpack_unserialize_map(
+ msgpack_unserialize_data *unpack, unsigned int count, zval **obj)
+{
+ MSGPACK_UNSERIALIZE_ALLOC_VALUE(unpack);
- if (object)
- {
- convert_to_string(val);
+ unpack->stack[unpack->deps++] = count;
- 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;
- }
+ unpack->type = MSGPACK_SERIALIZE_TYPE_NONE;
- /* Check for unserialize callback */
- if ((PG(unserialize_callback_func) == NULL) ||
- (PG(unserialize_callback_func)[0] == '\0'))
- {
- incomplete_class = 1;
- ce = PHP_IC_ENTRY;
- break;
- }
+ return 0;
+}
- /* 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));
- }
+int msgpack_unserialize_map_item(
+ msgpack_unserialize_data *unpack, zval **container, zval *key, zval *val)
+{
+ TSRMLS_FETCH();
- 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);
- }
+ if (MSGPACK_G(php_only))
+ {
+ if (Z_TYPE_P(key) == IS_NULL)
+ {
+ unpack->type = MSGPACK_SERIALIZE_TYPE_NONE;
- /* 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 (Z_TYPE_P(val) == IS_LONG)
{
- if (MSGPACK_G(error_display))
+ switch (Z_LVAL_P(val))
{
- zend_error(E_WARNING,
- "[msgpack] (msgpack_unserialize_object) "
- "Function %s() hasn't defined the class"
- "it was called for", Z_STRVAL_P(val));
+ case MSGPACK_SERIALIZE_TYPE_REFERENCE:
+ Z_SET_ISREF_PP(container);
+ break;
+ case MSGPACK_SERIALIZE_TYPE_RECURSIVE:
+ unpack->type = MSGPACK_SERIALIZE_TYPE_RECURSIVE;
+ break;
+ case MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT:
+ unpack->type = MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT;
+ break;
+ default:
+ break;
}
-
- incomplete_class = true;
- ce = PHP_IC_ENTRY;
}
+ else if (Z_TYPE_P(val) == IS_STRING)
+ {
+ zend_class_entry *ce = msgpack_unserialize_class(
+ container, Z_STRVAL_P(val), Z_STRLEN_P(val));
- zval_ptr_dtor(&user_func);
- zval_ptr_dtor(&arg_func_name);
- } while(0);
+ if (ce == NULL)
+ {
+ MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);
- if (EG(exception))
- {
- if (MSGPACK_G(error_display))
- {
- zend_error(E_WARNING,
- "[msgpack] (msgpack_unserialize_object) "
- "Exception error");
+ return 0;
+ }
}
- zval_ptr_dtor(&val);
-
- ZVAL_BOOL(*return_value, 0);
+ MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);
- return MSGPACK_UNPACK_PARSE_ERROR;
+ return 0;
}
-
- msgpack_var_push(var_hash, return_value);
-
- object_init_ex(*return_value, ce);
-
- /* store incomplete class name */
- if (incomplete_class)
+ else if (unpack->type == MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT)
{
- php_store_class_name(
- *return_value, Z_STRVAL_P(val), Z_STRLEN_P(val));
- }
+ unpack->type = MSGPACK_SERIALIZE_TYPE_NONE;
- zval_ptr_dtor(&val);
+ zend_class_entry *ce = msgpack_unserialize_class(
+ container, Z_STRVAL_P(key), Z_STRLEN_P(key));
- /* implementing Serializable */
- if (custom_object)
- {
- zval *rval;
+ if (ce == NULL)
+ {
+ MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);
+ return 0;
+ }
+
+ /* implementing Serializable */
if (ce->unserialize == NULL)
{
if (MSGPACK_G(error_display))
{
zend_error(E_WARNING,
- "[msgpack] (msgpack_unserialize_object) "
+ "[msgpack] (msgpack_unserialize_map_item) "
"Class %s has no unserializer", ce->name);
}
- return MSGPACK_UNPACK_PARSE_ERROR;
- }
+ MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);
- /* 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;
+ return 0;
}
ce->unserialize(
- return_value, ce,
- (const unsigned char *)Z_STRVAL_P(rval), Z_STRLEN_P(rval) + 1,
- (zend_unserialize_data *)var_hash TSRMLS_CC);
+ container, ce,
+ (const unsigned char *)Z_STRVAL_P(val), Z_STRLEN_P(val) + 1,
+ NULL TSRMLS_CC);
- zval_ptr_dtor(&key);
- zval_ptr_dtor(&rval);
+ MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);
- return ret;
+ return 0;
}
-
- 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)
+ else if (unpack->type == MSGPACK_SERIALIZE_TYPE_RECURSIVE)
{
- zval_ptr_dtor(&key);
-
- return MSGPACK_UNPACK_PARSE_ERROR;
- }
+ zval **rval;
- /* value */
- ALLOC_INIT_ZVAL(rval);
+ unpack->type = MSGPACK_SERIALIZE_TYPE_NONE;
- if (msgpack_unserialize_zval(&rval, mpsd, var_hash TSRMLS_CC) <= 0)
- {
- zval_ptr_dtor(&rval);
- zval_ptr_dtor(&key);
+ if (msgpack_var_access(
+ unpack->var_hash, Z_LVAL_P(val) - 1, &rval) != SUCCESS)
+ {
+ if (MSGPACK_G(error_display))
+ {
+ zend_error(E_WARNING,
+ "[msgpack] (msgpack_unserialize_map_item) "
+ "Invalid references value: %ld",
+ Z_LVAL_P(val) - 1);
+ }
- return MSGPACK_UNPACK_PARSE_ERROR;
+ MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);
- }
+ return 0;
+ }
- /* 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);
+ if (container != NULL)
+ {
+ zval_ptr_dtor(container);
+ }
- return MSGPACK_UNPACK_PARSE_ERROR;
- }
+ *container = *rval;
- zval_ptr_dtor(&key);
- }
+ Z_ADDREF_PP(container);
- /* 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;
+ MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);
- 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 0;
}
}
- return ret;
-}
+ MSGPACK_UNSERIALIZE_PUSH_ITEM(unpack, 2, val);
-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)
+ if (Z_TYPE_PP(container) != IS_ARRAY && Z_TYPE_PP(container) != IS_OBJECT)
{
- goto _failed;
+ array_init(*container);
}
- if (mpsd->data == pe)
- {
- goto _out;
- }
- do
+ switch (Z_TYPE_P(key))
{
- 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)
+ case IS_LONG:
+ if (zend_hash_index_update(
+ HASH_OF(*container), Z_LVAL_P(key), &val,
+ sizeof(val), NULL) == FAILURE)
+ {
+ zval_ptr_dtor(&val);
+ if (MSGPACK_G(error_display))
{
- goto _out;
+ zend_error(E_WARNING,
+ "[msgpack] (msgpack_unserialize_map_item) "
+ "illegal offset type, skip this decoding");
}
- n = (mpsd->data);
- mpsd->data += trail - 1;
- switch (cs)
+ }
+ break;
+ case IS_STRING:
+ if (zend_symtable_update(
+ HASH_OF(*container), Z_STRVAL_P(key), Z_STRLEN_P(key) + 1,
+ &val, sizeof(val), NULL) == FAILURE)
+ {
+ zval_ptr_dtor(&val);
+ if (MSGPACK_G(error_display))
{
- 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;
+ zend_error(E_WARNING,
+ "[msgpack] (msgpack_unserialize_map_item) "
+ "illegal offset type, skip this decoding");
}
- }
- cs = CS_HEADER;
- ++(mpsd->data);
+ }
+ break;
+ default:
+ zval_ptr_dtor(&val);
+ if (MSGPACK_G(error_display))
+ {
+ zend_error(E_WARNING,
+ "[msgpack] (msgpack_unserialize_map_item) "
+ "illegal offset type, skip this decoding");
+ }
+ break;
}
- 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;
+ zval_ptr_dtor(&key);
- if (ret == MSGPACK_UNPACK_EXTRA_BYTES && mpsd->length == 0)
+ long deps = unpack->deps - 1;
+ unpack->stack[deps]--;
+ if (unpack->stack[deps] == 0)
{
- ret = MSGPACK_UNPACK_SUCCESS;
+ unpack->deps--;
+
+ /* wakeup */
+ if (MSGPACK_G(php_only) &&
+ Z_TYPE_PP(container) == IS_OBJECT &&
+ Z_OBJCE_PP(container) != PHP_IC_ENTRY &&
+ zend_hash_exists(
+ &Z_OBJCE_PP(container)->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), container, &f, &h, 0, 0, 1, NULL TSRMLS_CC);
+ if (h)
+ {
+ zval_ptr_dtor(&h);
+ }
+ }
}
- return ret;
+ return 0;
}
-
-#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