From d3c7ca6d63384081ec1b8ef15de121d10239804b Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Mon, 6 Apr 2015 01:21:51 +0000 Subject: [PATCH 01/75] Mass replace smart_str -> smart_string --- msgpack.c | 10 +++++----- msgpack_class.c | 20 ++++++++++---------- msgpack_pack.c | 22 +++++++++++----------- msgpack_pack.h | 2 +- php_msgpack.h | 4 ++-- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/msgpack.c b/msgpack.c index 3360b31..0868575 100644 --- a/msgpack.c +++ b/msgpack.c @@ -147,7 +147,7 @@ ZEND_GET_MODULE(msgpack) #if HAVE_PHP_SESSION PS_SERIALIZER_ENCODE_FUNC(msgpack) { - smart_str buf = {0}; + smart_string buf = {0}; msgpack_serialize_data_t var_hash; msgpack_serialize_var_init(&var_hash); @@ -159,7 +159,7 @@ PS_SERIALIZER_ENCODE_FUNC(msgpack) *newlen = buf.len; } - smart_str_0(&buf); + smart_string_0(&buf); *newstr = buf.c; msgpack_serialize_var_destroy(&var_hash); @@ -230,7 +230,7 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) } #endif -PHP_MSGPACK_API void php_msgpack_serialize(smart_str *buf, zval *val TSRMLS_DC) +PHP_MSGPACK_API void php_msgpack_serialize(smart_string *buf, zval *val TSRMLS_DC) { msgpack_serialize_data_t var_hash; @@ -298,7 +298,7 @@ PHP_MSGPACK_API void php_msgpack_unserialize( static ZEND_FUNCTION(msgpack_serialize) { zval *parameter; - smart_str buf = {0}; + smart_string buf = {0}; if (zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶meter) == FAILURE) @@ -307,7 +307,7 @@ static ZEND_FUNCTION(msgpack_serialize) } php_msgpack_serialize(&buf, parameter TSRMLS_CC); - smart_str_0(&buf); + smart_string_0(&buf); ZVAL_STRINGL(return_value, buf.c, buf.len, 0); } diff --git a/msgpack_class.c b/msgpack_class.c index 740ca7a..7f2ea33 100644 --- a/msgpack_class.c +++ b/msgpack_class.c @@ -14,7 +14,7 @@ typedef struct { typedef struct { zend_object object; - smart_str buffer; + smart_string buffer; zval *retval; long offset; msgpack_unpack_t mp; @@ -316,7 +316,7 @@ static ZEND_METHOD(msgpack, setOption) static ZEND_METHOD(msgpack, pack) { zval *parameter; - smart_str buf = {0}; + smart_string buf = {0}; int php_only = MSGPACK_G(php_only); MSGPACK_BASE_OBJECT; @@ -334,7 +334,7 @@ static ZEND_METHOD(msgpack, pack) ZVAL_STRINGL(return_value, buf.c, buf.len, 1); - smart_str_free(&buf); + smart_string_free(&buf); } static ZEND_METHOD(msgpack, unpack) @@ -428,7 +428,7 @@ static ZEND_METHOD(msgpack_unpacker, __destruct) { MSGPACK_UNPACKER_OBJECT; - smart_str_free(&unpacker->buffer); + smart_string_free(&unpacker->buffer); if (unpacker->retval != NULL) { @@ -483,7 +483,7 @@ static ZEND_METHOD(msgpack_unpacker, feed) RETURN_FALSE; } - smart_str_appendl(&unpacker->buffer, str, str_len); + smart_string_appendl(&unpacker->buffer, str, str_len); RETURN_TRUE; } @@ -621,16 +621,16 @@ static ZEND_METHOD(msgpack_unpacker, data) static ZEND_METHOD(msgpack_unpacker, reset) { - smart_str buffer = {0}; + smart_string buffer = {0}; MSGPACK_UNPACKER_OBJECT; if (unpacker->buffer.len > unpacker->offset) { - smart_str_appendl(&buffer, unpacker->buffer.c + unpacker->offset, + smart_string_appendl(&buffer, unpacker->buffer.c + unpacker->offset, unpacker->buffer.len - unpacker->offset); } - smart_str_free(&unpacker->buffer); + smart_string_free(&unpacker->buffer); unpacker->buffer.c = NULL; unpacker->buffer.len = 0; @@ -640,10 +640,10 @@ static ZEND_METHOD(msgpack_unpacker, reset) if (buffer.len > 0) { - smart_str_appendl(&unpacker->buffer, buffer.c, buffer.len); + smart_string_appendl(&unpacker->buffer, buffer.c, buffer.len); } - smart_str_free(&buffer); + smart_string_free(&buffer); if (unpacker->retval != NULL) { diff --git a/msgpack_pack.c b/msgpack_pack.c index 0e11f4c..15475fe 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -1,7 +1,7 @@ #include "php.h" #include "php_ini.h" -#include "ext/standard/php_smart_str.h" +#include "ext/standard/php_smart_string.h" #include "ext/standard/php_incomplete_class.h" #include "ext/standard/php_var.h" @@ -10,20 +10,20 @@ #include "msgpack_errors.h" #include "msgpack/pack_define.h" -#define msgpack_pack_user smart_str* +#define msgpack_pack_user smart_string* #define msgpack_pack_inline_func(name) \ static inline void msgpack_pack ## name #define msgpack_pack_inline_func_cint(name) \ static inline void msgpack_pack ## name #define msgpack_pack_append_buffer(user, buf, len) \ - smart_str_appendl(user, (const void*)buf, len) + smart_string_appendl(user, (const void*)buf, len) #include "msgpack/pack_template.h" #if ZEND_MODULE_API_NO < 20090626 # define Z_ISREF_P(pz) PZVAL_IS_REF(pz) #endif -inline static int msgpack_check_ht_is_map(zval *array) +inline static int msgpack_check_ht_is_map(zval *array) { int count = zend_hash_num_elements(Z_ARRVAL_P(array)); @@ -52,7 +52,7 @@ inline static int msgpack_var_add( if ((Z_TYPE_P(var) == IS_OBJECT) && Z_OBJ_HT_P(var)->get_class_entry) { - p = smart_str_print_long( + p = smart_string_print_long( id + sizeof(id) - 1, (((size_t)Z_OBJCE_P(var) << 5) | ((size_t)Z_OBJCE_P(var) >> (sizeof(long) * 8 - 5))) @@ -61,7 +61,7 @@ inline static int msgpack_var_add( } else if (Z_TYPE_P(var) == IS_ARRAY) { - p = smart_str_print_long(id + sizeof(id) - 1, (long)var); + p = smart_string_print_long(id + sizeof(id) - 1, (long)var); len = id + sizeof(id) - 1 - p; } else @@ -88,14 +88,14 @@ inline static int msgpack_var_add( } inline static void msgpack_serialize_string( - smart_str *buf, char *str, size_t len) + smart_string *buf, char *str, size_t len) { msgpack_pack_raw(buf, len); msgpack_pack_raw_body(buf, str, len); } inline static void msgpack_serialize_class( - smart_str *buf, zval *val, zval *retval_ptr, HashTable *var_hash, + smart_string *buf, zval *val, zval *retval_ptr, HashTable *var_hash, char *class_name, zend_uint name_len, zend_bool incomplete_class TSRMLS_DC) { int count; @@ -244,7 +244,7 @@ inline static void msgpack_serialize_class( } inline static void msgpack_serialize_array( - smart_str *buf, zval *val, HashTable *var_hash, zend_bool object, + smart_string *buf, zval *val, HashTable *var_hash, zend_bool object, char* class_name, zend_uint name_len, zend_bool incomplete_class TSRMLS_DC) { HashTable *ht; @@ -423,7 +423,7 @@ inline static void msgpack_serialize_array( } inline static void msgpack_serialize_object( - smart_str *buf, zval *val, HashTable *var_hash, + smart_string *buf, zval *val, HashTable *var_hash, char* class_name, zend_uint name_len, zend_bool incomplete_class TSRMLS_DC) { zval *retval_ptr = NULL; @@ -513,7 +513,7 @@ inline static void msgpack_serialize_object( } void msgpack_serialize_zval( - smart_str *buf, zval *val, HashTable *var_hash TSRMLS_DC) + smart_string *buf, zval *val, HashTable *var_hash TSRMLS_DC) { ulong *var_already; diff --git a/msgpack_pack.h b/msgpack_pack.h index 28ae06a..0c87f38 100644 --- a/msgpack_pack.h +++ b/msgpack_pack.h @@ -17,6 +17,6 @@ enum msgpack_serialize_type }; void msgpack_serialize_zval( - smart_str *buf, zval *val, HashTable *var_hash TSRMLS_DC); + smart_string *buf, zval *val, HashTable *var_hash TSRMLS_DC); #endif diff --git a/php_msgpack.h b/php_msgpack.h index 492c448..b08282b 100644 --- a/php_msgpack.h +++ b/php_msgpack.h @@ -1,7 +1,7 @@ #ifndef PHP_MSGPACK_H #define PHP_MSGPACK_H -#include "ext/standard/php_smart_str.h" /* for smart_str */ +#include "ext/standard/php_smart_string.h" /* for smart_string */ #define PHP_MSGPACK_VERSION "0.5.7-dev" @@ -39,7 +39,7 @@ ZEND_EXTERN_MODULE_GLOBALS(msgpack) #endif PHP_MSGPACK_API void php_msgpack_serialize( - smart_str *buf, zval *val TSRMLS_DC); + smart_string *buf, zval *val TSRMLS_DC); PHP_MSGPACK_API void php_msgpack_unserialize( zval *return_value, char *str, size_t str_len TSRMLS_DC); From bb36411fad0495c57b1173e698aa4b0d037296ba Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Mon, 6 Apr 2015 05:36:28 +0000 Subject: [PATCH 02/75] Update PS_SERIALIZER_ENCODE_FUNC returns a zend_string instead of passing in a char/int to mutate --- msgpack.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/msgpack.c b/msgpack.c index 0868575..39b9efd 100644 --- a/msgpack.c +++ b/msgpack.c @@ -148,23 +148,17 @@ ZEND_GET_MODULE(msgpack) PS_SERIALIZER_ENCODE_FUNC(msgpack) { smart_string buf = {0}; + zend_string *z_string; msgpack_serialize_data_t var_hash; msgpack_serialize_var_init(&var_hash); - - msgpack_serialize_zval(&buf, PS(http_session_vars), var_hash TSRMLS_CC); - - if (newlen) - { - *newlen = buf.len; - } - - smart_string_0(&buf); - *newstr = buf.c; - + msgpack_serialize_zval(&buf, &PS(http_session_vars), var_hash TSRMLS_CC); msgpack_serialize_var_destroy(&var_hash); - return SUCCESS; + z_string = zend_string_init(buf.c, buf.len, 0); + smart_string_free(&buf); + + return z_string; } PS_SERIALIZER_DECODE_FUNC(msgpack) From 39a9afd956327b3edf715934c68f41b19ecfec17 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Mon, 6 Apr 2015 05:38:17 +0000 Subject: [PATCH 03/75] Update PS_SERIALIZER_DECODE_FUNC to use the new hash iteration API, php_session functions also expect smart_string instead of char* + int --- msgpack.c | 48 +++++++++++++----------------------------------- 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/msgpack.c b/msgpack.c index 39b9efd..cd5a4f5 100644 --- a/msgpack.c +++ b/msgpack.c @@ -164,19 +164,14 @@ PS_SERIALIZER_ENCODE_FUNC(msgpack) PS_SERIALIZER_DECODE_FUNC(msgpack) { int ret; - HashTable *tmp_hash; - HashPosition tmp_hash_pos; - char *key_str; + zend_string *key_str; ulong key_long; - uint key_len; zval *tmp; - zval **value; + zval *value; size_t off = 0; msgpack_unpack_t mp; msgpack_unserialize_data_t var_hash; - ALLOC_INIT_ZVAL(tmp); - template_init(&mp); msgpack_unserialize_var_init(&var_hash); @@ -186,39 +181,23 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) ret = template_execute(&mp, (char *)val, (size_t)vallen, &off); - if (ret == MSGPACK_UNPACK_EXTRA_BYTES || ret == MSGPACK_UNPACK_SUCCESS) - { + if (ret == MSGPACK_UNPACK_EXTRA_BYTES || ret == MSGPACK_UNPACK_SUCCESS) { msgpack_unserialize_var_destroy(&var_hash, 0); - tmp_hash = HASH_OF(tmp); - - zend_hash_internal_pointer_reset_ex(tmp_hash, &tmp_hash_pos); - - while (zend_hash_get_current_data_ex( - tmp_hash, (void *)&value, &tmp_hash_pos) == SUCCESS) - { - ret = zend_hash_get_current_key_ex( - tmp_hash, &key_str, &key_len, &key_long, 0, &tmp_hash_pos); - switch (ret) - { - case HASH_KEY_IS_LONG: - /* ??? */ - break; - case HASH_KEY_IS_STRING: - php_set_session_var( - key_str, key_len - 1, *value, NULL TSRMLS_CC); - php_add_session_var(key_str, key_len - 1 TSRMLS_CC); - break; + ZEND_HASH_FOREACH_KEY_VAL(HASH_OF(tmp), key_long, key_str, value) { + if (key_str) { + php_set_session_var(key_str, value, NULL); + php_add_session_var(key_str); + } else { + //unhandled non-string key } - zend_hash_move_forward_ex(tmp_hash, &tmp_hash_pos); - } + } ZEND_HASH_FOREACH_END(); } - else - { + else { msgpack_unserialize_var_destroy(&var_hash, 1); } - zval_ptr_dtor(&tmp); + zval_ptr_dtor(tmp); return SUCCESS; } @@ -303,7 +282,7 @@ static ZEND_FUNCTION(msgpack_serialize) php_msgpack_serialize(&buf, parameter TSRMLS_CC); smart_string_0(&buf); - ZVAL_STRINGL(return_value, buf.c, buf.len, 0); + ZVAL_STRINGL(return_value, buf.c, buf.len); } static ZEND_FUNCTION(msgpack_unserialize) @@ -332,7 +311,6 @@ static ZEND_FUNCTION(msgpack_unserialize) { zval *zv; - ALLOC_INIT_ZVAL(zv); php_msgpack_unserialize(zv, str, str_len TSRMLS_CC); if (msgpack_convert_template(return_value, object, &zv) != SUCCESS) From 2a472e74c0cff5ea6af5ead41a3e4afe8cf77a54 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Mon, 6 Apr 2015 06:26:10 +0000 Subject: [PATCH 04/75] Update msgpack_var_add to use new hash API --- msgpack_pack.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index 15475fe..f463b3b 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -49,40 +49,35 @@ inline static int msgpack_var_add( ulong var_no; char id[32], *p; int len; + zend_string *zstring; - if ((Z_TYPE_P(var) == IS_OBJECT) && Z_OBJ_HT_P(var)->get_class_entry) - { - p = smart_string_print_long( + if ((Z_TYPE_P(var) == IS_OBJECT) && Z_OBJ_P(var)->ce) { + p = zend_print_long_to_buf( id + sizeof(id) - 1, (((size_t)Z_OBJCE_P(var) << 5) | ((size_t)Z_OBJCE_P(var) >> (sizeof(long) * 8 - 5))) + (long)Z_OBJ_HANDLE_P(var)); len = id + sizeof(id) - 1 - p; } - else if (Z_TYPE_P(var) == IS_ARRAY) - { - p = smart_string_print_long(id + sizeof(id) - 1, (long)var); + else if (Z_TYPE_P(var) == IS_ARRAY) { + p = zend_print_long_to_buf(id + sizeof(id) - 1, (long)var); len = id + sizeof(id) - 1 - p; } - else - { + else { return FAILURE; } - if (var_old && zend_hash_find(var_hash, p, len, var_old) == SUCCESS) - { - if (!Z_ISREF_P(var)) - { - var_no = -1; - zend_hash_next_index_insert( - var_hash, &var_no, sizeof(var_no), NULL); + zstring = zend_string_init(p, len, 1); + if (var_old && (var_old = zend_hash_find(var_hash, zstring)) != NULL) { + if (!Z_ISREF_P(var)) { + zend_hash_next_index_insert(var_hash, NULL); } return FAILURE; } var_no = zend_hash_num_elements(var_hash) + 1; - zend_hash_add(var_hash, p, len, &var_no, sizeof(var_no), NULL); + zend_hash_add(var_hash, zstring, NULL); return SUCCESS; } From 805e4a262badc2b6f78d3215352bfed442caef72 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Mon, 6 Apr 2015 06:36:49 +0000 Subject: [PATCH 05/75] zend_uint -> uint32_t --- msgpack_pack.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index f463b3b..174a32d 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -91,7 +91,7 @@ inline static void msgpack_serialize_string( inline static void msgpack_serialize_class( smart_string *buf, zval *val, zval *retval_ptr, HashTable *var_hash, - char *class_name, zend_uint name_len, zend_bool incomplete_class TSRMLS_DC) + char *class_name, uint32_t name_len, zend_bool incomplete_class TSRMLS_DC) { int count; HashTable *ht = HASH_OF(retval_ptr); @@ -240,7 +240,7 @@ inline static void msgpack_serialize_class( inline static void msgpack_serialize_array( smart_string *buf, zval *val, HashTable *var_hash, zend_bool object, - char* class_name, zend_uint name_len, zend_bool incomplete_class TSRMLS_DC) + char* class_name, uint32_t name_len, zend_bool incomplete_class TSRMLS_DC) { HashTable *ht; size_t n; @@ -419,7 +419,7 @@ inline static void msgpack_serialize_array( inline static void msgpack_serialize_object( smart_string *buf, zval *val, HashTable *var_hash, - char* class_name, zend_uint name_len, zend_bool incomplete_class TSRMLS_DC) + char* class_name, uint32_t name_len, zend_bool incomplete_class TSRMLS_DC) { zval *retval_ptr = NULL; zval fname; @@ -435,7 +435,7 @@ inline static void msgpack_serialize_object( if (ce && ce->serialize != NULL) { unsigned char *serialized_data = NULL; - zend_uint serialized_length; + uint32_t serialized_length; if (ce->serialize( val, &serialized_data, &serialized_length, From 6f31cbafd8a529f9bd07aac0e3329fa8b8bb4bb5 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Tue, 7 Apr 2015 04:09:43 +0000 Subject: [PATCH 06/75] Update msgpack_serialize_zval. PHP_SET_CLASS_ATTRIBUTES now returns a zend_string instead of char* + len. IS_BOOL is not a distinct type anymore IS_TRUE/IS_FALSE instead --- msgpack_pack.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index 174a32d..c86516e 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -563,15 +563,11 @@ void msgpack_serialize_zval( case IS_NULL: msgpack_pack_nil(buf); break; - case IS_BOOL: - if (Z_BVAL_P(val)) - { - msgpack_pack_true(buf); - } - else - { - msgpack_pack_false(buf); - } + case IS_TRUE: + msgpack_pack_true(buf); + break; + case IS_FALSE: + msgpack_pack_false(buf); break; case IS_LONG: msgpack_pack_long(buf, Z_LVAL_P(val)); @@ -596,7 +592,7 @@ void msgpack_serialize_zval( PHP_SET_CLASS_ATTRIBUTES(val); msgpack_serialize_object( - buf, val, var_hash, class_name, name_len, + buf, val, var_hash, class_name->val, class_name->len, incomplete_class TSRMLS_CC); PHP_CLEANUP_CLASS_ATTRIBUTES(); From e75fe8af2ad790819833e26e8937489110151f55 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Tue, 7 Apr 2015 05:42:07 +0000 Subject: [PATCH 07/75] Update msgpack_serialize_object for new hashmap and zend_string API --- msgpack_pack.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index c86516e..730e2ae 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -425,8 +425,9 @@ inline static void msgpack_serialize_object( zval fname; int res; zend_class_entry *ce = NULL; + zend_string *sleep_zstring = zend_string_init("__sleep", sizeof("__sleep")-1, 0); - if (Z_OBJ_HT_P(val)->get_class_entry) + if (Z_OBJ_P(val)->ce) { ce = Z_OBJCE_P(val); } @@ -467,12 +468,11 @@ inline static void msgpack_serialize_object( #endif if (ce && ce != PHP_IC_ENTRY && - zend_hash_exists(&ce->function_table, "__sleep", sizeof("__sleep"))) + zend_hash_exists(&ce->function_table, sleep_zstring)) { - INIT_PZVAL(&fname); - ZVAL_STRINGL(&fname, "__sleep", sizeof("__sleep") - 1, 0); - res = call_user_function_ex(CG(function_table), &val, &fname, - &retval_ptr, 0, 0, 1, NULL TSRMLS_CC); + ZVAL_STR(&fname, sleep_zstring); + res = call_user_function_ex(CG(function_table), val, &fname, + retval_ptr, 0, 0, 1, NULL TSRMLS_CC); if (res == SUCCESS && !EG(exception)) { if (retval_ptr) @@ -491,7 +491,7 @@ inline static void msgpack_serialize_object( "to serialize", __FUNCTION__); msgpack_pack_nil(buf); } - zval_ptr_dtor(&retval_ptr); + zval_ptr_dtor(retval_ptr); } return; } @@ -499,7 +499,7 @@ inline static void msgpack_serialize_object( if (retval_ptr) { - zval_ptr_dtor(&retval_ptr); + zval_ptr_dtor(retval_ptr); } msgpack_serialize_array( From 83f6ec0101bd2dabe54fb90a09ffce9b5fbf6eb8 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Tue, 7 Apr 2015 06:53:30 +0000 Subject: [PATCH 08/75] Rough version of msgpack_serialize_array, use new hash iteration API --- msgpack_pack.c | 96 ++++++++++++++++++-------------------------------- 1 file changed, 35 insertions(+), 61 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index 730e2ae..57d55da 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -319,97 +319,71 @@ inline static void msgpack_serialize_array( { if (object || hash) { - char *key; - uint key_len; - int key_type; - ulong key_index; - zval **data; - HashPosition pos; - - zend_hash_internal_pointer_reset_ex(ht, &pos); - for (;; zend_hash_move_forward_ex(ht, &pos)) - { - key_type = zend_hash_get_current_key_ex( - ht, &key, &key_len, &key_index, 0, &pos); - if (key_type == HASH_KEY_NON_EXISTANT) - { - break; - } - if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) - { + zend_string *key_str; + ulong key_long; + zval *value; + + + ZEND_HASH_FOREACH_KEY_VAL(ht, key_long, key_str, value) { + if (key_str && incomplete_class && strcmp(key_str->val, MAGIC_MEMBER) == 0) { continue; } - - if (hash) - { - switch (key_type) - { - case HASH_KEY_IS_LONG: - msgpack_pack_long(buf, key_index); - break; - case HASH_KEY_IS_STRING: - msgpack_serialize_string(buf, key, key_len - 1); - break; - default: - msgpack_serialize_string(buf, "", sizeof("")); - MSGPACK_WARNING( - "[msgpack] (%s) key is not string nor array", - __FUNCTION__); - break; - } + if (key_str) { + msgpack_serialize_string(buf, key_str->val, key_str->len - 1); + } else if (key_long) { + msgpack_pack_long(buf, key_long); + } else { + msgpack_serialize_string(buf, "", sizeof("")); + MSGPACK_WARNING( + "[msgpack] (%s) key is not string nor array", + __FUNCTION__); } - if (zend_hash_get_current_data_ex( - ht, (void *)&data, &pos) != SUCCESS || - !data || data == &val || - (Z_TYPE_PP(data) == IS_ARRAY && - Z_ARRVAL_PP(data)->nApplyCount > 1)) - { + + if ((Z_TYPE_P(value) == IS_ARRAY && Z_ARRVAL_P(value)->u.v.nApplyCount > 1)) { msgpack_pack_nil(buf); - } - else - { - if (Z_TYPE_PP(data) == IS_ARRAY) + } else { + if (Z_TYPE_P(value) == IS_ARRAY) { - Z_ARRVAL_PP(data)->nApplyCount++; + Z_ARRVAL_P(value)->u.v.nApplyCount++; } - msgpack_serialize_zval(buf, *data, var_hash TSRMLS_CC); + msgpack_serialize_zval(buf, value, var_hash TSRMLS_CC); - if (Z_TYPE_PP(data) == IS_ARRAY) + if (Z_TYPE_P(value) == IS_ARRAY) { - Z_ARRVAL_PP(data)->nApplyCount--; + Z_ARRVAL_P(value)->u.v.nApplyCount--; } } - } + } ZEND_HASH_FOREACH_END(); } else { - zval **data; + zval *data; uint i; for (i = 0; i < n; i++) { - if (zend_hash_index_find(ht, i, (void *)&data) != SUCCESS || - !data || data == &val || - (Z_TYPE_PP(data) == IS_ARRAY && - Z_ARRVAL_PP(data)->nApplyCount > 1)) + if ((data = zend_hash_index_find(ht, i)) == NULL || + !data || &data == &val || + (Z_TYPE_P(data) == IS_ARRAY && + Z_ARRVAL_P(data)->u.v.nApplyCount > 1)) { msgpack_pack_nil(buf); } else { - if (Z_TYPE_PP(data) == IS_ARRAY) + if (Z_TYPE_P(data) == IS_ARRAY) { - Z_ARRVAL_PP(data)->nApplyCount++; + Z_ARRVAL_P(data)->u.v.nApplyCount++; } - msgpack_serialize_zval(buf, *data, var_hash TSRMLS_CC); + msgpack_serialize_zval(buf, data, var_hash TSRMLS_CC); - if (Z_TYPE_PP(data) == IS_ARRAY) + if (Z_TYPE_P(data) == IS_ARRAY) { - Z_ARRVAL_PP(data)->nApplyCount--; + Z_ARRVAL_P(data)->u.v.nApplyCount--; } } } From 8793909c25ddd95e437744545684d42ebfdeadad Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Fri, 10 Apr 2015 06:22:00 +0000 Subject: [PATCH 09/75] Refactor msgpack_serialize_class to use new hash API and one level less of zval indirection --- msgpack_pack.c | 133 ++++++++++++++----------------------------------- 1 file changed, 38 insertions(+), 95 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index 57d55da..63cfbde 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -104,137 +104,80 @@ inline static void msgpack_serialize_class( if (count > 0) { - char *key; - zval **data, **name; - ulong key_index; - HashPosition pos; - int n; - zval nval, *nvalp; - msgpack_pack_map(buf, count + 1); - msgpack_pack_nil(buf); msgpack_serialize_string(buf, class_name, name_len); - INIT_ZVAL(nval); + zend_string *key_str; + ulong key_long; + zval *value, *data, nval, *nvalp; ZVAL_NULL(&nval); nvalp = &nval; - zend_hash_internal_pointer_reset_ex(ht, &pos); - - for (;; zend_hash_move_forward_ex(ht, &pos)) - { - n = zend_hash_get_current_key_ex( - ht, &key, NULL, &key_index, 0, &pos); - - if (n == HASH_KEY_NON_EXISTANT) - { + ZEND_HASH_FOREACH_KEY_VAL(ht, key_long, key_str, value) { + if (!key_long && !key_str) { break; } - if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) - { + if (incomplete_class && strcmp(key_str->val, MAGIC_MEMBER) == 0) { continue; } - zend_hash_get_current_data_ex(ht, (void **)&name, &pos); - - if (Z_TYPE_PP(name) != IS_STRING) - { + if (Z_TYPE_P(value) != IS_STRING) { MSGPACK_NOTICE( - "[msgpack] (%s) __sleep should return an array only " - "containing the names of instance-variables to serialize", - __FUNCTION__); + "[msgpack] (%s) __sleep should return an array only " + "containing the names of instance-variables to serialize", + __FUNCTION__); continue; } - - if (zend_hash_find( - Z_OBJPROP_P(val), Z_STRVAL_PP(name), - Z_STRLEN_PP(name) + 1, (void *)&data) == SUCCESS) - { - msgpack_serialize_string( - buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name)); - msgpack_serialize_zval(buf, *data, var_hash TSRMLS_CC); - } - else - { - zend_class_entry *ce; - ce = zend_get_class_entry(val TSRMLS_CC); + if ((data = zend_hash_find(Z_OBJPROP_P(val), key_str)) != NULL) { + msgpack_serialize_string(buf, key_str->val, key_str->len); + msgpack_serialize_zval(buf, data, var_hash TSRMLS_CC); + } else { + zend_class_entry *ce = Z_OBJ_P(val)->ce; if (ce) { - char *prot_name, *priv_name; - int prop_name_length; - + zend_string *priv_name, *prot_name; do { - zend_mangle_property_name( - &priv_name, &prop_name_length, ce->name, - ce->name_length, Z_STRVAL_PP(name), - Z_STRLEN_PP(name), - ce->type & ZEND_INTERNAL_CLASS); - if (zend_hash_find( - Z_OBJPROP_P(val), priv_name, - prop_name_length + 1, - (void *)&data) == SUCCESS) - { - msgpack_serialize_string( - buf, priv_name, prop_name_length); - - pefree(priv_name, - ce->type & ZEND_INTERNAL_CLASS); - - msgpack_serialize_zval( - buf, *data, var_hash TSRMLS_CC); + priv_name = zend_mangle_property_name(ce->name->val, ce->name->len, + key_str->val, key_str->len, + ce->type & ZEND_INTERNAL_CLASS); + if ((data = zend_hash_find(Z_OBJPROP_P(val), priv_name)) != NULL) { + msgpack_serialize_string(buf, priv_name->val, priv_name->len); + pefree(priv_name, ce->type & ZEND_INTERNAL_CLASS); + msgpack_serialize_zval(buf, data, var_hash TSRMLS_CC); break; } - pefree(priv_name, - ce->type & ZEND_INTERNAL_CLASS); + pefree(priv_name, ce->type & ZEND_INTERNAL_CLASS); - zend_mangle_property_name( - &prot_name, &prop_name_length, "*", 1, - Z_STRVAL_PP(name), Z_STRLEN_PP(name), - ce->type & ZEND_INTERNAL_CLASS); + prot_name = zend_mangle_property_name("*", 1, + key_str->val, key_str->len, + ce->type & ZEND_INTERNAL_CLASS); - if (zend_hash_find( - Z_OBJPROP_P(val), prot_name, - prop_name_length + 1, - (void *)&data) == SUCCESS) - { - msgpack_serialize_string( - buf, prot_name, prop_name_length); - - pefree(prot_name, - ce->type & ZEND_INTERNAL_CLASS); - - msgpack_serialize_zval( - buf, *data, var_hash TSRMLS_CC); + if ((data = zend_hash_find(Z_OBJPROP_P(val), prot_name)) != NULL) { + msgpack_serialize_string(buf, prot_name->val, prot_name->len); + pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS); + msgpack_serialize_zval(buf, data, var_hash TSRMLS_CC); break; } - pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS); MSGPACK_NOTICE( "[msgpack] (%s) \"%s\" returned as member " "variable from __sleep() but does not exist", - __FUNCTION__, Z_STRVAL_PP(name)); - - msgpack_serialize_string( - buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name)); - - msgpack_serialize_zval( - buf, nvalp, var_hash TSRMLS_CC); - } - while (0); + __FUNCTION__, key_str->val); + msgpack_serialize_string(buf, key_str->val, key_str->len); + msgpack_serialize_zval(buf, nvalp, var_hash TSRMLS_CC); + } while (0); } else { - msgpack_serialize_string( - buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name)); - + msgpack_serialize_string(buf, key_str->val, key_str->len); msgpack_serialize_zval(buf, nvalp, var_hash TSRMLS_CC); - } + } } - } + } ZEND_HASH_FOREACH_END(); } } From fbc4e8ea0618b22866785a9904b0e8c4bd72e395 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sat, 11 Apr 2015 03:10:32 +0000 Subject: [PATCH 10/75] Refactor msgpack_unserialize_class to drop one level of zval deference, and zend_string instead of char+int for zend_lookup_class --- msgpack_unpack.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 3bf2ac9..c397476 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -198,13 +198,13 @@ inline static zend_class_entry* msgpack_unserialize_class( { zend_class_entry *ce, **pce; zend_bool incomplete_class = 0; - zval *user_func, *retval_ptr, **args[1], *arg_func_name; + zval *user_func, *retval_ptr, args[1], *arg_func_name; TSRMLS_FETCH(); do { /* Try to find class directly */ - if (zend_lookup_class(class_name, name_len, &pce TSRMLS_CC) == SUCCESS) + if ((*pce = zend_lookup_class(zend_string_init(class_name, name_len, 0))) != NULL) { ce = *pce; break; @@ -220,31 +220,27 @@ inline static zend_class_entry* msgpack_unserialize_class( } /* 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) + ZVAL_STRING(user_func, PG(unserialize_callback_func)); + args[0] = *arg_func_name; + ZVAL_STRING(arg_func_name, class_name); + if (call_user_function_ex(CG(function_table), NULL, user_func, retval_ptr, 1, args, 0, NULL TSRMLS_CC) != SUCCESS) { MSGPACK_WARNING("[msgpack] (%s) defined (%s) but not found", __FUNCTION__, class_name); incomplete_class = 1; ce = PHP_IC_ENTRY; - zval_ptr_dtor(&user_func); - zval_ptr_dtor(&arg_func_name); + zval_ptr_dtor(user_func); + zval_ptr_dtor(arg_func_name); break; } if (retval_ptr) { - zval_ptr_dtor(&retval_ptr); + zval_ptr_dtor(retval_ptr); } /* The callback function may have defined the class */ - if (zend_lookup_class(class_name, name_len, &pce TSRMLS_CC) == SUCCESS) + if ((*pce = zend_lookup_class(zend_string_init(class_name, name_len, 0))) != NULL) { ce = *pce; } @@ -258,8 +254,8 @@ inline static zend_class_entry* msgpack_unserialize_class( ce = PHP_IC_ENTRY; } - zval_ptr_dtor(&user_func); - zval_ptr_dtor(&arg_func_name); + zval_ptr_dtor(user_func); + zval_ptr_dtor(arg_func_name); } while(0); From 4f1e6e75a629e53942301a58ff6d03fa677e7d31 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sat, 11 Apr 2015 03:45:55 +0000 Subject: [PATCH 11/75] Remove unused macros from msgpack_unpack.c, update msgpack_var_push and msgpack_unserialize_raw to have one level less of dereference --- msgpack_unpack.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index c397476..5b7cfe7 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -8,12 +8,6 @@ #include "msgpack_unpack.h" #include "msgpack_errors.h" -#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 @@ -49,8 +43,8 @@ typedef struct } #define MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(_unpack, _key, _val) \ - zval_ptr_dtor(&_key); \ - zval_ptr_dtor(&_val); \ + zval_ptr_dtor(_key); \ + zval_ptr_dtor(_val); \ MSGPACK_UNSERIALIZE_FINISH_ITEM(_unpack, 2); inline static void msgpack_var_push( @@ -343,7 +337,7 @@ void msgpack_unserialize_var_destroy( { if (var_hash->data[i]) { - zval_ptr_dtor(&var_hash->data[i]); + zval_ptr_dtor(var_hash->data[i]); var_hash->data[i] = NULL; } } @@ -495,11 +489,11 @@ int msgpack_unserialize_raw( if (len == 0) { - ZVAL_STRINGL(*obj, "", 0, 1); + ZVAL_STRINGL(*obj, "", 0); } else { - ZVAL_STRINGL(*obj, (char *)data, len, 1); + ZVAL_STRINGL(*obj, (char *)data, len); } return 0; @@ -570,7 +564,7 @@ int msgpack_unserialize_map_item( switch (Z_LVAL_P(val)) { case MSGPACK_SERIALIZE_TYPE_REFERENCE: - Z_SET_ISREF_PP(container); + ZVAL_MAKE_REF(*container); break; case MSGPACK_SERIALIZE_TYPE_RECURSIVE: unpack->type = MSGPACK_SERIALIZE_TYPE_RECURSIVE; From 8814fdd4742b358c596121822e8cf485922d6831 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sat, 11 Apr 2015 08:21:59 +0000 Subject: [PATCH 12/75] Update msgpack_unserialize_map_item to handle zend_string inputs and macro removal PHP 5 -> 7 --- msgpack_unpack.c | 71 ++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 42 deletions(-) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 5b7cfe7..db2192a 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -22,7 +22,6 @@ typedef struct *obj = _unpack->retval; \ msgpack_stack_push(_unpack->var_hash, obj, 0); \ } else { \ - ALLOC_INIT_ZVAL(*obj); \ msgpack_stack_push(_unpack->var_hash, obj, 1); \ } @@ -31,7 +30,6 @@ typedef struct *obj = _unpack->retval; \ msgpack_var_push(_unpack->var_hash, obj); \ } else { \ - ALLOC_INIT_ZVAL(*obj); \ msgpack_var_push(_unpack->var_hash, obj); \ } @@ -660,20 +658,20 @@ int msgpack_unserialize_map_item( if (container != NULL) { - zval_ptr_dtor(container); + zval_ptr_dtor(*container); } *container = *rval; - Z_ADDREF_PP(container); + Z_TRY_ADDREF_P(*container); - if (type == MSGPACK_SERIALIZE_TYPE_OBJECT) + if (type == MSGPACK_SERIALIZE_TYPE_OBJECT && Z_ISREF_P(*container)) { - Z_UNSET_ISREF_PP(container); + ZVAL_UNREF(*container); } - else if (type == MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE) + else if (type == MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE && Z_ISREF_P(*container)) { - Z_SET_ISREF_PP(container); + ZVAL_UNREF(*container); } MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); @@ -684,7 +682,7 @@ int msgpack_unserialize_map_item( } } - if (Z_TYPE_PP(container) != IS_ARRAY && Z_TYPE_PP(container) != IS_OBJECT) + if (Z_TYPE_P(*container) != IS_ARRAY && Z_TYPE_P(*container) != IS_OBJECT) { array_init(*container); } @@ -692,56 +690,48 @@ int msgpack_unserialize_map_item( switch (Z_TYPE_P(key)) { case IS_LONG: - if (zend_hash_index_update( - HASH_OF(*container), Z_LVAL_P(key), &val, - sizeof(val), NULL) == FAILURE) + if ((val = zend_hash_index_update(HASH_OF(*container), Z_LVAL_P(key), val)) != NULL) { - zval_ptr_dtor(&val); + zval_ptr_dtor(val); MSGPACK_WARNING( "[msgpack] (%s) illegal offset type, skip this decoding", __FUNCTION__); } - zval_ptr_dtor(&key); + zval_ptr_dtor(key); 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) + + if ((val = zend_symtable_update(HASH_OF(*container), zend_string_init(Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, 0), val)) != NULL) { - zval_ptr_dtor(&val); + zval_ptr_dtor(val); MSGPACK_WARNING( "[msgpack] (%s) illegal offset type, skip this decoding", __FUNCTION__); } - zval_ptr_dtor(&key); + zval_ptr_dtor(key); break; default: MSGPACK_WARNING("[msgpack] (%s) illegal key type", __FUNCTION__); if (MSGPACK_G(illegal_key_insert)) { - if (zend_hash_next_index_insert( - HASH_OF(*container), &key, sizeof(key), NULL) == FAILURE) + if ((key = zend_hash_next_index_insert(HASH_OF(*container), key)) != NULL) { - zval_ptr_dtor(&val); + zval_ptr_dtor(val); } - if (zend_hash_next_index_insert( - HASH_OF(*container), &val, sizeof(val), NULL) == FAILURE) + if ((val = zend_hash_next_index_insert(HASH_OF(*container), val)) != NULL) { - zval_ptr_dtor(&val); + zval_ptr_dtor(val); } } else { convert_to_string(key); - if (zend_symtable_update( - HASH_OF(*container), - Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, - &val, sizeof(val), NULL) == FAILURE) + if ((zend_symtable_update(HASH_OF(*container), zend_string_init(Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, 0), val)) != NULL) { - zval_ptr_dtor(&val); + zval_ptr_dtor(val); } - zval_ptr_dtor(&key); + zval_ptr_dtor(key); } break; } @@ -756,21 +746,18 @@ int msgpack_unserialize_map_item( /* 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"))) + Z_TYPE_P(*container) == IS_OBJECT && + Z_OBJCE_P(*container) != PHP_IC_ENTRY && + + zend_hash_exists(&Z_OBJ_P(*container)->ce->function_table, zend_string_init("__wakeup", sizeof("__wakeup") + 1, 1))) { - zval f, *h = NULL; + 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); + ZVAL_STRINGL(f, "__wakeup", sizeof("__wakeup") - 1); + call_user_function_ex( CG(function_table), *container, f, h, 0, 0, 1, NULL TSRMLS_CC); if (h) { - zval_ptr_dtor(&h); + zval_ptr_dtor(h); } } } From 41800b5d603087ceddc85faea0c00535f27ccffb Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sat, 11 Apr 2015 09:04:10 +0000 Subject: [PATCH 13/75] Replace MSGPACK_UNPACKER_OBJECT and MSGPACK_BASE_OBJECT macros with msgpack_unpacker_fetch_object and msgpack_base_fetch_object --- msgpack_class.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/msgpack_class.c b/msgpack_class.c index 7f2ea33..38f48fd 100644 --- a/msgpack_class.c +++ b/msgpack_class.c @@ -65,13 +65,15 @@ typedef struct { #define MSGPACK_METHOD1(classname, name, retval, thisptr, param1) \ MSGPACK_METHOD_HELPER(classname, name, retval, thisptr, 1, param1); -#define MSGPACK_BASE_OBJECT \ - php_msgpack_base_t *base; \ - base = (php_msgpack_base_t *)zend_object_store_get_object(getThis() TSRMLS_CC); +static inline php_msgpack_base_t *msgpack_base_fetch_object(zend_object *obj) { + return (php_msgpack_base_t *)((char*)(obj) - XtOffsetOf(php_msgpack_base_t, object)); +} +#define Z_MSGPACK_BASE_P(zv) msgpack_base_fetch_object(Z_OBJ_P((zv))) -#define MSGPACK_UNPACKER_OBJECT \ - php_msgpack_unpacker_t *unpacker; \ - unpacker = (php_msgpack_unpacker_t *)zend_object_store_get_object(getThis() TSRMLS_CC); +static inline php_msgpack_unpacker_t *msgpack_unpacker_fetch_object(zend_object *obj) { + return (php_msgpack_unpacker_t *)((char*)(obj) - XtOffsetOf(php_msgpack_unpacker_t, object)); +} +#define Z_MSGPACK_UNPACKER_P(zv) msgpack_unpacker_fetch_object(Z_OBJ_P((zv))) /* MessagePack */ static zend_class_entry *msgpack_ce = NULL; @@ -274,7 +276,7 @@ static zend_object_value php_msgpack_unpacker_new( static ZEND_METHOD(msgpack, __construct) { zend_bool php_only = MSGPACK_G(php_only); - MSGPACK_BASE_OBJECT; + php_msgpack_base_t *base = Z_MSGPACK_BASE_P(getThis()); if (zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "|b", &php_only) == FAILURE) @@ -289,7 +291,7 @@ static ZEND_METHOD(msgpack, setOption) { long option; zval *value; - MSGPACK_BASE_OBJECT; + php_msgpack_base_t *base = Z_MSGPACK_BASE_P(getThis()); if (zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "lz", &option, &value) == FAILURE) @@ -318,7 +320,7 @@ static ZEND_METHOD(msgpack, pack) zval *parameter; smart_string buf = {0}; int php_only = MSGPACK_G(php_only); - MSGPACK_BASE_OBJECT; + php_msgpack_base_t *base = Z_MSGPACK_BASE_P(getThis()); if (zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶meter) == FAILURE) @@ -343,7 +345,7 @@ static ZEND_METHOD(msgpack, unpack) int str_len; zval *object = NULL; int php_only = MSGPACK_G(php_only); - MSGPACK_BASE_OBJECT; + php_msgpack_base_t *base = Z_MSGPACK_BASE_P(getThis()); if (zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s|z", @@ -382,7 +384,7 @@ static ZEND_METHOD(msgpack, unpack) static ZEND_METHOD(msgpack, unpacker) { zval temp, *opt; - MSGPACK_BASE_OBJECT; + php_msgpack_base_t *base = Z_MSGPACK_BASE_P(getThis()); ALLOC_INIT_ZVAL(opt); ZVAL_BOOL(opt, base->php_only); @@ -398,7 +400,7 @@ static ZEND_METHOD(msgpack, unpacker) static ZEND_METHOD(msgpack_unpacker, __construct) { zend_bool php_only = MSGPACK_G(php_only); - MSGPACK_UNPACKER_OBJECT; + php_msgpack_unpacker_t *unpacker = Z_MSGPACK_UNPACKER_P(getThis()); if (zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "|b", &php_only) == FAILURE) @@ -426,7 +428,7 @@ static ZEND_METHOD(msgpack_unpacker, __construct) static ZEND_METHOD(msgpack_unpacker, __destruct) { - MSGPACK_UNPACKER_OBJECT; + php_msgpack_unpacker_t *unpacker = Z_MSGPACK_UNPACKER_P(getThis()); smart_string_free(&unpacker->buffer); @@ -442,7 +444,8 @@ static ZEND_METHOD(msgpack_unpacker, setOption) { long option; zval *value; - MSGPACK_UNPACKER_OBJECT; + php_msgpack_unpacker_t *unpacker = Z_MSGPACK_UNPACKER_P(getThis()); + if (zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "lz", &option, &value) == FAILURE) @@ -470,7 +473,7 @@ static ZEND_METHOD(msgpack_unpacker, feed) { char *str; int str_len; - MSGPACK_UNPACKER_OBJECT; + php_msgpack_unpacker_t *unpacker = Z_MSGPACK_UNPACKER_P(getThis()); if (zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) @@ -497,7 +500,7 @@ static ZEND_METHOD(msgpack_unpacker, execute) size_t len, off; int error_display = MSGPACK_G(error_display); int php_only = MSGPACK_G(php_only); - MSGPACK_UNPACKER_OBJECT; + php_msgpack_unpacker_t *unpacker = Z_MSGPACK_UNPACKER_P(getThis()); if (zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "|sz/", @@ -584,7 +587,7 @@ static ZEND_METHOD(msgpack_unpacker, execute) static ZEND_METHOD(msgpack_unpacker, data) { zval *object = NULL; - MSGPACK_UNPACKER_OBJECT; + php_msgpack_unpacker_t *unpacker = Z_MSGPACK_UNPACKER_P(getThis()); if (zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "|z", &object) == FAILURE) @@ -622,7 +625,7 @@ static ZEND_METHOD(msgpack_unpacker, data) static ZEND_METHOD(msgpack_unpacker, reset) { smart_string buffer = {0}; - MSGPACK_UNPACKER_OBJECT; + php_msgpack_unpacker_t *unpacker = Z_MSGPACK_UNPACKER_P(getThis()); if (unpacker->buffer.len > unpacker->offset) { From 51f764284dac645aabfac0684cb726e2400dcdf2 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sun, 12 Apr 2015 04:36:00 +0000 Subject: [PATCH 14/75] Update php_msgpack_base_t and php_msgpack_unpacker_t to use the new custom object API --- msgpack_class.c | 114 +++++++++++------------------------------------- 1 file changed, 25 insertions(+), 89 deletions(-) diff --git a/msgpack_class.c b/msgpack_class.c index 38f48fd..2209bb4 100644 --- a/msgpack_class.c +++ b/msgpack_class.c @@ -77,6 +77,7 @@ static inline php_msgpack_unpacker_t *msgpack_unpacker_fetch_object(zend_object /* MessagePack */ static zend_class_entry *msgpack_ce = NULL; +zend_object_handlers msgpack_handlers; static ZEND_METHOD(msgpack, __construct); static ZEND_METHOD(msgpack, setOption); @@ -117,6 +118,7 @@ static zend_function_entry msgpack_base_methods[] = { /* MessagePackUnpacker */ static zend_class_entry *msgpack_unpacker_ce = NULL; +zend_object_handlers msgpack_unpacker_handlers; static ZEND_METHOD(msgpack_unpacker, __construct); static ZEND_METHOD(msgpack_unpacker, __destruct); @@ -171,106 +173,40 @@ static zend_function_entry msgpack_unpacker_methods[] = { arginfo_msgpack_unpacker_reset, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; - +zend_object *php_msgpack_base_new(zend_class_entry *ce TSRMLS_DC) { + php_msgpack_base_t *intern = ecalloc(1, + sizeof(php_msgpack_base_t) + + zend_object_properties_size(ce)); + + zend_object_std_init(&intern->object, ce TSRMLS_CC); + object_properties_init(&intern->object, ce); + intern->object.handlers = &msgpack_handlers; + return &intern->object; +} static void php_msgpack_base_free(php_msgpack_base_t *base TSRMLS_DC) { -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0) zend_object_std_dtor(&base->object TSRMLS_CC); -#else - if (base->object.properties) - { - zend_hash_destroy(base->object.properties); - FREE_HASHTABLE(base->object.properties); - } -#endif efree(base); } -static zend_object_value php_msgpack_base_new(zend_class_entry *ce TSRMLS_DC) -{ - zend_object_value retval; - php_msgpack_base_t *base; -#if PHP_API_VERSION < 20100412 - zval *tmp; -#endif - - base = emalloc(sizeof(php_msgpack_base_t)); +zend_object *php_msgpack_unpacker_new(zend_class_entry *ce TSRMLS_DC) { + php_msgpack_unpacker_t *intern = ecalloc(1, + sizeof(php_msgpack_unpacker_t) + + zend_object_properties_size(ce)); -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0) - zend_object_std_init(&base->object, ce TSRMLS_CC); -#else - ALLOC_HASHTABLE(base->object.properties); - zend_hash_init(base->object.properties, 0, NULL, ZVAL_PTR_DTOR, 0); - base->object.ce = ce; -#endif - -#if PHP_API_VERSION < 20100412 - zend_hash_copy( - base->object.properties, &ce->default_properties, - (copy_ctor_func_t)zval_add_ref, (void *)&tmp, sizeof(zval *)); -#else - object_properties_init(&base->object, ce); -#endif - - retval.handle = zend_objects_store_put( - base, (zend_objects_store_dtor_t)zend_objects_destroy_object, - (zend_objects_free_object_storage_t)php_msgpack_base_free, - NULL TSRMLS_CC); - retval.handlers = zend_get_std_object_handlers(); - - return retval; + zend_object_std_init(&intern->object, ce TSRMLS_CC); + object_properties_init(&intern->object, ce); + intern->object.handlers = &msgpack_unpacker_handlers; + return &intern->object; } static void php_msgpack_unpacker_free( php_msgpack_unpacker_t *unpacker TSRMLS_DC) { -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0) zend_object_std_dtor(&unpacker->object TSRMLS_CC); -#else - if (unpacker->object.properties) - { - zend_hash_destroy(unpacker->object.properties); - FREE_HASHTABLE(unpacker->object.properties); - } -#endif efree(unpacker); } -static zend_object_value php_msgpack_unpacker_new( - zend_class_entry *ce TSRMLS_DC) -{ - zend_object_value retval; - php_msgpack_unpacker_t *unpacker; -#if PHP_API_VERSION < 20100412 - zval *tmp; -#endif - - unpacker = emalloc(sizeof(php_msgpack_unpacker_t)); - -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0) - zend_object_std_init(&unpacker->object, ce TSRMLS_CC); -#else - ALLOC_HASHTABLE(unpacker->object.properties); - zend_hash_init(unpacker->object.properties, 0, NULL, ZVAL_PTR_DTOR, 0); - unpacker->object.ce = ce; -#endif - -#if PHP_API_VERSION < 20100412 - zend_hash_copy( - unpacker->object.properties, &ce->default_properties, - (copy_ctor_func_t)zval_add_ref, (void *)&tmp, sizeof(zval *)); -#else - object_properties_init(&unpacker->object, ce); -#endif - - retval.handle = zend_objects_store_put( - unpacker, (zend_objects_store_dtor_t)zend_objects_destroy_object, - (zend_objects_free_object_storage_t)php_msgpack_unpacker_free, - NULL TSRMLS_CC); - retval.handlers = zend_get_std_object_handlers(); - - return retval; -} /* MessagePack */ static ZEND_METHOD(msgpack, __construct) @@ -675,15 +611,15 @@ void msgpack_init_class() INIT_CLASS_ENTRY(ce, "MessagePack", msgpack_base_methods); msgpack_ce = zend_register_internal_class(&ce TSRMLS_CC); msgpack_ce->create_object = php_msgpack_base_new; + memcpy(&msgpack_handlers, zend_get_std_object_handlers(),sizeof msgpack_handlers); + msgpack_handlers.offset = XtOffsetOf(php_msgpack_base_t, object); -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0) - zend_declare_class_constant_long( - msgpack_ce, ZEND_STRS("OPT_PHPONLY") - 1, - MSGPACK_CLASS_OPT_PHPONLY TSRMLS_CC); -#endif + zend_declare_class_constant_long(msgpack_ce, ZEND_STRS("OPT_PHPONLY") - 1, MSGPACK_CLASS_OPT_PHPONLY TSRMLS_CC); /* unpacker */ INIT_CLASS_ENTRY(ce, "MessagePackUnpacker", msgpack_unpacker_methods); msgpack_unpacker_ce = zend_register_internal_class(&ce TSRMLS_CC); msgpack_unpacker_ce->create_object = php_msgpack_unpacker_new; + memcpy(&msgpack_unpacker_handlers, zend_get_std_object_handlers(),sizeof msgpack_unpacker_handlers); + msgpack_unpacker_handlers.offset = XtOffsetOf(php_msgpack_unpacker_t, object); } From 01d65191c3c34842074e704f787209ef68cd3d09 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sun, 12 Apr 2015 06:37:04 +0000 Subject: [PATCH 15/75] Cleanup last zval deref changes in msgpack_class.c --- msgpack_class.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/msgpack_class.c b/msgpack_class.c index 2209bb4..268a2db 100644 --- a/msgpack_class.c +++ b/msgpack_class.c @@ -239,7 +239,7 @@ static ZEND_METHOD(msgpack, setOption) { case MSGPACK_CLASS_OPT_PHPONLY: convert_to_boolean(value); - base->php_only = Z_BVAL_P(value); + base->php_only = Z_LVAL_P(value); break; default: MSGPACK_WARNING("[msgpack] (MessagePack::setOption) " @@ -270,7 +270,7 @@ static ZEND_METHOD(msgpack, pack) MSGPACK_G(php_only) = php_only; - ZVAL_STRINGL(return_value, buf.c, buf.len, 1); + ZVAL_STRINGL(return_value, buf.c, buf.len); smart_string_free(&buf); } @@ -305,7 +305,6 @@ static ZEND_METHOD(msgpack, unpack) { zval *zv; - ALLOC_INIT_ZVAL(zv); php_msgpack_unserialize(zv, str, str_len TSRMLS_CC); if (msgpack_convert_template(return_value, object, &zv) != SUCCESS) @@ -322,14 +321,13 @@ static ZEND_METHOD(msgpack, unpacker) zval temp, *opt; php_msgpack_base_t *base = Z_MSGPACK_BASE_P(getThis()); - ALLOC_INIT_ZVAL(opt); ZVAL_BOOL(opt, base->php_only); object_init_ex(return_value, msgpack_unpacker_ce); MSGPACK_METHOD1(msgpack_unpacker, __construct, &temp, return_value, opt); - zval_ptr_dtor(&opt); + zval_ptr_dtor(opt); } /* MessagePackUnpacker */ @@ -370,7 +368,7 @@ static ZEND_METHOD(msgpack_unpacker, __destruct) if (unpacker->retval != NULL) { - zval_ptr_dtor(&unpacker->retval); + zval_ptr_dtor(unpacker->retval); } msgpack_unserialize_var_destroy(&unpacker->var_hash, unpacker->error); @@ -393,7 +391,7 @@ static ZEND_METHOD(msgpack_unpacker, setOption) { case MSGPACK_CLASS_OPT_PHPONLY: convert_to_boolean(value); - unpacker->php_only = Z_BVAL_P(value); + unpacker->php_only = Z_LVAL_P(value); break; default: MSGPACK_WARNING("[msgpack] (MessagePackUnpacker::setOption) " @@ -467,16 +465,18 @@ static ZEND_METHOD(msgpack_unpacker, execute) if (unpacker->retval == NULL) { - ALLOC_INIT_ZVAL(unpacker->retval); + zval zv; + unpacker->retval = &zv; } else if (unpacker->finished) { - zval_ptr_dtor(&unpacker->retval); + zval_ptr_dtor(unpacker->retval); msgpack_unserialize_var_destroy(&unpacker->var_hash, unpacker->error); unpacker->error = 0; - ALLOC_INIT_ZVAL(unpacker->retval); + zval zv; + unpacker->retval = &zv; template_init(&unpacker->mp); @@ -541,7 +541,6 @@ static ZEND_METHOD(msgpack_unpacker, data) { zval *zv; - ALLOC_INIT_ZVAL(zv); ZVAL_ZVAL(zv, unpacker->retval, 1, 0); if (msgpack_convert_object(return_value, object, &zv) != SUCCESS) @@ -586,7 +585,7 @@ static ZEND_METHOD(msgpack_unpacker, reset) if (unpacker->retval != NULL) { - zval_ptr_dtor(&unpacker->retval); + zval_ptr_dtor(unpacker->retval); unpacker->retval = NULL; } From 8e8e23c326ee1e69d6dd174847eefe7f9d4484a5 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Mon, 13 Apr 2015 02:34:14 +0000 Subject: [PATCH 16/75] Update msgpack_convert_long_to_properties to new hash table iteration API --- msgpack_convert.c | 110 ++++++++++++++-------------------------------- 1 file changed, 33 insertions(+), 77 deletions(-) diff --git a/msgpack_convert.c b/msgpack_convert.c index 4f426d3..56a3b91 100644 --- a/msgpack_convert.c +++ b/msgpack_convert.c @@ -34,7 +34,7 @@ return SUCCESS; \ } -static inline int msgpack_convert_long_to_properties( +static inline int msgpack_convert_long_to_properties( HashTable *ht, HashTable **properties, HashPosition *prop_pos, uint key_index, zval *val, HashTable *var) { @@ -42,95 +42,51 @@ static inline int msgpack_convert_long_to_properties( if (*properties != NULL) { - char *prop_key; - uint prop_key_len; - ulong prop_key_index; - zval **data = NULL; - zval *tplval = NULL; - zval **dataval = NULL; - - for (;; zend_hash_move_forward_ex(*properties, prop_pos)) - { - if (zend_hash_get_current_key_ex( - *properties, &prop_key, &prop_key_len, - &prop_key_index, 0, prop_pos) == HASH_KEY_IS_STRING) - { - if (var == NULL || - !zend_hash_exists(var, prop_key, prop_key_len)) + zend_string *key_str; + ulong key_long; + zval *data; + + //non-iteration + zval *dataval = NULL, *tplval = NULL; + + ZEND_HASH_FOREACH_KEY_VAL(ht, key_long, key_str, data) { + if(key_str) { + switch (Z_TYPE_P(data)) { - if (zend_hash_find( - ht, prop_key, prop_key_len, - (void **)&data) == SUCCESS) - { - switch (Z_TYPE_PP(data)) + case IS_ARRAY: { - case IS_ARRAY: - { - HashTable *dataht; - dataht = HASH_OF(val); - if (zend_hash_index_find( - dataht, prop_key_index, - (void **)dataval) != SUCCESS) - { - MSGPACK_WARNING( + HashTable *dataht; + dataht = HASH_OF(val); + if ((dataval = zend_hash_index_find(dataht, key_long)) != NULL) { + MSGPACK_WARNING( "[msgpack] (%s) " "can't get data value by index", __FUNCTION__); - return FAILURE; - } - - ALLOC_INIT_ZVAL(tplval); - if (msgpack_convert_array( - tplval, *data, dataval) == SUCCESS) - { - zend_hash_move_forward_ex( - *properties, prop_pos); - - return zend_symtable_update( - ht, prop_key, prop_key_len, - &tplval, sizeof(tplval), NULL); - } - // TODO: de we need to call dtor? return FAILURE; - break; } - case IS_OBJECT: - { - ALLOC_INIT_ZVAL(tplval); - if (msgpack_convert_object( - tplval, *data, &val) == SUCCESS) - { - zend_hash_move_forward_ex( - *properties, prop_pos); - - return zend_symtable_update( - ht, prop_key, prop_key_len, - &tplval, sizeof(tplval), NULL); - } - // TODO: de we need to call dtor? - return FAILURE; - break; + + if (msgpack_convert_array(tplval, data, &dataval) == SUCCESS) { + return (zend_symtable_update(ht, key_str, tplval) != NULL); } - default: - zend_hash_move_forward_ex(*properties, prop_pos); - return zend_symtable_update( - ht, prop_key, prop_key_len, - &val, sizeof(val), NULL); - break; + // TODO: de we need to call dtor? + return FAILURE; } - } + case IS_OBJECT: + { + if (msgpack_convert_object(tplval, data, &val) == SUCCESS) { + return (zend_symtable_update(ht, key_str, tplval) != NULL); + } + // TODO: de we need to call dtor? + return FAILURE; + } + default: + return (zend_symtable_update(ht, key_str, tplval) != NULL); } } - else - { - break; - } - } - + } ZEND_HASH_FOREACH_END(); *properties = NULL; } - - return zend_hash_index_update(ht, key_index, &val, sizeof(val), NULL); + return (zend_hash_index_update(ht, key_index, val) != NULL); } static inline int msgpack_convert_string_to_properties( From 67deff3a856695b71f5503b62d9728fa7eb50406 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Mon, 13 Apr 2015 04:31:02 +0000 Subject: [PATCH 17/75] Update msgpack_convert_string_to_properties to use new zend_string API --- msgpack_convert.c | 45 +++++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/msgpack_convert.c b/msgpack_convert.c index 56a3b91..02066ca 100644 --- a/msgpack_convert.c +++ b/msgpack_convert.c @@ -27,11 +27,10 @@ INIT_PZVAL(_pz); \ } -#define MSGPACK_CONVERT_UPDATE_PROPERTY(_ht, _key, _key_len, _val, _var) \ - if (zend_symtable_update( \ - _ht, _key, _key_len, &_val, sizeof(_val), NULL) == SUCCESS) { \ - zend_hash_add(_var, _key, _key_len, &_val, sizeof(_val), NULL); \ - return SUCCESS; \ +#define MSGPACK_CONVERT_UPDATE_PROPERTY(_ht, _key, _val, _var) \ + if ((val = zend_symtable_update(_ht, _key, _val)) != NULL) { \ + zend_hash_add(_var, _key, _val); \ + return SUCCESS; \ } static inline int msgpack_convert_long_to_properties( @@ -89,39 +88,33 @@ static inline int msgpack_convert_long_to_properties( return (zend_hash_index_update(ht, key_index, val) != NULL); } -static inline int msgpack_convert_string_to_properties( +static inline int msgpack_convert_string_to_properties( zval *object, char *key, uint key_len, zval *val, HashTable *var) { - zval **data = NULL; + zval *data = NULL; HashTable *ht; zend_class_entry *ce; - char *prot_name, *priv_name; - int prop_name_len; + zend_string *priv_name, *prot_name; + TSRMLS_FETCH(); ht = HASH_OF(object); - ce = zend_get_class_entry(object TSRMLS_CC); + ce = Z_OBJ_P(object)->ce; /* private */ - zend_mangle_property_name( - &priv_name, &prop_name_len, ce->name, ce->name_length, key, key_len - 1, 1); - if (zend_hash_find( - ht, priv_name, prop_name_len + 1, (void **)&data) == SUCCESS) - { - MSGPACK_CONVERT_UPDATE_PROPERTY(ht, priv_name, prop_name_len + 1, val, var); - } + priv_name = zend_mangle_property_name(ce->name->val, ce->name->len, key, key_len - 1, 1); + if ((data = zend_hash_find(ht, priv_name)) != NULL) { + MSGPACK_CONVERT_UPDATE_PROPERTY(ht, priv_name, val, var); + } - /* protected */ - zend_mangle_property_name( - &prot_name, &prop_name_len, "*", 1, key, key_len - 1, 1); - if (zend_hash_find( - ht, prot_name, prop_name_len + 1, (void **)&data) == SUCCESS) - { - MSGPACK_CONVERT_UPDATE_PROPERTY(ht, prot_name, prop_name_len + 1, val, var); - } + /* protected */ + prot_name = zend_mangle_property_name("*", 1, key, key_len - 1, 1); + if ((data = zend_hash_find(ht, prot_name)) != NULL) { + MSGPACK_CONVERT_UPDATE_PROPERTY(ht, prot_name, val, var); + } /* public */ - MSGPACK_CONVERT_UPDATE_PROPERTY(ht, key, key_len, val, var); + MSGPACK_CONVERT_UPDATE_PROPERTY(ht, zend_string_init(key, key_len, 1), val, var); return FAILURE; } From e5ec207038ef9cc6737959502bceda144b65dfef Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Mon, 13 Apr 2015 07:10:41 +0000 Subject: [PATCH 18/75] Port msgpack_convert_array to the new hash iteration API --- msgpack_convert.c | 206 ++++++++++++++++++---------------------------- 1 file changed, 81 insertions(+), 125 deletions(-) diff --git a/msgpack_convert.c b/msgpack_convert.c index 02066ca..dc18dd0 100644 --- a/msgpack_convert.c +++ b/msgpack_convert.c @@ -125,14 +125,12 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) if (Z_TYPE_P(tpl) == IS_ARRAY) { - char *key; - uint key_len; - int key_type; - ulong key_index; - zval **data, **arydata; - HashPosition pos, valpos; HashTable *ht, *htval; int num; + zend_string *key_str; + ulong key_long; + zval *data; + ht = HASH_OF(tpl); // TODO: maybe need to release memory? @@ -144,7 +142,7 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) MSGPACK_WARNING( "[msgpack] (%s) template array length is 0", __FUNCTION__); - zval_ptr_dtor(value); + zval_ptr_dtor(*value); return FAILURE; } @@ -157,54 +155,32 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) MSGPACK_WARNING( "[msgpack] (%s) input data is not array", __FUNCTION__); - zval_ptr_dtor(value); + zval_ptr_dtor(*value); return FAILURE; } - zend_hash_internal_pointer_reset_ex(ht, &pos); - zend_hash_internal_pointer_reset_ex(htval, &valpos); - for (;; zend_hash_move_forward_ex(ht, &pos), - zend_hash_move_forward_ex(htval, &valpos)) - { - key_type = zend_hash_get_current_key_ex( - ht, &key, &key_len, &key_index, 0, &pos); - - if (key_type == HASH_KEY_NON_EXISTANT) - { - break; - } - - if (zend_hash_get_current_data_ex( - ht, (void *)&data, &pos) != SUCCESS) - { - continue; - } - - if (key_type == HASH_KEY_IS_STRING) - { + ZEND_HASH_FOREACH_KEY_VAL(ht, key_long, key_str, data) { + if (key_str) { int (*convert_function)(zval *, zval *, zval **) = NULL; zval **dataval, *val; - switch (Z_TYPE_PP(data)) + switch (Z_TYPE_P(data)) { case IS_ARRAY: convert_function = msgpack_convert_array; break; case IS_OBJECT: - // case IS_STRING: convert_function = msgpack_convert_object; break; default: break; } - if (zend_hash_get_current_data_ex( - htval, (void *)&dataval, &valpos) != SUCCESS) - { + if (!data) { MSGPACK_WARNING( "[msgpack] (%s) can't get data", __FUNCTION__); - zval_ptr_dtor(value); + zval_ptr_dtor(*value); return FAILURE; } @@ -213,22 +189,25 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) if (convert_function) { zval *rv; - ALLOC_INIT_ZVAL(rv); - if (convert_function(rv, *data, &val) != SUCCESS) + if (convert_function(rv, data, &val) != SUCCESS) { - zval_ptr_dtor(&val); + zval_ptr_dtor(val); return FAILURE; } - add_assoc_zval_ex(return_value, key, key_len, rv); + add_assoc_zval_ex(return_value, key_str->val, key_str->len, rv); } else { - add_assoc_zval_ex(return_value, key, key_len, val); + add_assoc_zval_ex(return_value, key_str->val, key_str->len, val); } + + } - } - zval_ptr_dtor(value); + } ZEND_HASH_FOREACH_END(); + + + zval_ptr_dtor(*value); return SUCCESS; } @@ -236,102 +215,79 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) { /* index */ int (*convert_function)(zval *, zval *, zval **) = NULL; + int first_loop = 0; - if (Z_TYPE_PP(value) != IS_ARRAY) + if (Z_TYPE_P(*value) != IS_ARRAY) { MSGPACK_WARNING( "[msgpack] (%s) unserialized data must be array.", __FUNCTION__); - zval_ptr_dtor(value); - return FAILURE; - } - - zend_hash_internal_pointer_reset_ex(ht, &pos); - - key_type = zend_hash_get_current_key_ex( - ht, &key, &key_len, &key_index, 0, &pos); - - if (key_type == HASH_KEY_NON_EXISTANT) - { - MSGPACK_WARNING( - "[msgpack] (%s) first element in template array is empty", - __FUNCTION__); - zval_ptr_dtor(value); + zval_ptr_dtor(*value); return FAILURE; } - if (zend_hash_get_current_data_ex( - ht, (void *)&data, &pos) != SUCCESS) - { - MSGPACK_WARNING( - "[msgpack] (%s) invalid template: empty array?", - __FUNCTION__); - zval_ptr_dtor(value); - return FAILURE; - } - - switch (Z_TYPE_PP(data)) - { - case IS_ARRAY: - convert_function = msgpack_convert_array; - break; - case IS_OBJECT: - case IS_STRING: - convert_function = msgpack_convert_object; - break; - default: - break; - } + ZEND_HASH_FOREACH_KEY_VAL(ht, key_long, key_str, data) { + if (first_loop) { + if (!key_long && !key_str) { + MSGPACK_WARNING( + "[msgpack] (%s) first element in template array is empty", + __FUNCTION__); + zval_ptr_dtor(*value); + return FAILURE; + } - htval = HASH_OF(*value); - num = zend_hash_num_elements(htval); - if (num <= 0) - { - MSGPACK_WARNING( - "[msgpack] (%s) array length is 0 in unserialized data", - __FUNCTION__); - zval_ptr_dtor(value); - return FAILURE; - } + if (!data) { + MSGPACK_WARNING( + "[msgpack] (%s) invalid template: empty array?", + __FUNCTION__); + zval_ptr_dtor(*value); + return FAILURE; + } - zend_hash_internal_pointer_reset_ex(htval, &valpos); - for (;; zend_hash_move_forward_ex(htval, &valpos)) - { - key_type = zend_hash_get_current_key_ex( - htval, &key, &key_len, &key_index, 0, &valpos); + switch (Z_TYPE_P(data)) { + case IS_ARRAY: + convert_function = msgpack_convert_array; + break; + case IS_OBJECT: + case IS_STRING: + convert_function = msgpack_convert_object; + break; + default: + break; + } - if (key_type == HASH_KEY_NON_EXISTANT) - { - break; - } + htval = HASH_OF(*value); + num = zend_hash_num_elements(htval); + if (num <= 0) { + MSGPACK_WARNING( + "[msgpack] (%s) array length is 0 in unserialized data", + __FUNCTION__); + zval_ptr_dtor(*value); + return FAILURE; + } - if (zend_hash_get_current_data_ex( - htval, (void *)&arydata, &valpos) != SUCCESS) - { - MSGPACK_WARNING( - "[msgpack] (%s) can't get next data in indexed array", - __FUNCTION__); - continue; - } - switch (key_type) - { - case HASH_KEY_IS_LONG: - { + first_loop = 1; + } else { + if (!data) { + MSGPACK_WARNING( + "[msgpack] (%s) can't get next data in indexed array", + __FUNCTION__); + continue; + } else if (key_long) { zval *aryval, *rv; - ALLOC_INIT_ZVAL(rv); - MSGPACK_CONVERT_COPY_ZVAL(aryval, arydata); + MSGPACK_CONVERT_COPY_ZVAL(aryval, data); if (convert_function) { - if (convert_function(rv, *data, &aryval) != SUCCESS) + if (convert_function(rv, data, &aryval) != SUCCESS) { - zval_ptr_dtor(&aryval); + zval_ptr_dtor(aryval); MSGPACK_WARNING( "[msgpack] (%s) " "convert failure in HASH_KEY_IS_LONG " "in indexed array", __FUNCTION__); - zval_ptr_dtor(value); + zval_ptr_dtor(*value); return FAILURE; } add_next_index_zval(return_value, rv); @@ -341,23 +297,23 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) add_next_index_zval(return_value, aryval); } break; - } - case HASH_KEY_IS_STRING: + } else if (key_str) { MSGPACK_WARNING( "[msgpack] (%s) key is string", __FUNCTION__); - zval_ptr_dtor(value); + zval_ptr_dtor(*value); return FAILURE; - default: + } else { MSGPACK_WARNING( "[msgpack] (%s) key is not string nor array", __FUNCTION__); - zval_ptr_dtor(value); + zval_ptr_dtor(*value); return FAILURE; + } } - } + } ZEND_HASH_FOREACH_END(); - zval_ptr_dtor(value); + zval_ptr_dtor(*value); return SUCCESS; } } @@ -367,12 +323,12 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) MSGPACK_WARNING( "[msgpack] (%s) template is not array", __FUNCTION__); - zval_ptr_dtor(value); + zval_ptr_dtor(*value); return FAILURE; } // shouldn't reach - zval_ptr_dtor(value); + zval_ptr_dtor(*value); return FAILURE; } From 272eebd943ba9373180832784fb35c4e8831d43f Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Mon, 13 Apr 2015 08:29:55 +0000 Subject: [PATCH 19/75] Update ZEND_FUNCTION declaration of msgpack_unserialize to use new zend_parse_parameters, which returns a zend_string instead of char+int --- msgpack.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/msgpack.c b/msgpack.c index cd5a4f5..f56f44f 100644 --- a/msgpack.c +++ b/msgpack.c @@ -287,34 +287,26 @@ static ZEND_FUNCTION(msgpack_serialize) static ZEND_FUNCTION(msgpack_unserialize) { - char *str; - int str_len; + zend_string *str; zval *object = NULL; - if (zend_parse_parameters( - ZEND_NUM_ARGS() TSRMLS_CC, "s|z", - &str, &str_len, &object) == FAILURE) - { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S|z", &str, &object) == FAILURE) { return; } - if (!str_len) - { + if (!str) { RETURN_NULL(); } - if (object == NULL) - { - php_msgpack_unserialize(return_value, str, str_len TSRMLS_CC); + if (object == NULL) { + php_msgpack_unserialize(return_value, str->val, str->len TSRMLS_CC); } - else - { + else { zval *zv; - php_msgpack_unserialize(zv, str, str_len TSRMLS_CC); + php_msgpack_unserialize(zv, str->val, str->len TSRMLS_CC); - if (msgpack_convert_template(return_value, object, &zv) != SUCCESS) - { + if (msgpack_convert_template(return_value, object, &zv) != SUCCESS) { RETURN_NULL(); } } From c52e1a79adba2984ea1b52fa007782109bd4a601 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Tue, 14 Apr 2015 06:41:46 +0000 Subject: [PATCH 20/75] Make sure to free returned smart_string in exposed ZEND_FUNCTION msgpack_serialize --- msgpack.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/msgpack.c b/msgpack.c index f56f44f..dfaf016 100644 --- a/msgpack.c +++ b/msgpack.c @@ -273,16 +273,15 @@ static ZEND_FUNCTION(msgpack_serialize) zval *parameter; smart_string buf = {0}; - if (zend_parse_parameters( - ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶meter) == FAILURE) - { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶meter) == FAILURE) { return; } php_msgpack_serialize(&buf, parameter TSRMLS_CC); - smart_string_0(&buf); + smart_string_0(&buf); ZVAL_STRINGL(return_value, buf.c, buf.len); + smart_string_free(&buf); } static ZEND_FUNCTION(msgpack_unserialize) From ff238285614307c4c0939d98bcfd7bf2e36404ed Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Wed, 15 Apr 2015 00:21:27 +0000 Subject: [PATCH 21/75] Update msgpack_check_ht_is_map to properly call zend_hash_add --- msgpack_pack.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index 63cfbde..e65de3a 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -46,10 +46,10 @@ inline static int msgpack_check_ht_is_map(zval *array) inline static int msgpack_var_add( HashTable *var_hash, zval *var, void *var_old TSRMLS_DC) { - ulong var_no; char id[32], *p; int len; zend_string *zstring; + zval zv; if ((Z_TYPE_P(var) == IS_OBJECT) && Z_OBJ_P(var)->ce) { p = zend_print_long_to_buf( @@ -75,9 +75,8 @@ inline static int msgpack_var_add( return FAILURE; } - var_no = zend_hash_num_elements(var_hash) + 1; - - zend_hash_add(var_hash, zstring, NULL); + ZVAL_LONG(&zv, zend_hash_num_elements(var_hash) + 1); + zend_hash_add(var_hash, zstring, &zv); return SUCCESS; } From 3137c5bc24f6671da77290b5cdc40e5fcc0bcb43 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Wed, 15 Apr 2015 05:26:06 +0000 Subject: [PATCH 22/75] Cleanup indentation, remove redundant casting --- msgpack.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/msgpack.c b/msgpack.c index dfaf016..42debdc 100644 --- a/msgpack.c +++ b/msgpack.c @@ -232,13 +232,12 @@ PHP_MSGPACK_API void php_msgpack_unserialize( msgpack_unserialize_var_init(&var_hash); RETVAL_NULL(); - mp.user.retval = (zval *)return_value; - mp.user.var_hash = (msgpack_unserialize_data_t *)&var_hash; + mp.user.retval = return_value; + mp.user.var_hash = &var_hash; ret = template_execute(&mp, str, (size_t)str_len, &off); - switch (ret) - { + switch (ret) { case MSGPACK_UNPACK_PARSE_ERROR: zval_dtor(return_value); ZVAL_FALSE(return_value); @@ -254,8 +253,7 @@ PHP_MSGPACK_API void php_msgpack_unserialize( case MSGPACK_UNPACK_EXTRA_BYTES: case MSGPACK_UNPACK_SUCCESS: msgpack_unserialize_var_destroy(&var_hash, 0); - if (off < (size_t)str_len) - { + if (off < str_len) { MSGPACK_WARNING("[msgpack] (%s) Extra bytes", __FUNCTION__); } break; @@ -299,8 +297,7 @@ static ZEND_FUNCTION(msgpack_unserialize) if (object == NULL) { php_msgpack_unserialize(return_value, str->val, str->len TSRMLS_CC); - } - else { + } else { zval *zv; php_msgpack_unserialize(zv, str->val, str->len TSRMLS_CC); From 19e32ed451ef2f7162d3145d5e86a3b22b32e599 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Thu, 16 Apr 2015 06:55:16 +0000 Subject: [PATCH 23/75] Port msgpack_convert_array to the new hash iteration API --- msgpack_convert.c | 247 ++++++++++++++-------------------------------- 1 file changed, 73 insertions(+), 174 deletions(-) diff --git a/msgpack_convert.c b/msgpack_convert.c index dc18dd0..eefd5ad 100644 --- a/msgpack_convert.c +++ b/msgpack_convert.c @@ -33,8 +33,7 @@ return SUCCESS; \ } -static inline int msgpack_convert_long_to_properties( - HashTable *ht, HashTable **properties, HashPosition *prop_pos, +static inline int msgpack_convert_long_to_properties(HashTable *ht, HashTable **properties, uint key_index, zval *val, HashTable *var) { TSRMLS_FETCH(); @@ -331,27 +330,21 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) zval_ptr_dtor(*value); return FAILURE; } - -int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) -{ - zend_class_entry *ce, **pce; +int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { + zend_class_entry *ce; TSRMLS_FETCH(); switch (Z_TYPE_P(tpl)) { case IS_STRING: - if (zend_lookup_class( - Z_STRVAL_P(tpl), Z_STRLEN_P(tpl), - &pce TSRMLS_CC) != SUCCESS) - { + if ((ce = zend_lookup_class(zend_string_init( Z_STRVAL_P(tpl), Z_STRLEN_P(tpl), 0))) != SUCCESS) { MSGPACK_ERROR("[msgpack] (%s) Class '%s' not found", __FUNCTION__, Z_STRVAL_P(tpl)); return FAILURE; } - ce = *pce; break; case IS_OBJECT: - ce = zend_get_class_entry(tpl TSRMLS_CC); + ce = Z_OBJ_P(tpl)->ce; break; default: MSGPACK_ERROR("[msgpack] (%s) object type is unsupported", @@ -359,16 +352,15 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) return FAILURE; } - if (Z_TYPE_PP(value) == IS_OBJECT) - { + if (Z_TYPE_PP(value) == IS_OBJECT) { zend_class_entry *vce; - vce = zend_get_class_entry(*value TSRMLS_CC); - if (strcmp(ce->name, vce->name) == 0) + vce = Z_OBJ_P(tpl)->ce; + if (strcmp(ce->name->val, vce->name->val) == 0) { *return_value = **value; zval_copy_ctor(return_value); - zval_ptr_dtor(value); + zval_ptr_dtor(*value); return SUCCESS; } } @@ -380,18 +372,18 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) && (ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC)) { zval *retval_ptr = NULL; - zval ***params = NULL; + zval *params = NULL; + zval function_name; int num_args = 0; zend_fcall_info fci; zend_fcall_info_cache fcc; -#if ZEND_MODULE_API_NO >= 20090626 fci.size = sizeof(fci); fci.function_table = EG(function_table); - fci.function_name = NULL; + fci.function_name = function_name; fci.symbol_table = NULL; - fci.object_ptr = return_value; - fci.retval_ptr_ptr = &retval_ptr; + fci.object = Z_OBJ_P(return_value); + fci.retval = retval_ptr; fci.param_count = num_args; fci.params = params; fci.no_separation = 1; @@ -400,33 +392,13 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) fcc.function_handler = ce->constructor; fcc.calling_scope = EG(scope); fcc.called_scope = Z_OBJCE_P(return_value); - fcc.object_ptr = return_value; -#else - fci.size = sizeof(fci); - fci.function_table = EG(function_table); - fci.function_name = NULL; - fci.symbol_table = NULL; - fci.object_pp = &return_value; - fci.retval_ptr_ptr = &retval_ptr; - fci.param_count = num_args; - fci.params = params; - fci.no_separation = 1; - fcc.initialized = 1; - fcc.function_handler = ce->constructor; - fcc.calling_scope = EG(scope); - fcc.object_pp = &return_value; -#endif - - if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) - { - if (params) - { + if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) { + if (params) { efree(params); } - if (retval_ptr) - { - zval_ptr_dtor(&retval_ptr); + if (retval_ptr) { + zval_ptr_dtor(retval_ptr); } MSGPACK_WARNING( @@ -435,12 +407,10 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) return FAILURE; } - if (retval_ptr) - { - zval_ptr_dtor(&retval_ptr); + if (retval_ptr) { + zval_ptr_dtor(retval_ptr); } - if (params) - { + if (params) { efree(params); } } @@ -449,151 +419,95 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { case IS_ARRAY: { - char *key; - uint key_len; - int key_type; - ulong key_index; - zval **data; - HashPosition pos; HashTable *ht, *ret; HashTable *var = NULL; int num; + zend_string *str_key; + zval *data; + ulong num_key; + ht = HASH_OF(*value); ret = HASH_OF(return_value); num = zend_hash_num_elements(ht); - if (num <= 0) - { - zval_ptr_dtor(value); + if (num <= 0) { + zval_ptr_dtor(*value); break; } /* string - php_only mode? */ if (ht->nNumOfElements != ht->nNextFreeElement - || ht->nNumOfElements != ret->nNumOfElements) - { + || ht->nNumOfElements != ret->nNumOfElements) { HashTable *properties = NULL; - HashPosition prop_pos; ALLOC_HASHTABLE(var); zend_hash_init(var, num, NULL, NULL, 0); - zend_hash_internal_pointer_reset_ex(ht, &pos); - for (;; zend_hash_move_forward_ex(ht, &pos)) - { - key_type = zend_hash_get_current_key_ex( - ht, &key, &key_len, &key_index, 0, &pos); - - if (key_type == HASH_KEY_NON_EXISTANT) - { - break; - } - - if (zend_hash_get_current_data_ex( - ht, (void *)&data, &pos) != SUCCESS) - { - continue; - } - - if (key_type == HASH_KEY_IS_STRING) - { + ZEND_HASH_FOREACH_KEY_VAL(ht, num_key, str_key, data) { + if (str_key && data) { zval *val; - MSGPACK_CONVERT_COPY_ZVAL(val, data); + MSGPACK_CONVERT_COPY_ZVAL(val, &data); if (msgpack_convert_string_to_properties( - return_value, key, key_len, val, var) != SUCCESS) + return_value, str_key->val, str_key->len, val, var) != SUCCESS) { - zval_ptr_dtor(&val); + zval_ptr_dtor(val); MSGPACK_WARNING( - "[msgpack] (%s) " - "illegal offset type, skip this decoding", - __FUNCTION__); + "[msgpack] (%s) " + "illegal offset type, skip this decoding", + __FUNCTION__); } } - } + } ZEND_HASH_FOREACH_END(); /* index */ - properties = Z_OBJ_HT_P(return_value)->get_properties( - return_value TSRMLS_CC); + properties = Z_OBJ_HT_P(return_value)->get_properties(return_value TSRMLS_CC); - if (HASH_OF(tpl)) - { + if (HASH_OF(tpl)) { properties = HASH_OF(tpl); } - zend_hash_internal_pointer_reset_ex(properties, &prop_pos); - - zend_hash_internal_pointer_reset_ex(ht, &pos); - for (;; zend_hash_move_forward_ex(ht, &pos)) - { - key_type = zend_hash_get_current_key_ex( - ht, &key, &key_len, &key_index, 0, &pos); - - if (key_type == HASH_KEY_NON_EXISTANT) - { - break; - } - if (zend_hash_get_current_data_ex( - ht, (void *)&data, &pos) != SUCCESS) - { + ZEND_HASH_FOREACH_KEY_VAL(ht, num_key, str_key, data) { + if (!data) { continue; } - - switch (key_type) - { - case HASH_KEY_IS_LONG: - { - zval *val; - MSGPACK_CONVERT_COPY_ZVAL(val, data); - if (msgpack_convert_long_to_properties( - ret, &properties, &prop_pos, - key_index, val, var) != SUCCESS) - { - zval_ptr_dtor(&val); - MSGPACK_WARNING( + if (num_key) { + zval *val; + MSGPACK_CONVERT_COPY_ZVAL(val, &data); + if (msgpack_convert_long_to_properties(ret, &properties, num_key, val, var) != SUCCESS) { + zval_ptr_dtor(val); + MSGPACK_WARNING( "[msgpack] (%s) " "illegal offset type, skip this decoding", __FUNCTION__); - } - break; } - case HASH_KEY_IS_STRING: - break; - default: - MSGPACK_WARNING( + break; + } else if (str_key) { + break; + } else { + MSGPACK_WARNING( "[msgpack] (%s) key is not string nor array", __FUNCTION__); - break; + break; } - } + } ZEND_HASH_FOREACH_END(); zend_hash_destroy(var); FREE_HASHTABLE(var); - } - else - { + } else { HashPosition valpos; int (*convert_function)(zval *, zval *, zval **) = NULL; zval **arydata, *aryval; - /* index */ - zend_hash_internal_pointer_reset_ex(ret, &pos); - zend_hash_internal_pointer_reset_ex(ht, &valpos); - for (;; zend_hash_move_forward_ex(ret, &pos), - zend_hash_move_forward_ex(ht, &valpos)) - { - key_type = zend_hash_get_current_key_ex( - ret, &key, &key_len, &key_index, 0, &pos); + ZEND_HASH_FOREACH_KEY_VAL(ret, num_key, str_key, data) { - if (key_type == HASH_KEY_NON_EXISTANT) - { + if (!num_key && !str_key) { break; - } - - if (zend_hash_get_current_data_ex( - ret, (void *)&data, &pos) != SUCCESS) - { - continue; + } if (!data) { + MSGPACK_WARNING( + "[msgpack] (%s) can't get data value by index", + __FUNCTION__); + return FAILURE; } switch (Z_TYPE_PP(data)) @@ -610,25 +524,14 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) break; } - if (zend_hash_get_current_data_ex( - ht, (void *)&arydata, &valpos) != SUCCESS) - { - MSGPACK_WARNING( - "[msgpack] (%s) can't get data value by index", - __FUNCTION__); - return FAILURE; - } - - MSGPACK_CONVERT_COPY_ZVAL(aryval, arydata); + MSGPACK_CONVERT_COPY_ZVAL(aryval, &data); - if (convert_function) - { + if (convert_function) { zval *rv; ALLOC_INIT_ZVAL(rv); - if (convert_function(rv, *data, &aryval) != SUCCESS) - { - zval_ptr_dtor(&aryval); + if (convert_function(rv, data, &aryval) != SUCCESS) { + zval_ptr_dtor(aryval); MSGPACK_WARNING( "[msgpack] (%s) " "convert failure in convert_object", @@ -636,18 +539,14 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) return FAILURE; } - zend_symtable_update( - ret, key, key_len, &rv, sizeof(rv), NULL); + zend_symtable_update( ret, str_key, rv); + } else { + zend_symtable_update(ret, str_key, aryval); } - else - { - zend_symtable_update( - ret, key, key_len, &aryval, sizeof(aryval), NULL); - } - } - } + } ZEND_HASH_FOREACH_END(); - zval_ptr_dtor(value); + } + zval_ptr_dtor(*value); break; } default: @@ -660,7 +559,7 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) zend_hash_internal_pointer_reset_ex(properties, &prop_pos); if (msgpack_convert_long_to_properties( - HASH_OF(return_value), &properties, &prop_pos, + HASH_OF(return_value), &properties, 0, *value, NULL) != SUCCESS) { MSGPACK_WARNING( From a765bd8fdfc8fcf76481603d2a9cee57307a8755 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Thu, 16 Apr 2015 07:49:21 +0000 Subject: [PATCH 24/75] Off by one when serializing a string during array serialization --- msgpack_pack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index e65de3a..86c90f0 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -272,7 +272,7 @@ inline static void msgpack_serialize_array( continue; } if (key_str) { - msgpack_serialize_string(buf, key_str->val, key_str->len - 1); + msgpack_serialize_string(buf, key_str->val, key_str->len); } else if (key_long) { msgpack_pack_long(buf, key_long); } else { From f1388a6663c9ff43c900106e52a1f3a473aa0312 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Thu, 16 Apr 2015 09:14:20 +0000 Subject: [PATCH 25/75] msgpack_unserialize_map_item was incorrectly ported, MSGPACK_WARNING was being fired when zend_symtable_update succeeded instead of failed --- msgpack_unpack.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index db2192a..4bebeff 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -690,8 +690,7 @@ int msgpack_unserialize_map_item( switch (Z_TYPE_P(key)) { case IS_LONG: - if ((val = zend_hash_index_update(HASH_OF(*container), Z_LVAL_P(key), val)) != NULL) - { + if ((val = zend_hash_index_update(HASH_OF(*container), Z_LVAL_P(key), val)) == NULL) { zval_ptr_dtor(val); MSGPACK_WARNING( "[msgpack] (%s) illegal offset type, skip this decoding", @@ -701,8 +700,7 @@ int msgpack_unserialize_map_item( break; case IS_STRING: - if ((val = zend_symtable_update(HASH_OF(*container), zend_string_init(Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, 0), val)) != NULL) - { + if ((val = zend_symtable_update(HASH_OF(*container), zend_string_init(Z_STRVAL_P(key), Z_STRLEN_P(key), 0), val)) == NULL) { zval_ptr_dtor(val); MSGPACK_WARNING( "[msgpack] (%s) illegal offset type, skip this decoding", @@ -715,20 +713,17 @@ int msgpack_unserialize_map_item( if (MSGPACK_G(illegal_key_insert)) { - if ((key = zend_hash_next_index_insert(HASH_OF(*container), key)) != NULL) - { + if ((key = zend_hash_next_index_insert(HASH_OF(*container), key)) == NULL) { zval_ptr_dtor(val); } - if ((val = zend_hash_next_index_insert(HASH_OF(*container), val)) != NULL) - { + if ((val = zend_hash_next_index_insert(HASH_OF(*container), val)) == NULL) { zval_ptr_dtor(val); } } else { convert_to_string(key); - if ((zend_symtable_update(HASH_OF(*container), zend_string_init(Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, 0), val)) != NULL) - { + if ((zend_symtable_update(HASH_OF(*container), zend_string_init(Z_STRVAL_P(key), Z_STRLEN_P(key), 0), val)) == NULL) { zval_ptr_dtor(val); } zval_ptr_dtor(key); From 9d6d6367505cffd85c9b22a31f09fb1307bb8efa Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Thu, 16 Apr 2015 23:13:24 +0000 Subject: [PATCH 26/75] Add Z_TYPE_REF_AWARE_P macro since when packing we can are possibly processing refs --- msgpack_pack.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index 86c90f0..ac19fa3 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -18,10 +18,8 @@ #define msgpack_pack_append_buffer(user, buf, len) \ smart_string_appendl(user, (const void*)buf, len) #include "msgpack/pack_template.h" - -#if ZEND_MODULE_API_NO < 20090626 -# define Z_ISREF_P(pz) PZVAL_IS_REF(pz) -#endif +#define Z_TYPE_REF_AWARE_P(_obj) \ + (Z_ISREF_P(_obj)?Z_TYPE_P(Z_REFVAL_P(_obj)):Z_TYPE_P(_obj)) inline static int msgpack_check_ht_is_map(zval *array) { @@ -51,7 +49,7 @@ inline static int msgpack_var_add( zend_string *zstring; zval zv; - if ((Z_TYPE_P(var) == IS_OBJECT) && Z_OBJ_P(var)->ce) { + if ((Z_TYPE_REF_AWARE_P(var) == IS_OBJECT) && Z_OBJ_P(var)->ce) { p = zend_print_long_to_buf( id + sizeof(id) - 1, (((size_t)Z_OBJCE_P(var) << 5) @@ -59,7 +57,7 @@ inline static int msgpack_var_add( + (long)Z_OBJ_HANDLE_P(var)); len = id + sizeof(id) - 1 - p; } - else if (Z_TYPE_P(var) == IS_ARRAY) { + else if (Z_TYPE_REF_AWARE_P(var) == IS_ARRAY) { p = zend_print_long_to_buf(id + sizeof(id) - 1, (long)var); len = id + sizeof(id) - 1 - p; } @@ -67,7 +65,7 @@ inline static int msgpack_var_add( return FAILURE; } - zstring = zend_string_init(p, len, 1); + zstring = zend_string_init(p, len, 0); if (var_old && (var_old = zend_hash_find(var_hash, zstring)) != NULL) { if (!Z_ISREF_P(var)) { zend_hash_next_index_insert(var_hash, NULL); @@ -121,7 +119,7 @@ inline static void msgpack_serialize_class( continue; } - if (Z_TYPE_P(value) != IS_STRING) { + if (Z_TYPE_REF_AWARE_P(value) != IS_STRING) { MSGPACK_NOTICE( "[msgpack] (%s) __sleep should return an array only " "containing the names of instance-variables to serialize", @@ -282,18 +280,17 @@ inline static void msgpack_serialize_array( __FUNCTION__); } - - if ((Z_TYPE_P(value) == IS_ARRAY && Z_ARRVAL_P(value)->u.v.nApplyCount > 1)) { + if ((Z_TYPE_REF_AWARE_P(value) == IS_ARRAY && Z_ARRVAL_P(value)->u.v.nApplyCount > 1)) { msgpack_pack_nil(buf); } else { - if (Z_TYPE_P(value) == IS_ARRAY) + if (Z_TYPE_REF_AWARE_P(value) == IS_ARRAY) { Z_ARRVAL_P(value)->u.v.nApplyCount++; } msgpack_serialize_zval(buf, value, var_hash TSRMLS_CC); - if (Z_TYPE_P(value) == IS_ARRAY) + if (Z_TYPE_REF_AWARE_P(value) == IS_ARRAY) { Z_ARRVAL_P(value)->u.v.nApplyCount--; } @@ -309,21 +306,21 @@ inline static void msgpack_serialize_array( { if ((data = zend_hash_index_find(ht, i)) == NULL || !data || &data == &val || - (Z_TYPE_P(data) == IS_ARRAY && + (Z_TYPE_REF_AWARE_P(data) == IS_ARRAY && Z_ARRVAL_P(data)->u.v.nApplyCount > 1)) { msgpack_pack_nil(buf); } else { - if (Z_TYPE_P(data) == IS_ARRAY) + if (Z_TYPE_REF_AWARE_P(data) == IS_ARRAY) { Z_ARRVAL_P(data)->u.v.nApplyCount++; } msgpack_serialize_zval(buf, data, var_hash TSRMLS_CC); - if (Z_TYPE_P(data) == IS_ARRAY) + if (Z_TYPE_REF_AWARE_P(data) == IS_ARRAY) { Z_ARRVAL_P(data)->u.v.nApplyCount--; } @@ -435,7 +432,7 @@ void msgpack_serialize_zval( { if (Z_ISREF_P(val)) { - if (Z_TYPE_P(val) == IS_ARRAY) + if (Z_TYPE_REF_AWARE_P(val) == IS_ARRAY) { msgpack_pack_map(buf, 2); @@ -447,7 +444,7 @@ void msgpack_serialize_zval( return; } - else if (Z_TYPE_P(val) == IS_OBJECT) + else if (Z_TYPE_REF_AWARE_P(val) == IS_OBJECT) { msgpack_pack_map(buf, 2); @@ -460,7 +457,7 @@ void msgpack_serialize_zval( return; } } - else if (Z_TYPE_P(val) == IS_OBJECT) + else if (Z_TYPE_REF_AWARE_P(val) == IS_OBJECT) { msgpack_pack_map(buf, 2); @@ -474,7 +471,7 @@ void msgpack_serialize_zval( } } - switch (Z_TYPE_P(val)) + switch (Z_TYPE_REF_AWARE_P(val)) { case IS_NULL: msgpack_pack_nil(buf); From aaeee58772d612caba0920e5f4621b67edf3c483 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Fri, 17 Apr 2015 09:01:54 +0000 Subject: [PATCH 27/75] Z_LVAL_P -> zval_get_long in case where we could have refs --- msgpack_pack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index ac19fa3..7dcb849 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -483,7 +483,7 @@ void msgpack_serialize_zval( msgpack_pack_false(buf); break; case IS_LONG: - msgpack_pack_long(buf, Z_LVAL_P(val)); + msgpack_pack_long(buf, zval_get_long(val)); break; case IS_DOUBLE: { From d9b65530ae8cd876dcf680da34e576b9af89fdb6 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sat, 18 Apr 2015 21:31:33 +0000 Subject: [PATCH 28/75] When packing make everything ref aware, before TYPE/VAL would fail --- msgpack_pack.c | 60 ++++++++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index 7dcb849..3a354d5 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -18,24 +18,24 @@ #define msgpack_pack_append_buffer(user, buf, len) \ smart_string_appendl(user, (const void*)buf, len) #include "msgpack/pack_template.h" -#define Z_TYPE_REF_AWARE_P(_obj) \ - (Z_ISREF_P(_obj)?Z_TYPE_P(Z_REFVAL_P(_obj)):Z_TYPE_P(_obj)) +#define Z_REF_AWARE_P(_obj) \ + (Z_ISREF_P(_obj)?Z_REFVAL_P(_obj):_obj) inline static int msgpack_check_ht_is_map(zval *array) { - int count = zend_hash_num_elements(Z_ARRVAL_P(array)); + int count = zend_hash_num_elements(Z_ARRVAL_P(Z_REF_AWARE_P(array))); - if (count != (Z_ARRVAL_P(array))->nNextFreeElement) { + if (count != (Z_ARRVAL_P(Z_REF_AWARE_P(array)))->nNextFreeElement) { return 1; } else { int i; HashPosition pos = {0}; - zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos); + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(Z_REF_AWARE_P(array)), &pos); for (i = 0; i < count; i++) { - if (zend_hash_get_current_key_type_ex(Z_ARRVAL_P(array), &pos) != HASH_KEY_IS_LONG) { + if (zend_hash_get_current_key_type_ex(Z_ARRVAL_P(Z_REF_AWARE_P(array)), &pos) != HASH_KEY_IS_LONG) { return 1; } - zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos); + zend_hash_move_forward_ex(Z_ARRVAL_P(Z_REF_AWARE_P(array)), &pos); } } return 0; @@ -49,7 +49,7 @@ inline static int msgpack_var_add( zend_string *zstring; zval zv; - if ((Z_TYPE_REF_AWARE_P(var) == IS_OBJECT) && Z_OBJ_P(var)->ce) { + if ((Z_TYPE_P(Z_REF_AWARE_P(var)) == IS_OBJECT) && Z_OBJ_P(var)->ce) { p = zend_print_long_to_buf( id + sizeof(id) - 1, (((size_t)Z_OBJCE_P(var) << 5) @@ -57,7 +57,7 @@ inline static int msgpack_var_add( + (long)Z_OBJ_HANDLE_P(var)); len = id + sizeof(id) - 1 - p; } - else if (Z_TYPE_REF_AWARE_P(var) == IS_ARRAY) { + else if (Z_TYPE_P(Z_REF_AWARE_P(var)) == IS_ARRAY) { p = zend_print_long_to_buf(id + sizeof(id) - 1, (long)var); len = id + sizeof(id) - 1 - p; } @@ -119,7 +119,7 @@ inline static void msgpack_serialize_class( continue; } - if (Z_TYPE_REF_AWARE_P(value) != IS_STRING) { + if (Z_TYPE_P(Z_REF_AWARE_P(value)) != IS_STRING) { MSGPACK_NOTICE( "[msgpack] (%s) __sleep should return an array only " "containing the names of instance-variables to serialize", @@ -192,7 +192,7 @@ inline static void msgpack_serialize_array( } else { - ht = HASH_OF(val); + ht = HASH_OF(Z_REF_AWARE_P(val)); } if (ht) @@ -271,26 +271,21 @@ inline static void msgpack_serialize_array( } if (key_str) { msgpack_serialize_string(buf, key_str->val, key_str->len); - } else if (key_long) { - msgpack_pack_long(buf, key_long); } else { - msgpack_serialize_string(buf, "", sizeof("")); - MSGPACK_WARNING( - "[msgpack] (%s) key is not string nor array", - __FUNCTION__); + msgpack_pack_long(buf, key_long); } - if ((Z_TYPE_REF_AWARE_P(value) == IS_ARRAY && Z_ARRVAL_P(value)->u.v.nApplyCount > 1)) { + if ((Z_TYPE_P(Z_REF_AWARE_P(value)) == IS_ARRAY && Z_ARRVAL_P(value)->u.v.nApplyCount > 1)) { msgpack_pack_nil(buf); } else { - if (Z_TYPE_REF_AWARE_P(value) == IS_ARRAY) + if (Z_TYPE_P(Z_REF_AWARE_P(value)) == IS_ARRAY) { Z_ARRVAL_P(value)->u.v.nApplyCount++; } msgpack_serialize_zval(buf, value, var_hash TSRMLS_CC); - if (Z_TYPE_REF_AWARE_P(value) == IS_ARRAY) + if (Z_TYPE_P(Z_REF_AWARE_P(value)) == IS_ARRAY) { Z_ARRVAL_P(value)->u.v.nApplyCount--; } @@ -306,23 +301,23 @@ inline static void msgpack_serialize_array( { if ((data = zend_hash_index_find(ht, i)) == NULL || !data || &data == &val || - (Z_TYPE_REF_AWARE_P(data) == IS_ARRAY && - Z_ARRVAL_P(data)->u.v.nApplyCount > 1)) + (Z_TYPE_P(Z_REF_AWARE_P(data)) == IS_ARRAY && + Z_ARRVAL_P(Z_REF_AWARE_P(data))->u.v.nApplyCount > 1)) { msgpack_pack_nil(buf); } else { - if (Z_TYPE_REF_AWARE_P(data) == IS_ARRAY) + if (Z_TYPE_P(Z_REF_AWARE_P(data)) == IS_ARRAY) { - Z_ARRVAL_P(data)->u.v.nApplyCount++; + Z_ARRVAL_P(Z_REF_AWARE_P(data))->u.v.nApplyCount++; } msgpack_serialize_zval(buf, data, var_hash TSRMLS_CC); - if (Z_TYPE_REF_AWARE_P(data) == IS_ARRAY) + if (Z_TYPE_P(Z_REF_AWARE_P(data)) == IS_ARRAY) { - Z_ARRVAL_P(data)->u.v.nApplyCount--; + Z_ARRVAL_P(Z_REF_AWARE_P(data))->u.v.nApplyCount--; } } } @@ -432,7 +427,7 @@ void msgpack_serialize_zval( { if (Z_ISREF_P(val)) { - if (Z_TYPE_REF_AWARE_P(val) == IS_ARRAY) + if (Z_TYPE_P(Z_REF_AWARE_P(val)) == IS_ARRAY) { msgpack_pack_map(buf, 2); @@ -444,7 +439,7 @@ void msgpack_serialize_zval( return; } - else if (Z_TYPE_REF_AWARE_P(val) == IS_OBJECT) + else if (Z_TYPE_P(Z_REF_AWARE_P(val)) == IS_OBJECT) { msgpack_pack_map(buf, 2); @@ -457,7 +452,7 @@ void msgpack_serialize_zval( return; } } - else if (Z_TYPE_REF_AWARE_P(val) == IS_OBJECT) + else if (Z_TYPE_P(Z_REF_AWARE_P(val)) == IS_OBJECT) { msgpack_pack_map(buf, 2); @@ -471,7 +466,7 @@ void msgpack_serialize_zval( } } - switch (Z_TYPE_REF_AWARE_P(val)) + switch (Z_TYPE_P(Z_REF_AWARE_P(val))) { case IS_NULL: msgpack_pack_nil(buf); @@ -486,10 +481,7 @@ void msgpack_serialize_zval( msgpack_pack_long(buf, zval_get_long(val)); break; case IS_DOUBLE: - { - double dbl = Z_DVAL_P(val); - msgpack_pack_double(buf, dbl); - } + msgpack_pack_double(buf, Z_DVAL_P(val)); break; case IS_STRING: msgpack_serialize_string( From b37104b5f7a151f4dcfc2569491ff74213f6ee7b Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Mon, 20 Apr 2015 23:49:31 +0000 Subject: [PATCH 29/75] FIXME update msgpack_serialize_zval to call Z_INDIRECT_P if the type equals IS_INDIRECT --- msgpack_pack.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/msgpack_pack.c b/msgpack_pack.c index 3a354d5..a9282ec 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -420,6 +420,10 @@ void msgpack_serialize_zval( { ulong *var_already; + if (Z_TYPE_P(val) == IS_INDIRECT) { + val = Z_INDIRECT_P(val); + } + if (MSGPACK_G(php_only) && var_hash && msgpack_var_add( From f5b47f831a534f18418abc1b3d5f4f26d472c1ff Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Tue, 21 Apr 2015 18:16:51 +0000 Subject: [PATCH 30/75] Cleanup msgpack_unserialize_class, fixing 012 test segment fault --- msgpack_unpack.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 4bebeff..df80271 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -188,7 +188,7 @@ inline static void msgpack_stack_pop( inline static zend_class_entry* msgpack_unserialize_class( zval **container, char *class_name, size_t name_len) { - zend_class_entry *ce, **pce; + zend_class_entry *ce; zend_bool incomplete_class = 0; zval *user_func, *retval_ptr, args[1], *arg_func_name; TSRMLS_FETCH(); @@ -196,9 +196,7 @@ inline static zend_class_entry* msgpack_unserialize_class( do { /* Try to find class directly */ - if ((*pce = zend_lookup_class(zend_string_init(class_name, name_len, 0))) != NULL) - { - ce = *pce; + if ((ce = zend_lookup_class(zend_string_init("Obj", name_len, 0))) != NULL) { break; } @@ -226,18 +224,12 @@ inline static zend_class_entry* msgpack_unserialize_class( zval_ptr_dtor(arg_func_name); break; } - if (retval_ptr) - { + if (retval_ptr) { zval_ptr_dtor(retval_ptr); } /* The callback function may have defined the class */ - if ((*pce = zend_lookup_class(zend_string_init(class_name, name_len, 0))) != NULL) - { - ce = *pce; - } - else - { + if ((ce = zend_lookup_class(zend_string_init(class_name, name_len, 0))) == NULL) { MSGPACK_WARNING("[msgpack] (%s) Function %s() hasn't defined " "the class it was called for", __FUNCTION__, class_name); From 774659c27d608a1ce25ce421050ec6670ab7b7fa Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Tue, 21 Apr 2015 18:28:45 +0000 Subject: [PATCH 31/75] FIXME add temporary version of ALLOC_INIT_ZVAL to msgpack_unpack, until we I do a proper refactor of zval allocation for the MSGPACK_UNSERIALIZE_ALLOC_STACK and MSGPACK_UNSERIALIZE_ALLOC_VALUE macros --- msgpack_unpack.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index df80271..bbe2dc4 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -17,11 +17,18 @@ typedef struct void *next; } var_entries; +#define ALLOC_ZVAL(z) \ + (z) = (zval *) emalloc(sizeof(zval)) + +#define ALLOC_INIT_ZVAL(zp) \ + ALLOC_ZVAL(zp); + #define MSGPACK_UNSERIALIZE_ALLOC_STACK(_unpack) \ if (_unpack->deps <= 0) { \ *obj = _unpack->retval; \ msgpack_stack_push(_unpack->var_hash, obj, 0); \ } else { \ + ALLOC_INIT_ZVAL(*obj); \ msgpack_stack_push(_unpack->var_hash, obj, 1); \ } @@ -30,6 +37,7 @@ typedef struct *obj = _unpack->retval; \ msgpack_var_push(_unpack->var_hash, obj); \ } else { \ + ALLOC_INIT_ZVAL(*obj); \ msgpack_var_push(_unpack->var_hash, obj); \ } From 487f76dfd6faf934f67f3d543d6b792df94714d2 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Wed, 22 Apr 2015 01:19:05 +0000 Subject: [PATCH 32/75] msgpack_serialize_class expects a list of keys, not a map. Update msgpack_serialize_object so it passes an initalized zval to call_user_function_ex --- msgpack_pack.c | 84 +++++++++++++++++++------------------------------- 1 file changed, 32 insertions(+), 52 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index a9282ec..656852a 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -94,13 +94,11 @@ inline static void msgpack_serialize_class( HashTable *ht = HASH_OF(retval_ptr); count = zend_hash_num_elements(ht); - if (incomplete_class) - { + if (incomplete_class) { --count; } - if (count > 0) - { + if (count > 0) { msgpack_pack_map(buf, count + 1); msgpack_pack_nil(buf); msgpack_serialize_string(buf, class_name, name_len); @@ -112,9 +110,6 @@ inline static void msgpack_serialize_class( nvalp = &nval; ZEND_HASH_FOREACH_KEY_VAL(ht, key_long, key_str, value) { - if (!key_long && !key_str) { - break; - } if (incomplete_class && strcmp(key_str->val, MAGIC_MEMBER) == 0) { continue; } @@ -126,18 +121,19 @@ inline static void msgpack_serialize_class( __FUNCTION__); continue; } - if ((data = zend_hash_find(Z_OBJPROP_P(val), key_str)) != NULL) { - msgpack_serialize_string(buf, key_str->val, key_str->len); + if ((data = zend_hash_find(Z_OBJPROP_P(val), + zend_string_init(Z_STRVAL_P(value), Z_STRLEN_P(value), 0))) != NULL) + { + msgpack_serialize_string(buf, Z_STRVAL_P(value), Z_STRLEN_P(value)); msgpack_serialize_zval(buf, data, var_hash TSRMLS_CC); } else { zend_class_entry *ce = Z_OBJ_P(val)->ce; - if (ce) - { + if (ce) { zend_string *priv_name, *prot_name; do { priv_name = zend_mangle_property_name(ce->name->val, ce->name->len, - key_str->val, key_str->len, + Z_STRVAL_P(value), Z_STRLEN_P(value), ce->type & ZEND_INTERNAL_CLASS); if ((data = zend_hash_find(Z_OBJPROP_P(val), priv_name)) != NULL) { msgpack_serialize_string(buf, priv_name->val, priv_name->len); @@ -149,7 +145,7 @@ inline static void msgpack_serialize_class( pefree(priv_name, ce->type & ZEND_INTERNAL_CLASS); prot_name = zend_mangle_property_name("*", 1, - key_str->val, key_str->len, + Z_STRVAL_P(value), Z_STRLEN_P(value), ce->type & ZEND_INTERNAL_CLASS); if ((data = zend_hash_find(Z_OBJPROP_P(val), prot_name)) != NULL) { @@ -163,14 +159,12 @@ inline static void msgpack_serialize_class( MSGPACK_NOTICE( "[msgpack] (%s) \"%s\" returned as member " "variable from __sleep() but does not exist", - __FUNCTION__, key_str->val); - msgpack_serialize_string(buf, key_str->val, key_str->len); + __FUNCTION__, Z_STRVAL_P(value)); + msgpack_serialize_string(buf, Z_STRVAL_P(value), Z_STRLEN_P(value)); msgpack_serialize_zval(buf, nvalp, var_hash TSRMLS_CC); } while (0); - } - else - { - msgpack_serialize_string(buf, key_str->val, key_str->len); + } else { + msgpack_serialize_string(buf, Z_STRVAL_P(value), Z_STRLEN_P(value)); msgpack_serialize_zval(buf, nvalp, var_hash TSRMLS_CC); } } @@ -329,14 +323,15 @@ inline static void msgpack_serialize_object( smart_string *buf, zval *val, HashTable *var_hash, char* class_name, uint32_t name_len, zend_bool incomplete_class TSRMLS_DC) { - zval *retval_ptr = NULL; + zval retval; zval fname; int res; zend_class_entry *ce = NULL; - zend_string *sleep_zstring = zend_string_init("__sleep", sizeof("__sleep")-1, 0); - if (Z_OBJ_P(val)->ce) - { + zend_string *sleep_zstring = zend_string_init("__sleep", sizeof("__sleep") - 1, 0); + ZVAL_STRING(&fname, "__sleep"); + + if (Z_OBJ_P(val)->ce) { ce = Z_OBJCE_P(val); } @@ -360,14 +355,11 @@ inline static void msgpack_serialize_object( msgpack_serialize_string(buf, (char *)ce->name, ce->name_length); msgpack_pack_raw(buf, serialized_length); msgpack_pack_raw_body(buf, serialized_data, serialized_length); - } - else - { + } else { msgpack_pack_nil(buf); } - if (serialized_data) - { + if (serialized_data) { efree(serialized_data); } @@ -376,39 +368,27 @@ inline static void msgpack_serialize_object( #endif if (ce && ce != PHP_IC_ENTRY && - zend_hash_exists(&ce->function_table, sleep_zstring)) - { - ZVAL_STR(&fname, sleep_zstring); - res = call_user_function_ex(CG(function_table), val, &fname, - retval_ptr, 0, 0, 1, NULL TSRMLS_CC); - if (res == SUCCESS && !EG(exception)) - { - if (retval_ptr) - { - if (HASH_OF(retval_ptr)) - { - msgpack_serialize_class( - buf, val, retval_ptr, var_hash, + zend_hash_exists(&ce->function_table, sleep_zstring)) { + res = call_user_function_ex(CG(function_table), val, &fname, &retval, 0, 0, 1, NULL); + + if (res == SUCCESS && !EG(exception)) { + if (HASH_OF(&retval)) { + msgpack_serialize_class( + buf, val, &retval, var_hash, class_name, name_len, incomplete_class TSRMLS_CC); - } - else - { - MSGPACK_NOTICE( + } else { + MSGPACK_NOTICE( "[msgpack] (%s) __sleep should return an array only " "containing the names of instance-variables " "to serialize", __FUNCTION__); - msgpack_pack_nil(buf); - } - zval_ptr_dtor(retval_ptr); + msgpack_pack_nil(buf); } + zval_ptr_dtor(&retval); return; } } - if (retval_ptr) - { - zval_ptr_dtor(retval_ptr); - } + zval_ptr_dtor(&retval); msgpack_serialize_array( buf, val, var_hash, 1, From 85f58f4a91a858a22e1a87e6c84315c28867bf52 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Fri, 24 Apr 2015 21:02:49 +0000 Subject: [PATCH 33/75] Properly call __wakeup during unpacking --- msgpack_unpack.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index bbe2dc4..187a914 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -743,17 +743,13 @@ int msgpack_unserialize_map_item( if (MSGPACK_G(php_only) && Z_TYPE_P(*container) == IS_OBJECT && Z_OBJCE_P(*container) != PHP_IC_ENTRY && - - zend_hash_exists(&Z_OBJ_P(*container)->ce->function_table, zend_string_init("__wakeup", sizeof("__wakeup") + 1, 1))) + zend_hash_exists(&Z_OBJ_P(*container)->ce->function_table, zend_string_init("__wakeup", sizeof("__wakeup") - 1, 0))) { - zval *f, *h = NULL; + zval f, h; + ZVAL_STRING(&f, "__wakeup"); - ZVAL_STRINGL(f, "__wakeup", sizeof("__wakeup") - 1); - call_user_function_ex( CG(function_table), *container, f, h, 0, 0, 1, NULL TSRMLS_CC); - if (h) - { - zval_ptr_dtor(h); - } + call_user_function_ex(CG(function_table), *container, &f, &h, 0, NULL, 1, NULL TSRMLS_CC); + zval_ptr_dtor(&h); } } From ea2d5be764979c8d63b19412faab74e19c6d1fa2 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sun, 3 May 2015 05:59:53 +0000 Subject: [PATCH 34/75] Update var_push/stack_push to use a var_entries where data is a zval[] instead of *zval[], following the current pattern in ext/standard/var_unserializer.re --- msgpack.c | 12 +-- msgpack_pack.c | 3 +- msgpack_unpack.c | 194 ++++++++++------------------------------------- msgpack_unpack.h | 2 +- 4 files changed, 49 insertions(+), 162 deletions(-) diff --git a/msgpack.c b/msgpack.c index 42debdc..bd08aba 100644 --- a/msgpack.c +++ b/msgpack.c @@ -182,7 +182,7 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) ret = template_execute(&mp, (char *)val, (size_t)vallen, &off); if (ret == MSGPACK_UNPACK_EXTRA_BYTES || ret == MSGPACK_UNPACK_SUCCESS) { - msgpack_unserialize_var_destroy(&var_hash, 0); + msgpack_unserialize_var_destroy(&var_hash, 0, tmp); ZEND_HASH_FOREACH_KEY_VAL(HASH_OF(tmp), key_long, key_str, value) { if (key_str) { @@ -194,7 +194,7 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) } ZEND_HASH_FOREACH_END(); } else { - msgpack_unserialize_var_destroy(&var_hash, 1); + msgpack_unserialize_var_destroy(&var_hash, 1, tmp); } zval_ptr_dtor(tmp); @@ -241,18 +241,18 @@ PHP_MSGPACK_API void php_msgpack_unserialize( case MSGPACK_UNPACK_PARSE_ERROR: zval_dtor(return_value); ZVAL_FALSE(return_value); - msgpack_unserialize_var_destroy(&var_hash, 1); + msgpack_unserialize_var_destroy(&var_hash, 1, return_value); MSGPACK_WARNING("[msgpack] (%s) Parse error", __FUNCTION__); break; case MSGPACK_UNPACK_CONTINUE: - msgpack_unserialize_var_destroy(&var_hash, 0); + msgpack_unserialize_var_destroy(&var_hash, 0, return_value); MSGPACK_WARNING( "[msgpack] (%s) Insufficient data for unserializing", __FUNCTION__); break; case MSGPACK_UNPACK_EXTRA_BYTES: case MSGPACK_UNPACK_SUCCESS: - msgpack_unserialize_var_destroy(&var_hash, 0); + msgpack_unserialize_var_destroy(&var_hash, 0, return_value); if (off < str_len) { MSGPACK_WARNING("[msgpack] (%s) Extra bytes", __FUNCTION__); } @@ -260,7 +260,7 @@ PHP_MSGPACK_API void php_msgpack_unserialize( default: zval_dtor(return_value); ZVAL_FALSE(return_value); - msgpack_unserialize_var_destroy(&var_hash, 0); + msgpack_unserialize_var_destroy(&var_hash, 0, return_value); MSGPACK_WARNING("[msgpack] (%s) Unknown result", __FUNCTION__); break; } diff --git a/msgpack_pack.c b/msgpack_pack.c index 656852a..cc1d935 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -65,7 +65,7 @@ inline static int msgpack_var_add( return FAILURE; } - zstring = zend_string_init(p, len, 0); + zstring = zend_string_init(p, len, 0); if (var_old && (var_old = zend_hash_find(var_hash, zstring)) != NULL) { if (!Z_ISREF_P(var)) { zend_hash_next_index_insert(var_hash, NULL); @@ -75,6 +75,7 @@ inline static int msgpack_var_add( ZVAL_LONG(&zv, zend_hash_num_elements(var_hash) + 1); zend_hash_add(var_hash, zstring, &zv); + zend_string_release(zstring); return SUCCESS; } diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 187a914..4ef3c85 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -12,35 +12,11 @@ typedef struct { - zval *data[VAR_ENTRIES_MAX]; + zval data[VAR_ENTRIES_MAX]; long used_slots; void *next; } var_entries; -#define ALLOC_ZVAL(z) \ - (z) = (zval *) emalloc(sizeof(zval)) - -#define ALLOC_INIT_ZVAL(zp) \ - ALLOC_ZVAL(zp); - -#define MSGPACK_UNSERIALIZE_ALLOC_STACK(_unpack) \ - if (_unpack->deps <= 0) { \ - *obj = _unpack->retval; \ - msgpack_stack_push(_unpack->var_hash, obj, 0); \ - } else { \ - ALLOC_INIT_ZVAL(*obj); \ - msgpack_stack_push(_unpack->var_hash, obj, 1); \ - } - -#define MSGPACK_UNSERIALIZE_ALLOC_VALUE(_unpack) \ - if (_unpack->deps <= 0) { \ - *obj = _unpack->retval; \ - msgpack_var_push(_unpack->var_hash, obj); \ - } else { \ - ALLOC_INIT_ZVAL(*obj); \ - msgpack_var_push(_unpack->var_hash, obj); \ - } - #define MSGPACK_UNSERIALIZE_FINISH_ITEM(_unpack, _count) \ msgpack_stack_pop(_unpack->var_hash, _count); \ _unpack->stack[_unpack->deps-1]--; \ @@ -58,36 +34,30 @@ inline static void msgpack_var_push( { var_entries *var_hash, *prev = NULL; - if (!var_hashx) - { + if (!var_hashx) { return; } var_hash = var_hashx->first; - while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) - { + while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) { prev = var_hash; var_hash = var_hash->next; } - if (!var_hash) - { + if (!var_hash) { var_hash = emalloc(sizeof(var_entries)); var_hash->used_slots = 0; var_hash->next = 0; - if (!var_hashx->first) - { + if (!var_hashx->first) { var_hashx->first = var_hash; - } - else - { + } else { prev->next = var_hash; } } - var_hash->data[var_hash->used_slots++] = *rval; + *rval = &var_hash->data[var_hash->used_slots++]; } inline static int msgpack_var_access( @@ -112,55 +82,12 @@ inline static int msgpack_var_access( return !SUCCESS; } - *store = &var_hash->data[id]; + // TODO + //*store = &var_hash->data[id]; return SUCCESS; } -inline static void msgpack_stack_push( - msgpack_unserialize_data_t *var_hashx, zval **rval, zend_bool save) -{ - var_entries *var_hash, *prev = NULL; - - if (!var_hashx) - { - return; - } - - var_hash = var_hashx->first_dtor; - - 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_dtor) - { - var_hashx->first_dtor = var_hash; - } - else - { - prev->next = var_hash; - } - } - - if (save) - { - var_hash->data[var_hash->used_slots++] = *rval; - } - else - { - var_hash->data[var_hash->used_slots++] = NULL; - } -} - inline static void msgpack_stack_pop( msgpack_unserialize_data_t *var_hashx, long count) { @@ -177,18 +104,16 @@ inline static void msgpack_stack_pop( return; } - for (i = count; i > 0; i--) - { + for (i = count; i > 0; i--) { var_hash->used_slots--; - if (var_hash->used_slots < 0) - { + if (var_hash->used_slots < 0) { var_hash->used_slots = 0; - var_hash->data[var_hash->used_slots] = NULL; + // TODO + //var_hash->data[var_hash->used_slots] = NULL; break; - } - else - { - var_hash->data[var_hash->used_slots] = NULL; + } else { + // TODO + //var_hash->data[var_hash->used_slots] = NULL; } } } @@ -286,7 +211,6 @@ void msgpack_serialize_var_init(msgpack_serialize_data_t *var_hash) void msgpack_serialize_var_destroy(msgpack_serialize_data_t *var_hash) { HashTable **var_hash_ptr = (HashTable **)var_hash; - TSRMLS_FETCH(); --MSGPACK_G(serialize).level; if (!MSGPACK_G(serialize).level) { @@ -302,25 +226,15 @@ void msgpack_unserialize_var_init(msgpack_unserialize_data_t *var_hashx) } void msgpack_unserialize_var_destroy( - msgpack_unserialize_data_t *var_hashx, zend_bool err) + msgpack_unserialize_data_t *var_hashx, zend_bool err, zval *return_value) { + // TODO void *next; long i; var_entries *var_hash = var_hashx->first; - while (var_hash) - { - if (err) - { - for (i = var_hash->used_slots - 1; i > 0; i--) - { - if (var_hash->data[i]) - { - //zval_ptr_dtor(&var_hash->data[i]); - //var_hash->data[i] = NULL; - } - } - } + if (var_hash) { + ZVAL_COPY(return_value, &var_hash->data[0]); next = var_hash->next; efree(var_hash); @@ -329,17 +243,7 @@ void msgpack_unserialize_var_destroy( var_hash = var_hashx->first_dtor; - while (var_hash) - { - for (i = var_hash->used_slots - 1; i >= 0; i--) - { - if (var_hash->data[i]) - { - zval_ptr_dtor(var_hash->data[i]); - var_hash->data[i] = NULL; - } - } - + if (var_hash) { next = var_hash->next; efree(var_hash); var_hash = next; @@ -355,8 +259,7 @@ void msgpack_unserialize_init(msgpack_unserialize_data *unpack) int msgpack_unserialize_uint8( msgpack_unserialize_data *unpack, uint8_t data, zval **obj) { - MSGPACK_UNSERIALIZE_ALLOC_STACK(unpack); - + msgpack_var_push(unpack->var_hash, obj); ZVAL_LONG(*obj, data); return 0; @@ -365,8 +268,8 @@ int msgpack_unserialize_uint8( int msgpack_unserialize_uint16( msgpack_unserialize_data *unpack, uint16_t data, zval **obj) { - MSGPACK_UNSERIALIZE_ALLOC_STACK(unpack); + msgpack_var_push(unpack->var_hash, obj); ZVAL_LONG(*obj, data); return 0; @@ -375,8 +278,7 @@ int msgpack_unserialize_uint16( int msgpack_unserialize_uint32( msgpack_unserialize_data *unpack, uint32_t data, zval **obj) { - MSGPACK_UNSERIALIZE_ALLOC_STACK(unpack); - + msgpack_var_push(unpack->var_hash, obj); ZVAL_LONG(*obj, data); return 0; @@ -385,8 +287,7 @@ int msgpack_unserialize_uint32( int msgpack_unserialize_uint64( msgpack_unserialize_data *unpack, uint64_t data, zval **obj) { - MSGPACK_UNSERIALIZE_ALLOC_STACK(unpack); - + msgpack_var_push(unpack->var_hash, obj); ZVAL_LONG(*obj, data); return 0; @@ -395,8 +296,7 @@ int msgpack_unserialize_uint64( int msgpack_unserialize_int8( msgpack_unserialize_data *unpack, int8_t data, zval **obj) { - MSGPACK_UNSERIALIZE_ALLOC_STACK(unpack); - + msgpack_var_push(unpack->var_hash, obj); ZVAL_LONG(*obj, data); return 0; @@ -405,8 +305,7 @@ int msgpack_unserialize_int8( int msgpack_unserialize_int16( msgpack_unserialize_data *unpack, int16_t data, zval **obj) { - MSGPACK_UNSERIALIZE_ALLOC_STACK(unpack); - + msgpack_var_push(unpack->var_hash, obj); ZVAL_LONG(*obj, data); return 0; @@ -415,8 +314,7 @@ int msgpack_unserialize_int16( int msgpack_unserialize_int32( msgpack_unserialize_data *unpack, int32_t data, zval **obj) { - MSGPACK_UNSERIALIZE_ALLOC_STACK(unpack); - + msgpack_var_push(unpack->var_hash, obj); ZVAL_LONG(*obj, data); return 0; @@ -425,8 +323,7 @@ int msgpack_unserialize_int32( int msgpack_unserialize_int64( msgpack_unserialize_data *unpack, int64_t data, zval **obj) { - MSGPACK_UNSERIALIZE_ALLOC_STACK(unpack); - + msgpack_var_push(unpack->var_hash, obj); ZVAL_LONG(*obj, data); return 0; @@ -435,8 +332,7 @@ int msgpack_unserialize_int64( int msgpack_unserialize_float( msgpack_unserialize_data *unpack, float data, zval **obj) { - MSGPACK_UNSERIALIZE_ALLOC_STACK(unpack); - + msgpack_var_push(unpack->var_hash, obj); ZVAL_DOUBLE(*obj, data); return 0; @@ -445,8 +341,7 @@ int msgpack_unserialize_float( int msgpack_unserialize_double( msgpack_unserialize_data *unpack, double data, zval **obj) { - MSGPACK_UNSERIALIZE_ALLOC_STACK(unpack); - + msgpack_var_push(unpack->var_hash, obj); ZVAL_DOUBLE(*obj, data); return 0; @@ -454,8 +349,7 @@ int msgpack_unserialize_double( int msgpack_unserialize_nil(msgpack_unserialize_data *unpack, zval **obj) { - MSGPACK_UNSERIALIZE_ALLOC_STACK(unpack); - + msgpack_var_push(unpack->var_hash, obj); ZVAL_NULL(*obj); return 0; @@ -463,8 +357,7 @@ int msgpack_unserialize_nil(msgpack_unserialize_data *unpack, zval **obj) int msgpack_unserialize_true(msgpack_unserialize_data *unpack, zval **obj) { - MSGPACK_UNSERIALIZE_ALLOC_STACK(unpack); - + msgpack_var_push(unpack->var_hash, obj); ZVAL_BOOL(*obj, 1); return 0; @@ -472,8 +365,7 @@ int msgpack_unserialize_true(msgpack_unserialize_data *unpack, zval **obj) int msgpack_unserialize_false(msgpack_unserialize_data *unpack, zval **obj) { - MSGPACK_UNSERIALIZE_ALLOC_STACK(unpack); - + msgpack_var_push(unpack->var_hash, obj); ZVAL_BOOL(*obj, 0); return 0; @@ -483,14 +375,10 @@ int msgpack_unserialize_raw( msgpack_unserialize_data *unpack, const char* base, const char* data, unsigned int len, zval **obj) { - MSGPACK_UNSERIALIZE_ALLOC_STACK(unpack); - - if (len == 0) - { + msgpack_var_push(unpack->var_hash, obj); + if (len == 0) { ZVAL_STRINGL(*obj, "", 0); - } - else - { + } else { ZVAL_STRINGL(*obj, (char *)data, len); } @@ -500,8 +388,7 @@ int msgpack_unserialize_raw( int msgpack_unserialize_array( msgpack_unserialize_data *unpack, unsigned int count, zval **obj) { - MSGPACK_UNSERIALIZE_ALLOC_VALUE(unpack); - + msgpack_var_push(unpack->var_hash, obj); array_init(*obj); if (count) unpack->stack[unpack->deps++] = count; @@ -522,9 +409,7 @@ int msgpack_unserialize_array_item( int msgpack_unserialize_map( msgpack_unserialize_data *unpack, unsigned int count, zval **obj) { - TSRMLS_FETCH(); - MSGPACK_UNSERIALIZE_ALLOC_VALUE(unpack); - + msgpack_var_push(unpack->var_hash, obj); if (count) unpack->stack[unpack->deps++] = count; unpack->type = MSGPACK_SERIALIZE_TYPE_NONE; @@ -541,6 +426,7 @@ int msgpack_unserialize_map( } } + return 0; } diff --git a/msgpack_unpack.h b/msgpack_unpack.h index e140145..835d76d 100644 --- a/msgpack_unpack.h +++ b/msgpack_unpack.h @@ -30,7 +30,7 @@ void msgpack_serialize_var_init(msgpack_serialize_data_t *var_hash); void msgpack_serialize_var_destroy(msgpack_serialize_data_t *var_hash); void msgpack_unserialize_var_init(msgpack_unserialize_data_t *var_hashx); void msgpack_unserialize_var_destroy( - msgpack_unserialize_data_t *var_hashx, zend_bool err); + msgpack_unserialize_data_t *var_hashx, zend_bool err, zval *return_value); void msgpack_unserialize_init(msgpack_unserialize_data *unpack); From 76d5a8aecb9b14592148fc2ea4f44349bbd12493 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Tue, 5 May 2015 06:21:07 +0000 Subject: [PATCH 35/75] FIXME: Comment out the call_user_function_ex calls implemented via opcodes, still need to migrate --- msgpack_class.c | 10 +++++----- msgpack_convert.c | 2 +- msgpack_unpack.c | 12 ------------ 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/msgpack_class.c b/msgpack_class.c index 268a2db..ff24c1c 100644 --- a/msgpack_class.c +++ b/msgpack_class.c @@ -325,7 +325,7 @@ static ZEND_METHOD(msgpack, unpacker) object_init_ex(return_value, msgpack_unpacker_ce); - MSGPACK_METHOD1(msgpack_unpacker, __construct, &temp, return_value, opt); + //MSGPACK_METHOD1(msgpack_unpacker, __construct, &temp, return_value, opt); zval_ptr_dtor(opt); } @@ -371,7 +371,7 @@ static ZEND_METHOD(msgpack_unpacker, __destruct) zval_ptr_dtor(unpacker->retval); } - msgpack_unserialize_var_destroy(&unpacker->var_hash, unpacker->error); + msgpack_unserialize_var_destroy(&unpacker->var_hash, unpacker->error, unpacker->retval); } static ZEND_METHOD(msgpack_unpacker, setOption) @@ -472,7 +472,7 @@ static ZEND_METHOD(msgpack_unpacker, execute) { zval_ptr_dtor(unpacker->retval); - msgpack_unserialize_var_destroy(&unpacker->var_hash, unpacker->error); + msgpack_unserialize_var_destroy(&unpacker->var_hash, unpacker->error, unpacker->retval); unpacker->error = 0; zval zv; @@ -549,7 +549,7 @@ static ZEND_METHOD(msgpack_unpacker, data) } } - MSGPACK_METHOD(msgpack_unpacker, reset, NULL, getThis()); + //MSGPACK_METHOD(msgpack_unpacker, reset, NULL, getThis()); return; } @@ -589,7 +589,7 @@ static ZEND_METHOD(msgpack_unpacker, reset) unpacker->retval = NULL; } - msgpack_unserialize_var_destroy(&unpacker->var_hash, unpacker->error); + msgpack_unserialize_var_destroy(&unpacker->var_hash, unpacker->error, unpacker->retval); unpacker->error = 0; diff --git a/msgpack_convert.c b/msgpack_convert.c index eefd5ad..6c09db6 100644 --- a/msgpack_convert.c +++ b/msgpack_convert.c @@ -275,7 +275,7 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) continue; } else if (key_long) { zval *aryval, *rv; - MSGPACK_CONVERT_COPY_ZVAL(aryval, data); + //MSGPACK_CONVERT_COPY_ZVAL(aryval, data); if (convert_function) { if (convert_function(rv, data, &aryval) != SUCCESS) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 4ef3c85..e75bcc4 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -228,26 +228,15 @@ void msgpack_unserialize_var_init(msgpack_unserialize_data_t *var_hashx) void msgpack_unserialize_var_destroy( msgpack_unserialize_data_t *var_hashx, zend_bool err, zval *return_value) { - // TODO void *next; long i; var_entries *var_hash = var_hashx->first; if (var_hash) { ZVAL_COPY(return_value, &var_hash->data[0]); - - next = var_hash->next; efree(var_hash); - var_hash = next; } - var_hash = var_hashx->first_dtor; - - if (var_hash) { - next = var_hash->next; - efree(var_hash); - var_hash = next; - } } void msgpack_unserialize_init(msgpack_unserialize_data *unpack) @@ -434,7 +423,6 @@ int msgpack_unserialize_map_item( msgpack_unserialize_data *unpack, zval **container, zval *key, zval *val) { long deps; - TSRMLS_FETCH(); if (MSGPACK_G(php_only)) { From c4baa8eff9f315661b09fffccbbfd4c47b88044c Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Tue, 5 May 2015 14:39:21 +0000 Subject: [PATCH 36/75] Add commented out loop over var_hash for freeing after serialization --- msgpack_unpack.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index e75bcc4..ee058b5 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -233,8 +233,11 @@ void msgpack_unserialize_var_destroy( var_entries *var_hash = var_hashx->first; if (var_hash) { - ZVAL_COPY(return_value, &var_hash->data[0]); - efree(var_hash); + ZVAL_DUP(return_value, &var_hash->data[0]); + for (i = var_hash->used_slots - 1; i >= 0; i--) { + //zval_ptr_dtor(&var_hash->data[i]); + } + //efree(var_hash); } } From 4e19afa1a20ea11ab814b5f62c53b9cb6b08123f Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Thu, 7 May 2015 03:50:06 +0000 Subject: [PATCH 37/75] Update msgpack_unserialize_class to use call_user_function_ex correctly --- msgpack_unpack.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index ee058b5..fab5508 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -123,7 +123,7 @@ inline static zend_class_entry* msgpack_unserialize_class( { zend_class_entry *ce; zend_bool incomplete_class = 0; - zval *user_func, *retval_ptr, args[1], *arg_func_name; + zval user_func, retval, args[1], arg_func_name; TSRMLS_FETCH(); do @@ -143,23 +143,19 @@ inline static zend_class_entry* msgpack_unserialize_class( } /* Call unserialize callback */ - ZVAL_STRING(user_func, PG(unserialize_callback_func)); - args[0] = *arg_func_name; - ZVAL_STRING(arg_func_name, class_name); - if (call_user_function_ex(CG(function_table), NULL, user_func, retval_ptr, 1, args, 0, NULL TSRMLS_CC) != SUCCESS) + ZVAL_STRING(&user_func, PG(unserialize_callback_func)); + ZVAL_STRING(&arg_func_name, class_name); + + args[0] = arg_func_name; + if (call_user_function_ex(CG(function_table), NULL, &user_func, &retval, 1, args, 0, NULL) != SUCCESS) { MSGPACK_WARNING("[msgpack] (%s) defined (%s) but not found", __FUNCTION__, class_name); 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 ((ce = zend_lookup_class(zend_string_init(class_name, name_len, 0))) == NULL) { @@ -170,14 +166,10 @@ inline static zend_class_entry* msgpack_unserialize_class( incomplete_class = 1; ce = PHP_IC_ENTRY; } - - zval_ptr_dtor(user_func); - zval_ptr_dtor(arg_func_name); } while(0); - if (EG(exception)) - { + if (EG(exception)) { MSGPACK_WARNING("[msgpack] (%s) Exception error", __FUNCTION__); return NULL; } From 51960ae97630fd9098e224fcb7abd885cdafab63 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Thu, 7 May 2015 04:29:27 +0000 Subject: [PATCH 38/75] Update ZEND_METHOD(msgpack_unpacker, feed) to use a zend_string for zend_parse_parameters instead of val+len --- msgpack_class.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/msgpack_class.c b/msgpack_class.c index ff24c1c..4aef057 100644 --- a/msgpack_class.c +++ b/msgpack_class.c @@ -405,22 +405,18 @@ static ZEND_METHOD(msgpack_unpacker, setOption) static ZEND_METHOD(msgpack_unpacker, feed) { - char *str; - int str_len; + zend_string *str; php_msgpack_unpacker_t *unpacker = Z_MSGPACK_UNPACKER_P(getThis()); - if (zend_parse_parameters( - ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) - { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S", &str) == FAILURE) { return; } - if (!str_len) - { + if (!str) { RETURN_FALSE; } - smart_string_appendl(&unpacker->buffer, str, str_len); + smart_string_appendl(&unpacker->buffer, str->val, str->len); RETURN_TRUE; } From 3e67e92d25793cbb677c31756025132ca99ecf33 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Thu, 7 May 2015 07:41:40 +0000 Subject: [PATCH 39/75] When updating a class in msgpack_unserialize_map_item call zend_update_property to update a class instead of zend_symtable_update, which would cause undefined behavior --- msgpack_unpack.c | 76 +++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index fab5508..06f9cc9 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -556,48 +556,50 @@ int msgpack_unserialize_map_item( array_init(*container); } - switch (Z_TYPE_P(key)) - { - case IS_LONG: - if ((val = zend_hash_index_update(HASH_OF(*container), Z_LVAL_P(key), val)) == NULL) { - zval_ptr_dtor(val); - MSGPACK_WARNING( - "[msgpack] (%s) illegal offset type, skip this decoding", - __FUNCTION__); - } - zval_ptr_dtor(key); - break; - case IS_STRING: - - if ((val = zend_symtable_update(HASH_OF(*container), zend_string_init(Z_STRVAL_P(key), Z_STRLEN_P(key), 0), val)) == NULL) { - zval_ptr_dtor(val); - MSGPACK_WARNING( - "[msgpack] (%s) illegal offset type, skip this decoding", - __FUNCTION__); - } - zval_ptr_dtor(key); - break; - default: - MSGPACK_WARNING("[msgpack] (%s) illegal key type", __FUNCTION__); - - if (MSGPACK_G(illegal_key_insert)) - { - if ((key = zend_hash_next_index_insert(HASH_OF(*container), key)) == NULL) { - zval_ptr_dtor(val); - } - if ((val = zend_hash_next_index_insert(HASH_OF(*container), val)) == NULL) { + if (Z_TYPE_P(*container) == IS_OBJECT) { + zend_update_property(Z_OBJ_P(*container)->ce, *container, Z_STRVAL_P(key), Z_STRLEN_P(key), val); + } else { + switch (Z_TYPE_P(key)) { + case IS_LONG: + if ((val = zend_hash_index_update(HASH_OF(*container), Z_LVAL_P(key), val)) == NULL) { zval_ptr_dtor(val); + MSGPACK_WARNING( + "[msgpack] (%s) illegal offset type, skip this decoding", + __FUNCTION__); } - } - else - { - convert_to_string(key); - if ((zend_symtable_update(HASH_OF(*container), zend_string_init(Z_STRVAL_P(key), Z_STRLEN_P(key), 0), val)) == NULL) { + zval_ptr_dtor(key); + break; + case IS_STRING: + if ((val = zend_symtable_update(HASH_OF(*container), zend_string_init(Z_STRVAL_P(key), Z_STRLEN_P(key), 0), val)) == NULL) { zval_ptr_dtor(val); + MSGPACK_WARNING( + "[msgpack] (%s) illegal offset type, skip this decoding", + __FUNCTION__); } zval_ptr_dtor(key); - } - break; + break; + default: + MSGPACK_WARNING("[msgpack] (%s) illegal key type", __FUNCTION__); + + if (MSGPACK_G(illegal_key_insert)) + { + if ((key = zend_hash_next_index_insert(HASH_OF(*container), key)) == NULL) { + zval_ptr_dtor(val); + } + if ((val = zend_hash_next_index_insert(HASH_OF(*container), val)) == NULL) { + zval_ptr_dtor(val); + } + } + else + { + convert_to_string(key); + if ((zend_symtable_update(HASH_OF(*container), zend_string_init(Z_STRVAL_P(key), Z_STRLEN_P(key), 0), val)) == NULL) { + zval_ptr_dtor(val); + } + zval_ptr_dtor(key); + } + break; + } } msgpack_stack_pop(unpack->var_hash, 2); From 591b3b3647448fbe5b1a51fab755f4029e6f02eb Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sat, 9 May 2015 09:15:41 +0000 Subject: [PATCH 40/75] Update msgpack_unserialize_map_item to properly handle adding elements to a map that is a reference --- msgpack_unpack.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 06f9cc9..7277fa9 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -551,8 +551,13 @@ int msgpack_unserialize_map_item( } } - if (Z_TYPE_P(*container) != IS_ARRAY && Z_TYPE_P(*container) != IS_OBJECT) - { + int container_is_ref = 0; + if (Z_ISREF_P(*container)) { + container_is_ref = 1; + ZVAL_DEREF(*container); + } + + if (Z_TYPE_P(*container) != IS_ARRAY && Z_TYPE_P(*container) != IS_OBJECT) { array_init(*container); } @@ -602,6 +607,11 @@ int msgpack_unserialize_map_item( } } + if (container_is_ref) { + ZVAL_MAKE_REF(*container); + Z_TRY_ADDREF_P(*container); + } + msgpack_stack_pop(unpack->var_hash, 2); deps = unpack->deps - 1; From 0cd9aedfa33831e04c0975dc2b6215af853d7578 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sat, 9 May 2015 09:17:22 +0000 Subject: [PATCH 41/75] Update msgpack_var_add to return to the index of an already serialized object as a zval instead of a ulong --- msgpack_pack.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index cc1d935..0a76477 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -42,7 +42,7 @@ inline static int msgpack_check_ht_is_map(zval *array) } inline static int msgpack_var_add( - HashTable *var_hash, zval *var, void *var_old TSRMLS_DC) + HashTable *var_hash, zval *var, zval **var_old TSRMLS_DC) { char id[32], *p; int len; @@ -66,9 +66,10 @@ inline static int msgpack_var_add( } zstring = zend_string_init(p, len, 0); - if (var_old && (var_old = zend_hash_find(var_hash, zstring)) != NULL) { + if (var_old && (*var_old = zend_hash_find(var_hash, zstring)) != NULL) { if (!Z_ISREF_P(var)) { - zend_hash_next_index_insert(var_hash, NULL); + ZVAL_LONG(&zv, -1); + zend_hash_next_index_insert(var_hash, &zv); } return FAILURE; } @@ -270,19 +271,17 @@ inline static void msgpack_serialize_array( msgpack_pack_long(buf, key_long); } - if ((Z_TYPE_P(Z_REF_AWARE_P(value)) == IS_ARRAY && Z_ARRVAL_P(value)->u.v.nApplyCount > 1)) { + if ((Z_TYPE_P(Z_REF_AWARE_P(value)) == IS_ARRAY && Z_ARRVAL_P(Z_REF_AWARE_P(value))->u.v.nApplyCount > 1)) { msgpack_pack_nil(buf); } else { - if (Z_TYPE_P(Z_REF_AWARE_P(value)) == IS_ARRAY) - { - Z_ARRVAL_P(value)->u.v.nApplyCount++; + if (Z_TYPE_P(Z_REF_AWARE_P(value)) == IS_ARRAY) { + Z_ARRVAL_P(Z_REF_AWARE_P(value))->u.v.nApplyCount++; } msgpack_serialize_zval(buf, value, var_hash TSRMLS_CC); - if (Z_TYPE_P(Z_REF_AWARE_P(value)) == IS_ARRAY) - { - Z_ARRVAL_P(value)->u.v.nApplyCount--; + if (Z_TYPE_P(Z_REF_AWARE_P(value)) == IS_ARRAY) { + Z_ARRVAL_P(Z_REF_AWARE_P(value))->u.v.nApplyCount--; } } } ZEND_HASH_FOREACH_END(); @@ -399,7 +398,7 @@ inline static void msgpack_serialize_object( void msgpack_serialize_zval( smart_string *buf, zval *val, HashTable *var_hash TSRMLS_DC) { - ulong *var_already; + zval *var_already; if (Z_TYPE_P(val) == IS_INDIRECT) { val = Z_INDIRECT_P(val); @@ -408,7 +407,7 @@ void msgpack_serialize_zval( if (MSGPACK_G(php_only) && var_hash && msgpack_var_add( - var_hash, val, (void *)&var_already TSRMLS_CC) == FAILURE) + var_hash, val, &var_already TSRMLS_CC) == FAILURE) { if (Z_ISREF_P(val)) { @@ -420,7 +419,7 @@ void msgpack_serialize_zval( msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_RECURSIVE); msgpack_pack_long(buf, 0); - msgpack_pack_long(buf, *var_already); + msgpack_pack_long(buf, Z_LVAL_P(var_already)); return; } @@ -432,7 +431,7 @@ void msgpack_serialize_zval( msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE); msgpack_pack_long(buf, 0); - msgpack_pack_long(buf, *var_already); + msgpack_pack_long(buf, Z_LVAL_P(var_already)); return; } @@ -445,7 +444,7 @@ void msgpack_serialize_zval( msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_OBJECT); msgpack_pack_long(buf, 0); - msgpack_pack_long(buf, *var_already); + msgpack_pack_long(buf, Z_LVAL_P(var_already)); return; } From 12c8a02ed8d23daf51bf2d381ea572db1f8a7e97 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sun, 10 May 2015 05:05:45 +0000 Subject: [PATCH 42/75] Update msgpack_unserialize_map_item to unmangle the property key set by zend_mangle_propery_name, since we now use zend_update_property instead of zend_symtable_update --- msgpack_pack.c | 2 -- msgpack_unpack.c | 11 ++++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index 0a76477..d019c05 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -388,8 +388,6 @@ inline static void msgpack_serialize_object( } } - zval_ptr_dtor(&retval); - msgpack_serialize_array( buf, val, var_hash, 1, class_name, name_len, incomplete_class TSRMLS_CC); diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 7277fa9..4b5cb81 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -124,12 +124,10 @@ inline static zend_class_entry* msgpack_unserialize_class( zend_class_entry *ce; zend_bool incomplete_class = 0; zval user_func, retval, args[1], arg_func_name; - TSRMLS_FETCH(); - do { /* Try to find class directly */ - if ((ce = zend_lookup_class(zend_string_init("Obj", name_len, 0))) != NULL) { + if ((ce = zend_lookup_class(zend_string_init(class_name, name_len, 0))) != NULL) { break; } @@ -561,8 +559,11 @@ int msgpack_unserialize_map_item( array_init(*container); } - if (Z_TYPE_P(*container) == IS_OBJECT) { - zend_update_property(Z_OBJ_P(*container)->ce, *container, Z_STRVAL_P(key), Z_STRLEN_P(key), val); + if (Z_TYPE_P(*container) == IS_OBJECT && false) { + const char *class_name, *prop_name; + size_t prop_len; + zend_unmangle_property_name_ex(zval_get_string(key), &class_name, &prop_name, &prop_len); + zend_update_property(Z_OBJ_P(*container)->ce, *container, prop_name, prop_len, val); } else { switch (Z_TYPE_P(key)) { case IS_LONG: From 70557c86c60624ebfcd1b496f298f8936007590d Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sun, 10 May 2015 05:06:51 +0000 Subject: [PATCH 43/75] Update msgpack_var_access to use a zval** instead of a zval*** when fetching a value, fixing the caller --- msgpack_pack.c | 19 ++++++++----------- msgpack_unpack.c | 31 ++++++++++--------------------- 2 files changed, 18 insertions(+), 32 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index d019c05..8275963 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -42,7 +42,7 @@ inline static int msgpack_check_ht_is_map(zval *array) } inline static int msgpack_var_add( - HashTable *var_hash, zval *var, zval **var_old TSRMLS_DC) + HashTable *var_hash, zval *var, zval **var_old) { char id[32], *p; int len; @@ -52,16 +52,14 @@ inline static int msgpack_var_add( if ((Z_TYPE_P(Z_REF_AWARE_P(var)) == IS_OBJECT) && Z_OBJ_P(var)->ce) { p = zend_print_long_to_buf( id + sizeof(id) - 1, - (((size_t)Z_OBJCE_P(var) << 5) - | ((size_t)Z_OBJCE_P(var) >> (sizeof(long) * 8 - 5))) - + (long)Z_OBJ_HANDLE_P(var)); + (((size_t)Z_OBJCE_P(Z_REF_AWARE_P(var)) << 5) + | ((size_t)Z_OBJCE_P(Z_REF_AWARE_P(var)) >> (sizeof(long) * 8 - 5))) + + (long)Z_OBJ_HANDLE_P(Z_REF_AWARE_P(var))); len = id + sizeof(id) - 1 - p; - } - else if (Z_TYPE_P(Z_REF_AWARE_P(var)) == IS_ARRAY) { - p = zend_print_long_to_buf(id + sizeof(id) - 1, (long)var); + } else if (Z_TYPE_P(Z_REF_AWARE_P(var)) == IS_ARRAY) { + p = zend_print_long_to_buf(id + sizeof(id) - 1, (long)Z_REF_AWARE_P(var)); len = id + sizeof(id) - 1 - p; - } - else { + } else { return FAILURE; } @@ -404,8 +402,7 @@ void msgpack_serialize_zval( if (MSGPACK_G(php_only) && var_hash && - msgpack_var_add( - var_hash, val, &var_already TSRMLS_CC) == FAILURE) + msgpack_var_add(var_hash, val, &var_already) == FAILURE) { if (Z_ISREF_P(val)) { diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 4b5cb81..3feb171 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -61,7 +61,7 @@ inline static void msgpack_var_push( } inline static int msgpack_var_access( - msgpack_unserialize_data_t *var_hashx, long id, zval ***store) + msgpack_unserialize_data_t *var_hashx, long id, zval **store) { var_entries *var_hash = var_hashx->first; @@ -82,8 +82,7 @@ inline static int msgpack_var_access( return !SUCCESS; } - // TODO - //*store = &var_hash->data[id]; + *store = &var_hash->data[id]; return SUCCESS; } @@ -506,39 +505,29 @@ int msgpack_unserialize_map_item( case MSGPACK_SERIALIZE_TYPE_OBJECT: case MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE: { - zval **rval; + zval *rval; int type = unpack->type; unpack->type = MSGPACK_SERIALIZE_TYPE_NONE; - if (msgpack_var_access( - unpack->var_hash, - Z_LVAL_P(val) - 1, &rval) != SUCCESS) - { - MSGPACK_WARNING( - "[msgpack] (%s) Invalid references value: %ld", + if (msgpack_var_access(unpack->var_hash, Z_LVAL_P(val) - 1, &rval) != SUCCESS) { + MSGPACK_WARNING("[msgpack] (%s) Invalid references value: %ld", __FUNCTION__, Z_LVAL_P(val) - 1); MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); - return 0; } - if (container != NULL) - { + if (container != NULL) { zval_ptr_dtor(*container); } - *container = *rval; - - Z_TRY_ADDREF_P(*container); + *container = rval; - if (type == MSGPACK_SERIALIZE_TYPE_OBJECT && Z_ISREF_P(*container)) - { + if (type == MSGPACK_SERIALIZE_TYPE_OBJECT && Z_ISREF_P(*container)) { ZVAL_UNREF(*container); } - else if (type == MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE && Z_ISREF_P(*container)) - { - ZVAL_UNREF(*container); + else if (type == MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE && Z_ISREF_P(*container)) { + ZVAL_MAKE_REF(*container); } MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); From 5306649470376f877afa309900ff3e8a236092b1 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Mon, 11 May 2015 04:03:02 +0000 Subject: [PATCH 44/75] Start fixing the compile time errors in msgpack_convert.c --- msgpack.c | 9 ++-- msgpack_class.c | 45 ++++++++---------- msgpack_convert.c | 117 +++++++++++++++++----------------------------- 3 files changed, 67 insertions(+), 104 deletions(-) diff --git a/msgpack.c b/msgpack.c index bd08aba..e18dd2e 100644 --- a/msgpack.c +++ b/msgpack.c @@ -296,13 +296,14 @@ static ZEND_FUNCTION(msgpack_unserialize) } if (object == NULL) { - php_msgpack_unserialize(return_value, str->val, str->len TSRMLS_CC); + php_msgpack_unserialize(return_value, str->val, str->len); } else { - zval *zv; + zval zv, *zv_p; + zv_p = &zv; - php_msgpack_unserialize(zv, str->val, str->len TSRMLS_CC); + php_msgpack_unserialize(&zv, str->val, str->len); - if (msgpack_convert_template(return_value, object, &zv) != SUCCESS) { + if (msgpack_convert_template(return_value, object, &zv_p) != SUCCESS) { RETURN_NULL(); } } diff --git a/msgpack_class.c b/msgpack_class.c index 4aef057..3e3084e 100644 --- a/msgpack_class.c +++ b/msgpack_class.c @@ -8,8 +8,8 @@ #include "msgpack_errors.h" typedef struct { - zend_object object; long php_only; + zend_object object; } php_msgpack_base_t; typedef struct { @@ -183,10 +183,12 @@ zend_object *php_msgpack_base_new(zend_class_entry *ce TSRMLS_DC) { intern->object.handlers = &msgpack_handlers; return &intern->object; } -static void php_msgpack_base_free(php_msgpack_base_t *base TSRMLS_DC) -{ - zend_object_std_dtor(&base->object TSRMLS_CC); - efree(base); +static void php_msgpack_base_free(zend_object *object) { + php_msgpack_base_t *intern = msgpack_base_fetch_object(object); + if (!intern) { + return; + } + zend_object_std_dtor(&intern->object); } zend_object *php_msgpack_unpacker_new(zend_class_entry *ce TSRMLS_DC) { @@ -277,39 +279,31 @@ static ZEND_METHOD(msgpack, pack) static ZEND_METHOD(msgpack, unpack) { - char *str; - int str_len; + zend_string *str; zval *object = NULL; int php_only = MSGPACK_G(php_only); php_msgpack_base_t *base = Z_MSGPACK_BASE_P(getThis()); - if (zend_parse_parameters( - ZEND_NUM_ARGS() TSRMLS_CC, "s|z", - &str, &str_len, &object) == FAILURE) - { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S|z", &str, &object) == FAILURE) { return; } - if (!str_len) - { - RETURN_FALSE; + if (!str) { + RETURN_NULL(); } MSGPACK_G(php_only) = base->php_only; - if (object == NULL) - { - php_msgpack_unserialize(return_value, str, str_len TSRMLS_CC); - } - else - { - zval *zv; + if (object == NULL) { + php_msgpack_unserialize(return_value, str->val, str->len TSRMLS_CC); + } else { + zval zv, *zv_p; + zv_p = &zv; - php_msgpack_unserialize(zv, str, str_len TSRMLS_CC); + php_msgpack_unserialize(&zv, str->val, str->len TSRMLS_CC); - if (msgpack_convert_template(return_value, object, &zv) != SUCCESS) - { - RETURN_FALSE; + if (msgpack_convert_template(return_value, object, &zv_p) != SUCCESS) { + RETURN_NULL(); } } @@ -608,6 +602,7 @@ void msgpack_init_class() msgpack_ce->create_object = php_msgpack_base_new; memcpy(&msgpack_handlers, zend_get_std_object_handlers(),sizeof msgpack_handlers); msgpack_handlers.offset = XtOffsetOf(php_msgpack_base_t, object); + msgpack_handlers.free_obj = php_msgpack_base_free; zend_declare_class_constant_long(msgpack_ce, ZEND_STRS("OPT_PHPONLY") - 1, MSGPACK_CLASS_OPT_PHPONLY TSRMLS_CC); diff --git a/msgpack_convert.c b/msgpack_convert.c index 6c09db6..e85cc1e 100644 --- a/msgpack_convert.c +++ b/msgpack_convert.c @@ -5,27 +5,21 @@ #include "msgpack_convert.h" #include "msgpack_errors.h" -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3) -# define Z_REFCOUNT_P(pz) ((pz)->refcount) -# define Z_SET_ISREF_P(pz) (pz)->is_ref = 1 -# define Z_UNSET_ISREF_P(pz) (pz)->is_ref = 0 -#endif - #define MSGPACK_CONVERT_COPY_ZVAL(_pz, _ppz) \ - ALLOC_INIT_ZVAL(_pz); \ - *(_pz) = **(_ppz); \ - if (PZVAL_IS_REF(*(_ppz))) { \ - if (Z_REFCOUNT_P(*(_ppz)) > 0) { \ - zval_copy_ctor(_pz); \ - } else { \ - FREE_ZVAL(*(_ppz)); \ - } \ - INIT_PZVAL(_pz); \ - Z_SET_ISREF_P(_pz); \ - } else { \ - zval_copy_ctor(_pz); \ - INIT_PZVAL(_pz); \ - } + //ALLOC_INIT_ZVAL(_pz); \ + //*(_pz) = **(_ppz); \ + //if (PZVAL_IS_REF(*(_ppz))) { \ + // if (Z_REFCOUNT_P(*(_ppz)) > 0) { \ + // zval_copy_ctor(_pz); \ + // } else { \ + // FREE_ZVAL(*(_ppz)); \ + // } \ + // INIT_PZVAL(_pz); \ + // Z_SET_ISREF_P(_pz); \ + //} else { \ + // zval_copy_ctor(_pz); \ + // INIT_PZVAL(_pz); \ + //} #define MSGPACK_CONVERT_UPDATE_PROPERTY(_ht, _key, _val, _var) \ if ((val = zend_symtable_update(_ht, _key, _val)) != NULL) { \ @@ -36,10 +30,7 @@ static inline int msgpack_convert_long_to_properties(HashTable *ht, HashTable **properties, uint key_index, zval *val, HashTable *var) { - TSRMLS_FETCH(); - - if (*properties != NULL) - { + if (*properties != NULL) { zend_string *key_str; ulong key_long; zval *data; @@ -49,8 +40,7 @@ static inline int msgpack_convert_long_to_properties(HashTable *ht, HashTable ** ZEND_HASH_FOREACH_KEY_VAL(ht, key_long, key_str, data) { if(key_str) { - switch (Z_TYPE_P(data)) - { + switch (Z_TYPE_P(data)) { case IS_ARRAY: { HashTable *dataht; @@ -78,7 +68,7 @@ static inline int msgpack_convert_long_to_properties(HashTable *ht, HashTable ** return FAILURE; } default: - return (zend_symtable_update(ht, key_str, tplval) != NULL); + return (zend_symtable_update(ht, key_str, val) != NULL); } } } ZEND_HASH_FOREACH_END(); @@ -275,7 +265,7 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) continue; } else if (key_long) { zval *aryval, *rv; - //MSGPACK_CONVERT_COPY_ZVAL(aryval, data); + MSGPACK_CONVERT_COPY_ZVAL(aryval, data); if (convert_function) { if (convert_function(rv, data, &aryval) != SUCCESS) @@ -332,12 +322,11 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) } int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { zend_class_entry *ce; - TSRMLS_FETCH(); - switch (Z_TYPE_P(tpl)) - { + switch (Z_TYPE_P(tpl)) { case IS_STRING: - if ((ce = zend_lookup_class(zend_string_init( Z_STRVAL_P(tpl), Z_STRLEN_P(tpl), 0))) != SUCCESS) { + + if ((ce = zend_lookup_class(zval_get_string(tpl))) == NULL) { MSGPACK_ERROR("[msgpack] (%s) Class '%s' not found", __FUNCTION__, Z_STRVAL_P(tpl)); return FAILURE; @@ -352,7 +341,7 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { return FAILURE; } - if (Z_TYPE_PP(value) == IS_OBJECT) { + if (Z_TYPE_P(*value) == IS_OBJECT) { zend_class_entry *vce; vce = Z_OBJ_P(tpl)->ce; @@ -368,13 +357,8 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { object_init_ex(return_value, ce); /* Run the constructor if there is one */ - if (ce->constructor - && (ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC)) - { - zval *retval_ptr = NULL; - zval *params = NULL; - zval function_name; - int num_args = 0; + if (ce->constructor && (ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC)) { + zval retval, params, function_name; zend_fcall_info fci; zend_fcall_info_cache fcc; @@ -383,39 +367,27 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { fci.function_name = function_name; fci.symbol_table = NULL; fci.object = Z_OBJ_P(return_value); - fci.retval = retval_ptr; - fci.param_count = num_args; - fci.params = params; + fci.retval = &retval; + fci.param_count = 0; + fci.params = ¶ms; fci.no_separation = 1; fcc.initialized = 1; fcc.function_handler = ce->constructor; fcc.calling_scope = EG(scope); fcc.called_scope = Z_OBJCE_P(return_value); + fcc.object = Z_OBJ_P(return_value); if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) { - if (params) { - efree(params); - } - if (retval_ptr) { - zval_ptr_dtor(retval_ptr); - } - MSGPACK_WARNING( "[msgpack] (%s) Invocation of %s's constructor failed", __FUNCTION__, ce->name); return FAILURE; } - if (retval_ptr) { - zval_ptr_dtor(retval_ptr); - } - if (params) { - efree(params); - } } - switch (Z_TYPE_PP(value)) + switch (Z_TYPE_P(*value)) { case IS_ARRAY: { @@ -472,10 +444,10 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { continue; } if (num_key) { - zval *val; - MSGPACK_CONVERT_COPY_ZVAL(val, &data); - if (msgpack_convert_long_to_properties(ret, &properties, num_key, val, var) != SUCCESS) { - zval_ptr_dtor(val); + zval val; + //MSGPACK_CONVERT_COPY_ZVAL(val, &data); + if (msgpack_convert_long_to_properties(ret, &properties, num_key, &val, var) != SUCCESS) { + zval_ptr_dtor(&val); MSGPACK_WARNING( "[msgpack] (%s) " "illegal offset type, skip this decoding", @@ -497,20 +469,18 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { } else { HashPosition valpos; int (*convert_function)(zval *, zval *, zval **) = NULL; - zval **arydata, *aryval; + zval **arydata, aryval, *aryval_p; + aryval_p = &aryval; ZEND_HASH_FOREACH_KEY_VAL(ret, num_key, str_key, data) { - - if (!num_key && !str_key) { - break; - } if (!data) { + if (!data) { MSGPACK_WARNING( "[msgpack] (%s) can't get data value by index", __FUNCTION__); return FAILURE; } - switch (Z_TYPE_PP(data)) + switch (Z_TYPE_P(data)) { case IS_ARRAY: convert_function = msgpack_convert_array; @@ -527,11 +497,10 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { MSGPACK_CONVERT_COPY_ZVAL(aryval, &data); if (convert_function) { - zval *rv; - ALLOC_INIT_ZVAL(rv); + zval rv; - if (convert_function(rv, data, &aryval) != SUCCESS) { - zval_ptr_dtor(aryval); + if (convert_function(&rv, data, &aryval_p) != SUCCESS) { + zval_ptr_dtor(&aryval); MSGPACK_WARNING( "[msgpack] (%s) " "convert failure in convert_object", @@ -539,9 +508,9 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { return FAILURE; } - zend_symtable_update( ret, str_key, rv); + zend_symtable_update(ret, str_key, &rv); } else { - zend_symtable_update(ret, str_key, aryval); + zend_symtable_update(ret, str_key, &aryval); } } ZEND_HASH_FOREACH_END(); @@ -575,8 +544,6 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { int msgpack_convert_template(zval *return_value, zval *tpl, zval **value) { - TSRMLS_FETCH(); - switch (Z_TYPE_P(tpl)) { case IS_ARRAY: From 414f72b7216e2ed907f108e858ee2d8aeeb114bd Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Mon, 11 May 2015 21:44:46 +0000 Subject: [PATCH 45/75] Accidently disabled branch used to update classes in msgpack_unserialize_map_item --- msgpack_unpack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 3feb171..8102fe7 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -548,7 +548,7 @@ int msgpack_unserialize_map_item( array_init(*container); } - if (Z_TYPE_P(*container) == IS_OBJECT && false) { + if (Z_TYPE_P(*container) == IS_OBJECT) { const char *class_name, *prop_name; size_t prop_len; zend_unmangle_property_name_ex(zval_get_string(key), &class_name, &prop_name, &prop_len); From 94d6f04c8990b01f7346e5496a3ac4832fdba98f Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Tue, 12 May 2015 04:48:51 +0000 Subject: [PATCH 46/75] MSGPACK_UNPACK_CONTINUE returned from template_execute means we should return false, fixes test 018 --- msgpack.c | 1 + 1 file changed, 1 insertion(+) diff --git a/msgpack.c b/msgpack.c index e18dd2e..90510bc 100644 --- a/msgpack.c +++ b/msgpack.c @@ -246,6 +246,7 @@ PHP_MSGPACK_API void php_msgpack_unserialize( break; case MSGPACK_UNPACK_CONTINUE: msgpack_unserialize_var_destroy(&var_hash, 0, return_value); + ZVAL_FALSE(return_value); MSGPACK_WARNING( "[msgpack] (%s) Insufficient data for unserializing", __FUNCTION__); From 60a3044c77e7d1f24217823545bb015d9604807f Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Tue, 12 May 2015 05:31:01 +0000 Subject: [PATCH 47/75] Bring back serializable interface support, was behind IFDEFs --- msgpack_pack.c | 15 ++++----------- msgpack_unpack.c | 10 ++-------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index 8275963..1ac57b6 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -333,24 +333,18 @@ inline static void msgpack_serialize_object( ce = Z_OBJCE_P(val); } -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0) - if (ce && ce->serialize != NULL) - { + if (ce && ce->serialize != NULL) { unsigned char *serialized_data = NULL; - uint32_t serialized_length; + size_t serialized_length; - if (ce->serialize( - val, &serialized_data, &serialized_length, - (zend_serialize_data *)var_hash TSRMLS_CC) == SUCCESS && - !EG(exception)) - { + if (ce->serialize(val, &serialized_data, &serialized_length, (zend_serialize_data *)var_hash) == SUCCESS && !EG(exception)) { /* has custom handler */ msgpack_pack_map(buf, 2); msgpack_pack_nil(buf); msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT); - msgpack_serialize_string(buf, (char *)ce->name, ce->name_length); + msgpack_serialize_string(buf, ce->name->val, ce->name->len); msgpack_pack_raw(buf, serialized_length); msgpack_pack_raw_body(buf, serialized_data, serialized_length); } else { @@ -363,7 +357,6 @@ inline static void msgpack_serialize_object( return; } -#endif if (ce && ce != PHP_IC_ENTRY && zend_hash_exists(&ce->function_table, sleep_zstring)) { diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 8102fe7..633d93b 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -479,10 +479,8 @@ int msgpack_unserialize_map_item( return 0; } -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0) /* implementing Serializable */ - if (ce->unserialize == NULL) - { + if (ce->unserialize == NULL) { MSGPACK_WARNING( "[msgpack] (%s) Class %s has no unserializer", __FUNCTION__, ce->name); @@ -492,11 +490,7 @@ int msgpack_unserialize_map_item( return 0; } - ce->unserialize( - container, ce, - (const unsigned char *)Z_STRVAL_P(val), - Z_STRLEN_P(val) + 1, NULL TSRMLS_CC); -#endif + ce->unserialize(*container, ce, Z_STRVAL_P(val), Z_STRLEN_P(val) + 1, NULL); MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); From 308e918ae38b7b24b7f35f54557f189cfe80d3cf Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Tue, 12 May 2015 05:39:42 +0000 Subject: [PATCH 48/75] msgpack_serialize_object is now ref aware --- msgpack_pack.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index 1ac57b6..66ac1d9 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -182,7 +182,7 @@ inline static void msgpack_serialize_array( if (object) { - ht = Z_OBJPROP_P(val); + ht = Z_OBJPROP_P(Z_REF_AWARE_P(val)); } else { @@ -321,16 +321,15 @@ inline static void msgpack_serialize_object( smart_string *buf, zval *val, HashTable *var_hash, char* class_name, uint32_t name_len, zend_bool incomplete_class TSRMLS_DC) { - zval retval; - zval fname; + zval retval, fname; int res; zend_class_entry *ce = NULL; zend_string *sleep_zstring = zend_string_init("__sleep", sizeof("__sleep") - 1, 0); ZVAL_STRING(&fname, "__sleep"); - if (Z_OBJ_P(val)->ce) { - ce = Z_OBJCE_P(val); + if (Z_OBJ_P(Z_REF_AWARE_P(val))->ce) { + ce = Z_OBJCE_P(Z_REF_AWARE_P(val)); } if (ce && ce->serialize != NULL) { @@ -466,7 +465,7 @@ void msgpack_serialize_zval( case IS_OBJECT: { PHP_CLASS_ATTRIBUTES; - PHP_SET_CLASS_ATTRIBUTES(val); + PHP_SET_CLASS_ATTRIBUTES(Z_REF_AWARE_P(val)); msgpack_serialize_object( buf, val, var_hash, class_name->val, class_name->len, From b265cd9e45dc31c01d76f1deb42d6cf07efc94be Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Thu, 14 May 2015 07:38:40 +0000 Subject: [PATCH 49/75] Bring back seperate stacks for dtor variables, still emalloc leaks --- msgpack_unpack.c | 188 ++++++++++++++++++++++++++--------------------- 1 file changed, 103 insertions(+), 85 deletions(-) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 633d93b..12ab139 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -10,13 +10,18 @@ #define VAR_ENTRIES_MAX 1024 -typedef struct -{ +typedef struct { zval data[VAR_ENTRIES_MAX]; long used_slots; void *next; } var_entries; +typedef struct { + zval data[VAR_ENTRIES_MAX]; + long used_slots; + void *next; +} var_entries_dtor; + #define MSGPACK_UNSERIALIZE_FINISH_ITEM(_unpack, _count) \ msgpack_stack_pop(_unpack->var_hash, _count); \ _unpack->stack[_unpack->deps-1]--; \ @@ -29,9 +34,7 @@ typedef struct zval_ptr_dtor(_val); \ MSGPACK_UNSERIALIZE_FINISH_ITEM(_unpack, 2); -inline static void msgpack_var_push( - msgpack_unserialize_data_t *var_hashx, zval **rval) -{ +inline static void msgpack_var_push(msgpack_unserialize_data_t *var_hashx, zval **rval) { var_entries *var_hash, *prev = NULL; if (!var_hashx) { @@ -60,25 +63,20 @@ inline static void msgpack_var_push( *rval = &var_hash->data[var_hash->used_slots++]; } -inline static int msgpack_var_access( - msgpack_unserialize_data_t *var_hashx, long id, zval **store) +inline static int msgpack_var_access(msgpack_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) - { + 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) - { + if (!var_hash) { return !SUCCESS; } - if (id < 0 || id >= var_hash->used_slots) - { + if (id < 0 || id >= var_hash->used_slots) { return !SUCCESS; } @@ -87,19 +85,47 @@ inline static int msgpack_var_access( return SUCCESS; } -inline static void msgpack_stack_pop( - msgpack_unserialize_data_t *var_hashx, long count) +inline static void msgpack_stack_push(msgpack_unserialize_data_t *var_hashx, zval **rval) +{ + var_entries_dtor *var_hash, *prev = NULL; + + if (!var_hashx) { + return; + } + + var_hash = var_hashx->first_dtor; + + 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_dtor)); + var_hash->used_slots = 0; + var_hash->next = 0; + + if (!var_hashx->first_dtor) { + var_hashx->first_dtor = var_hash; + } else { + prev->next = var_hash; + } + } + + *rval = &var_hash->data[var_hash->used_slots++]; +} + + +inline static void msgpack_stack_pop(msgpack_unserialize_data_t *var_hashx, long count) { long i; - var_entries *var_hash = var_hashx->first_dtor; + var_entries_dtor *var_hash = var_hashx->first_dtor; - while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) - { + while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) { var_hash = var_hash->next; } - if (!var_hash || count <= 0) - { + if (!var_hash || count <= 0) { return; } @@ -107,12 +133,7 @@ inline static void msgpack_stack_pop( var_hash->used_slots--; if (var_hash->used_slots < 0) { var_hash->used_slots = 0; - // TODO - //var_hash->data[var_hash->used_slots] = NULL; break; - } else { - // TODO - //var_hash->data[var_hash->used_slots] = NULL; } } } @@ -185,7 +206,6 @@ inline static zend_class_entry* msgpack_unserialize_class( void msgpack_serialize_var_init(msgpack_serialize_data_t *var_hash) { HashTable **var_hash_ptr = (HashTable **)var_hash; - TSRMLS_FETCH(); if (MSGPACK_G(serialize).level) { *var_hash_ptr = MSGPACK_G(serialize).var_hash; @@ -219,14 +239,32 @@ void msgpack_unserialize_var_destroy( { void *next; long i; - var_entries *var_hash = var_hashx->first; + zend_bool var_empty = 1; + var_entries *var_hash = var_hashx->first; if (var_hash) { - ZVAL_DUP(return_value, &var_hash->data[0]); - for (i = var_hash->used_slots - 1; i >= 0; i--) { - //zval_ptr_dtor(&var_hash->data[i]); - } - //efree(var_hash); + var_empty = 0; + ZVAL_COPY_VALUE(return_value, &var_hash->data[0]); + //zval_ptr_dtor(&var_hash->data[0]); + } + while (var_hash) { + next = var_hash->next; + //efree(var_hash); + var_hash = next; + } + + + var_entries_dtor *var_hash_dtor = var_hashx->first_dtor; + if (var_empty) { + ZVAL_DUP(return_value, &var_hash_dtor->data[0]); + } + while (var_hash_dtor) { + for (i = var_hash_dtor->used_slots - 1; i >= 0; i--) { + zval_ptr_dtor(&var_hash_dtor->data[i]); + } + next = var_hash_dtor->next; + efree(var_hash_dtor); + var_hash_dtor = next; } } @@ -240,7 +278,7 @@ void msgpack_unserialize_init(msgpack_unserialize_data *unpack) int msgpack_unserialize_uint8( msgpack_unserialize_data *unpack, uint8_t data, zval **obj) { - msgpack_var_push(unpack->var_hash, obj); + msgpack_stack_push(unpack->var_hash, obj); ZVAL_LONG(*obj, data); return 0; @@ -250,7 +288,7 @@ int msgpack_unserialize_uint16( msgpack_unserialize_data *unpack, uint16_t data, zval **obj) { - msgpack_var_push(unpack->var_hash, obj); + msgpack_stack_push(unpack->var_hash, obj); ZVAL_LONG(*obj, data); return 0; @@ -259,7 +297,7 @@ int msgpack_unserialize_uint16( int msgpack_unserialize_uint32( msgpack_unserialize_data *unpack, uint32_t data, zval **obj) { - msgpack_var_push(unpack->var_hash, obj); + msgpack_stack_push(unpack->var_hash, obj); ZVAL_LONG(*obj, data); return 0; @@ -268,7 +306,7 @@ int msgpack_unserialize_uint32( int msgpack_unserialize_uint64( msgpack_unserialize_data *unpack, uint64_t data, zval **obj) { - msgpack_var_push(unpack->var_hash, obj); + msgpack_stack_push(unpack->var_hash, obj); ZVAL_LONG(*obj, data); return 0; @@ -277,7 +315,7 @@ int msgpack_unserialize_uint64( int msgpack_unserialize_int8( msgpack_unserialize_data *unpack, int8_t data, zval **obj) { - msgpack_var_push(unpack->var_hash, obj); + msgpack_stack_push(unpack->var_hash, obj); ZVAL_LONG(*obj, data); return 0; @@ -286,7 +324,7 @@ int msgpack_unserialize_int8( int msgpack_unserialize_int16( msgpack_unserialize_data *unpack, int16_t data, zval **obj) { - msgpack_var_push(unpack->var_hash, obj); + msgpack_stack_push(unpack->var_hash, obj); ZVAL_LONG(*obj, data); return 0; @@ -295,7 +333,7 @@ int msgpack_unserialize_int16( int msgpack_unserialize_int32( msgpack_unserialize_data *unpack, int32_t data, zval **obj) { - msgpack_var_push(unpack->var_hash, obj); + msgpack_stack_push(unpack->var_hash, obj); ZVAL_LONG(*obj, data); return 0; @@ -304,7 +342,7 @@ int msgpack_unserialize_int32( int msgpack_unserialize_int64( msgpack_unserialize_data *unpack, int64_t data, zval **obj) { - msgpack_var_push(unpack->var_hash, obj); + msgpack_stack_push(unpack->var_hash, obj); ZVAL_LONG(*obj, data); return 0; @@ -313,7 +351,7 @@ int msgpack_unserialize_int64( int msgpack_unserialize_float( msgpack_unserialize_data *unpack, float data, zval **obj) { - msgpack_var_push(unpack->var_hash, obj); + msgpack_stack_push(unpack->var_hash, obj); ZVAL_DOUBLE(*obj, data); return 0; @@ -322,7 +360,7 @@ int msgpack_unserialize_float( int msgpack_unserialize_double( msgpack_unserialize_data *unpack, double data, zval **obj) { - msgpack_var_push(unpack->var_hash, obj); + msgpack_stack_push(unpack->var_hash, obj); ZVAL_DOUBLE(*obj, data); return 0; @@ -330,7 +368,7 @@ int msgpack_unserialize_double( int msgpack_unserialize_nil(msgpack_unserialize_data *unpack, zval **obj) { - msgpack_var_push(unpack->var_hash, obj); + msgpack_stack_push(unpack->var_hash, obj); ZVAL_NULL(*obj); return 0; @@ -338,7 +376,7 @@ int msgpack_unserialize_nil(msgpack_unserialize_data *unpack, zval **obj) int msgpack_unserialize_true(msgpack_unserialize_data *unpack, zval **obj) { - msgpack_var_push(unpack->var_hash, obj); + msgpack_stack_push(unpack->var_hash, obj); ZVAL_BOOL(*obj, 1); return 0; @@ -346,7 +384,7 @@ int msgpack_unserialize_true(msgpack_unserialize_data *unpack, zval **obj) int msgpack_unserialize_false(msgpack_unserialize_data *unpack, zval **obj) { - msgpack_var_push(unpack->var_hash, obj); + msgpack_stack_push(unpack->var_hash, obj); ZVAL_BOOL(*obj, 0); return 0; @@ -356,7 +394,7 @@ int msgpack_unserialize_raw( msgpack_unserialize_data *unpack, const char* base, const char* data, unsigned int len, zval **obj) { - msgpack_var_push(unpack->var_hash, obj); + msgpack_stack_push(unpack->var_hash, obj); if (len == 0) { ZVAL_STRINGL(*obj, "", 0); } else { @@ -395,19 +433,14 @@ int msgpack_unserialize_map( unpack->type = MSGPACK_SERIALIZE_TYPE_NONE; - if (count == 0) - { - if (MSGPACK_G(php_only)) - { + if (count == 0) { + if (MSGPACK_G(php_only)) { object_init(*obj); - } - else - { + } else { array_init(*obj); } } - return 0; } @@ -416,17 +449,13 @@ int msgpack_unserialize_map_item( { long deps; - if (MSGPACK_G(php_only)) - { + if (MSGPACK_G(php_only)) { zend_class_entry *ce; - if (Z_TYPE_P(key) == IS_NULL) - { + if (Z_TYPE_P(key) == IS_NULL) { unpack->type = MSGPACK_SERIALIZE_TYPE_NONE; - if (Z_TYPE_P(val) == IS_LONG) - { - switch (Z_LVAL_P(val)) - { + if (Z_TYPE_P(val) == IS_LONG) { + switch (Z_LVAL_P(val)) { case MSGPACK_SERIALIZE_TYPE_REFERENCE: ZVAL_MAKE_REF(*container); break; @@ -445,14 +474,11 @@ int msgpack_unserialize_map_item( default: break; } - } - else if (Z_TYPE_P(val) == IS_STRING) - { + } else if (Z_TYPE_P(val) == IS_STRING) { ce = msgpack_unserialize_class( container, Z_STRVAL_P(val), Z_STRLEN_P(val)); - if (ce == NULL) - { + if (ce == NULL) { MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); return 0; @@ -462,18 +488,13 @@ int msgpack_unserialize_map_item( MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); return 0; - } - else - { - switch (unpack->type) - { + } else { + switch (unpack->type) { case MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT: unpack->type = MSGPACK_SERIALIZE_TYPE_NONE; - ce = msgpack_unserialize_class( - container, Z_STRVAL_P(key), Z_STRLEN_P(key)); - if (ce == NULL) - { + ce = msgpack_unserialize_class(container, Z_STRVAL_P(key), Z_STRLEN_P(key)); + if (ce == NULL) { MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); return 0; @@ -532,8 +553,8 @@ int msgpack_unserialize_map_item( } } - int container_is_ref = 0; - if (Z_ISREF_P(*container)) { + zend_bool container_is_ref = 0; + if (container != NULL && Z_ISREF_P(*container)) { container_is_ref = 1; ZVAL_DEREF(*container); } @@ -559,7 +580,7 @@ int msgpack_unserialize_map_item( zval_ptr_dtor(key); break; case IS_STRING: - if ((val = zend_symtable_update(HASH_OF(*container), zend_string_init(Z_STRVAL_P(key), Z_STRLEN_P(key), 0), val)) == NULL) { + if ((val = zend_symtable_update(HASH_OF(*container), zval_get_string(key), val)) == NULL) { zval_ptr_dtor(val); MSGPACK_WARNING( "[msgpack] (%s) illegal offset type, skip this decoding", @@ -570,17 +591,14 @@ int msgpack_unserialize_map_item( default: MSGPACK_WARNING("[msgpack] (%s) illegal key type", __FUNCTION__); - if (MSGPACK_G(illegal_key_insert)) - { + if (MSGPACK_G(illegal_key_insert)) { if ((key = zend_hash_next_index_insert(HASH_OF(*container), key)) == NULL) { zval_ptr_dtor(val); } if ((val = zend_hash_next_index_insert(HASH_OF(*container), val)) == NULL) { zval_ptr_dtor(val); } - } - else - { + } else { convert_to_string(key); if ((zend_symtable_update(HASH_OF(*container), zend_string_init(Z_STRVAL_P(key), Z_STRLEN_P(key), 0), val)) == NULL) { zval_ptr_dtor(val); From a40f0e70945a402df4cb66db88d60e3c528db4df Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Fri, 15 May 2015 03:40:27 +0000 Subject: [PATCH 50/75] Fix memory leak, don't make pointless dupe of zval string when updating a map with a string key --- msgpack_unpack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 12ab139..620eb5c 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -580,7 +580,7 @@ int msgpack_unserialize_map_item( zval_ptr_dtor(key); break; case IS_STRING: - if ((val = zend_symtable_update(HASH_OF(*container), zval_get_string(key), val)) == NULL) { + if ((val = zend_hash_update(HASH_OF(*container), Z_STR(*key), val)) == NULL) { zval_ptr_dtor(val); MSGPACK_WARNING( "[msgpack] (%s) illegal offset type, skip this decoding", From 1185dba88e30e43f8bf592da26295da5b5593ba2 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sat, 16 May 2015 03:28:34 +0000 Subject: [PATCH 51/75] Fix memory leaks for non-dtor allocations --- msgpack_unpack.c | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 620eb5c..c454893 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -16,12 +16,6 @@ typedef struct { void *next; } var_entries; -typedef struct { - zval data[VAR_ENTRIES_MAX]; - long used_slots; - void *next; -} var_entries_dtor; - #define MSGPACK_UNSERIALIZE_FINISH_ITEM(_unpack, _count) \ msgpack_stack_pop(_unpack->var_hash, _count); \ _unpack->stack[_unpack->deps-1]--; \ @@ -49,7 +43,7 @@ inline static void msgpack_var_push(msgpack_unserialize_data_t *var_hashx, zval } if (!var_hash) { - var_hash = emalloc(sizeof(var_entries)); + var_hash = ecalloc(1, sizeof(var_entries)); var_hash->used_slots = 0; var_hash->next = 0; @@ -87,7 +81,7 @@ inline static int msgpack_var_access(msgpack_unserialize_data_t *var_hashx, long inline static void msgpack_stack_push(msgpack_unserialize_data_t *var_hashx, zval **rval) { - var_entries_dtor *var_hash, *prev = NULL; + var_entries *var_hash, *prev = NULL; if (!var_hashx) { return; @@ -101,7 +95,7 @@ inline static void msgpack_stack_push(msgpack_unserialize_data_t *var_hashx, zva } if (!var_hash) { - var_hash = emalloc(sizeof(var_entries_dtor)); + var_hash = ecalloc(1, sizeof(var_entries)); var_hash->used_slots = 0; var_hash->next = 0; @@ -119,7 +113,7 @@ inline static void msgpack_stack_push(msgpack_unserialize_data_t *var_hashx, zva inline static void msgpack_stack_pop(msgpack_unserialize_data_t *var_hashx, long count) { long i; - var_entries_dtor *var_hash = var_hashx->first_dtor; + var_entries *var_hash = var_hashx->first_dtor; while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) { var_hash = var_hash->next; @@ -245,26 +239,25 @@ void msgpack_unserialize_var_destroy( if (var_hash) { var_empty = 0; ZVAL_COPY_VALUE(return_value, &var_hash->data[0]); - //zval_ptr_dtor(&var_hash->data[0]); } while (var_hash) { next = var_hash->next; - //efree(var_hash); + efree(var_hash); var_hash = next; } - var_entries_dtor *var_hash_dtor = var_hashx->first_dtor; + var_hash = var_hashx->first_dtor; if (var_empty) { - ZVAL_DUP(return_value, &var_hash_dtor->data[0]); + ZVAL_DUP(return_value, &var_hash->data[0]); } - while (var_hash_dtor) { - for (i = var_hash_dtor->used_slots - 1; i >= 0; i--) { - zval_ptr_dtor(&var_hash_dtor->data[i]); + while (var_hash) { + for (i = var_hash->used_slots - 1; i >= 0; i--) { + zval_ptr_dtor(&var_hash->data[i]); } - next = var_hash_dtor->next; - efree(var_hash_dtor); - var_hash_dtor = next; + next = var_hash->next; + efree(var_hash); + var_hash = next; } } From 93ec0c78fca449ecd1cda6921ec05d092a10edb0 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sat, 16 May 2015 04:00:56 +0000 Subject: [PATCH 52/75] Fix pack/unpack memory leaks for classes --- msgpack_pack.c | 12 +++++++++--- msgpack_unpack.c | 17 ++++++++++++++--- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index 66ac1d9..828f421 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -358,10 +358,13 @@ inline static void msgpack_serialize_object( } if (ce && ce != PHP_IC_ENTRY && - zend_hash_exists(&ce->function_table, sleep_zstring)) { - res = call_user_function_ex(CG(function_table), val, &fname, &retval, 0, 0, 1, NULL); + zend_hash_exists(&ce->function_table, sleep_zstring)) + { + zend_string_release(sleep_zstring); + zval_ptr_dtor(&fname); - if (res == SUCCESS && !EG(exception)) { + if ((res = call_user_function_ex(CG(function_table), val, &fname, &retval, 0, 0, 1, NULL)) == SUCCESS && !EG(exception)) + { if (HASH_OF(&retval)) { msgpack_serialize_class( buf, val, &retval, var_hash, @@ -376,6 +379,9 @@ inline static void msgpack_serialize_object( zval_ptr_dtor(&retval); return; } + } else { + zval_ptr_dtor(&fname); + zend_string_release(sleep_zstring); } msgpack_serialize_array( diff --git a/msgpack_unpack.c b/msgpack_unpack.c index c454893..fd3299b 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -141,7 +141,10 @@ inline static zend_class_entry* msgpack_unserialize_class( do { /* Try to find class directly */ - if ((ce = zend_lookup_class(zend_string_init(class_name, name_len, 0))) != NULL) { + zend_string *class_zstring = zend_string_init(class_name, name_len, 0); + ce = zend_lookup_class(class_zstring); + zend_string_release(class_zstring); + if (ce != NULL) { break; } @@ -559,8 +562,13 @@ int msgpack_unserialize_map_item( if (Z_TYPE_P(*container) == IS_OBJECT) { const char *class_name, *prop_name; size_t prop_len; - zend_unmangle_property_name_ex(zval_get_string(key), &class_name, &prop_name, &prop_len); + zend_string *key_zstring = zval_get_string(key); + + zend_unmangle_property_name_ex(key_zstring, &class_name, &prop_name, &prop_len); zend_update_property(Z_OBJ_P(*container)->ce, *container, prop_name, prop_len, val); + + zval_ptr_dtor(key); + zend_string_release(key_zstring); } else { switch (Z_TYPE_P(key)) { case IS_LONG: @@ -616,10 +624,12 @@ int msgpack_unserialize_map_item( unpack->deps--; /* wakeup */ + zend_string *wakeup_zstring = zend_string_init("__wakeup", sizeof("__wakeup") - 1, 0); + if (MSGPACK_G(php_only) && Z_TYPE_P(*container) == IS_OBJECT && Z_OBJCE_P(*container) != PHP_IC_ENTRY && - zend_hash_exists(&Z_OBJ_P(*container)->ce->function_table, zend_string_init("__wakeup", sizeof("__wakeup") - 1, 0))) + zend_hash_exists(&Z_OBJ_P(*container)->ce->function_table, wakeup_zstring)) { zval f, h; ZVAL_STRING(&f, "__wakeup"); @@ -627,6 +637,7 @@ int msgpack_unserialize_map_item( call_user_function_ex(CG(function_table), *container, &f, &h, 0, NULL, 1, NULL TSRMLS_CC); zval_ptr_dtor(&h); } + zend_string_release(wakeup_zstring); } return 0; From 351c29cadbf83dd0d272607d6bad1537b98774a7 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sat, 16 May 2015 04:24:07 +0000 Subject: [PATCH 53/75] Fix zend_string memory leak in msgpack_serialize_class --- msgpack_pack.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index 828f421..8693f50 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -69,6 +69,7 @@ inline static int msgpack_var_add( ZVAL_LONG(&zv, -1); zend_hash_next_index_insert(var_hash, &zv); } + zend_string_release(zstring); return FAILURE; } @@ -121,9 +122,8 @@ inline static void msgpack_serialize_class( __FUNCTION__); continue; } - if ((data = zend_hash_find(Z_OBJPROP_P(val), - zend_string_init(Z_STRVAL_P(value), Z_STRLEN_P(value), 0))) != NULL) - { + zend_string *val_zstring = zval_get_string(value); + if ((data = zend_hash_find(Z_OBJPROP_P(val), val_zstring)) != NULL) { msgpack_serialize_string(buf, Z_STRVAL_P(value), Z_STRLEN_P(value)); msgpack_serialize_zval(buf, data, var_hash TSRMLS_CC); } else { @@ -168,6 +168,7 @@ inline static void msgpack_serialize_class( msgpack_serialize_zval(buf, nvalp, var_hash TSRMLS_CC); } } + zend_string_release(val_zstring); } ZEND_HASH_FOREACH_END(); } } From 2247ba1ed60e4a497e2519a57f1f69f6b13bcab1 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sat, 16 May 2015 04:30:27 +0000 Subject: [PATCH 54/75] Fix memory leak in msgpack_unserialize_map_item when executing __wakeup --- msgpack_unpack.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index fd3299b..ddd8a43 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -635,7 +635,9 @@ int msgpack_unserialize_map_item( ZVAL_STRING(&f, "__wakeup"); call_user_function_ex(CG(function_table), *container, &f, &h, 0, NULL, 1, NULL TSRMLS_CC); + zval_ptr_dtor(&h); + zval_ptr_dtor(&f); } zend_string_release(wakeup_zstring); } From 210da3dea62e5bbc08b877f4b32ae7367e3dd73d Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sat, 16 May 2015 04:52:37 +0000 Subject: [PATCH 55/75] In msgpack_serialize_object allocate strings later, to make error handling and freeing cleaner --- msgpack_pack.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index 8693f50..de50d90 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -325,9 +325,7 @@ inline static void msgpack_serialize_object( zval retval, fname; int res; zend_class_entry *ce = NULL; - - zend_string *sleep_zstring = zend_string_init("__sleep", sizeof("__sleep") - 1, 0); - ZVAL_STRING(&fname, "__sleep"); + zend_string *sleep_zstring; if (Z_OBJ_P(Z_REF_AWARE_P(val))->ce) { ce = Z_OBJCE_P(Z_REF_AWARE_P(val)); @@ -358,6 +356,9 @@ inline static void msgpack_serialize_object( return; } + sleep_zstring = zend_string_init("__sleep", sizeof("__sleep") - 1, 0); + ZVAL_STRING(&fname, "__sleep"); + if (ce && ce != PHP_IC_ENTRY && zend_hash_exists(&ce->function_table, sleep_zstring)) { From 45d832a52c4c51118b49ffa90bc7970e8ed6a895 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sat, 16 May 2015 10:40:25 +0000 Subject: [PATCH 56/75] Memory leaks in msgpack_unserialize_class --- msgpack_pack.c | 3 ++- msgpack_unpack.c | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index de50d90..f83c57b 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -363,10 +363,10 @@ inline static void msgpack_serialize_object( zend_hash_exists(&ce->function_table, sleep_zstring)) { zend_string_release(sleep_zstring); - zval_ptr_dtor(&fname); if ((res = call_user_function_ex(CG(function_table), val, &fname, &retval, 0, 0, 1, NULL)) == SUCCESS && !EG(exception)) { + zval_ptr_dtor(&fname); if (HASH_OF(&retval)) { msgpack_serialize_class( buf, val, &retval, var_hash, @@ -379,6 +379,7 @@ inline static void msgpack_serialize_object( msgpack_pack_nil(buf); } zval_ptr_dtor(&retval); + zval_ptr_dtor(&fname); return; } } else { diff --git a/msgpack_unpack.c b/msgpack_unpack.c index ddd8a43..4d94a02 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -138,10 +138,13 @@ inline static zend_class_entry* msgpack_unserialize_class( zend_class_entry *ce; zend_bool incomplete_class = 0; zval user_func, retval, args[1], arg_func_name; + int func_call_status; + zend_string *class_zstring; + do { /* Try to find class directly */ - zend_string *class_zstring = zend_string_init(class_name, name_len, 0); + class_zstring = zend_string_init(class_name, name_len, 0); ce = zend_lookup_class(class_zstring); zend_string_release(class_zstring); if (ce != NULL) { @@ -162,8 +165,11 @@ inline static zend_class_entry* msgpack_unserialize_class( ZVAL_STRING(&arg_func_name, class_name); args[0] = arg_func_name; - if (call_user_function_ex(CG(function_table), NULL, &user_func, &retval, 1, args, 0, NULL) != SUCCESS) - { + + func_call_status = call_user_function_ex(CG(function_table), NULL, &user_func, &retval, 1, args, 0, NULL); + zval_ptr_dtor(&arg_func_name); + zval_ptr_dtor(&user_func); + if (func_call_status != SUCCESS) { MSGPACK_WARNING("[msgpack] (%s) defined (%s) but not found", __FUNCTION__, class_name); @@ -173,7 +179,8 @@ inline static zend_class_entry* msgpack_unserialize_class( } /* The callback function may have defined the class */ - if ((ce = zend_lookup_class(zend_string_init(class_name, name_len, 0))) == NULL) { + class_zstring = zend_string_init(class_name, name_len, 0); + if ((ce = zend_lookup_class(class_zstring)) == NULL) { MSGPACK_WARNING("[msgpack] (%s) Function %s() hasn't defined " "the class it was called for", __FUNCTION__, class_name); @@ -181,6 +188,7 @@ inline static zend_class_entry* msgpack_unserialize_class( incomplete_class = 1; ce = PHP_IC_ENTRY; } + zend_string_release(class_zstring); } while(0); From f1b108a51c3ef847d6c825311e839fb55092311d Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sat, 16 May 2015 11:19:18 +0000 Subject: [PATCH 57/75] PS_SERIALIZER_ENCODE_FUNC would pass an null zval * as return_value to msgpack_unserialize_var_destroy causing a segfault --- msgpack.c | 19 +++++++++---------- msgpack_pack.c | 1 - msgpack_unpack.c | 3 +-- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/msgpack.c b/msgpack.c index 90510bc..7eb6095 100644 --- a/msgpack.c +++ b/msgpack.c @@ -152,7 +152,7 @@ PS_SERIALIZER_ENCODE_FUNC(msgpack) msgpack_serialize_data_t var_hash; msgpack_serialize_var_init(&var_hash); - msgpack_serialize_zval(&buf, &PS(http_session_vars), var_hash TSRMLS_CC); + msgpack_serialize_zval(&buf, &PS(http_session_vars), var_hash); msgpack_serialize_var_destroy(&var_hash); z_string = zend_string_init(buf.c, buf.len, 0); @@ -166,8 +166,7 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) int ret; zend_string *key_str; ulong key_long; - zval *tmp; - zval *value; + zval tmp, *value; size_t off = 0; msgpack_unpack_t mp; msgpack_unserialize_data_t var_hash; @@ -176,15 +175,15 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) msgpack_unserialize_var_init(&var_hash); - mp.user.retval = (zval *)tmp; - mp.user.var_hash = (msgpack_unserialize_data_t *)&var_hash; + mp.user.retval = &tmp; + mp.user.var_hash = &var_hash; - ret = template_execute(&mp, (char *)val, (size_t)vallen, &off); + ret = template_execute(&mp, val, vallen, &off); if (ret == MSGPACK_UNPACK_EXTRA_BYTES || ret == MSGPACK_UNPACK_SUCCESS) { - msgpack_unserialize_var_destroy(&var_hash, 0, tmp); + msgpack_unserialize_var_destroy(&var_hash, 0, &tmp); - ZEND_HASH_FOREACH_KEY_VAL(HASH_OF(tmp), key_long, key_str, value) { + ZEND_HASH_FOREACH_KEY_VAL(HASH_OF(&tmp), key_long, key_str, value) { if (key_str) { php_set_session_var(key_str, value, NULL); php_add_session_var(key_str); @@ -194,10 +193,10 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) } ZEND_HASH_FOREACH_END(); } else { - msgpack_unserialize_var_destroy(&var_hash, 1, tmp); + msgpack_unserialize_var_destroy(&var_hash, 1, &tmp); } - zval_ptr_dtor(tmp); + zval_ptr_dtor(&tmp); return SUCCESS; } diff --git a/msgpack_pack.c b/msgpack_pack.c index f83c57b..8d4cce7 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -366,7 +366,6 @@ inline static void msgpack_serialize_object( if ((res = call_user_function_ex(CG(function_table), val, &fname, &retval, 0, 0, 1, NULL)) == SUCCESS && !EG(exception)) { - zval_ptr_dtor(&fname); if (HASH_OF(&retval)) { msgpack_serialize_class( buf, val, &retval, var_hash, diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 4d94a02..9eefceb 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -141,8 +141,7 @@ inline static zend_class_entry* msgpack_unserialize_class( int func_call_status; zend_string *class_zstring; - do - { + do { /* Try to find class directly */ class_zstring = zend_string_init(class_name, name_len, 0); ce = zend_lookup_class(class_zstring); From caa80cb7213cd7cb366b40a3adad367dc2e74742 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sun, 17 May 2015 04:30:30 +0000 Subject: [PATCH 58/75] Use Z_OBJCE_P instead of Z_OBJ_P()->ce --- msgpack_convert.c | 6 +++--- msgpack_pack.c | 6 +++--- msgpack_unpack.c | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/msgpack_convert.c b/msgpack_convert.c index e85cc1e..d544384 100644 --- a/msgpack_convert.c +++ b/msgpack_convert.c @@ -88,7 +88,7 @@ static inline int msgpack_convert_string_to_properties( TSRMLS_FETCH(); ht = HASH_OF(object); - ce = Z_OBJ_P(object)->ce; + ce = Z_OBJCE_P(object); /* private */ priv_name = zend_mangle_property_name(ce->name->val, ce->name->len, key, key_len - 1, 1); @@ -333,7 +333,7 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { } break; case IS_OBJECT: - ce = Z_OBJ_P(tpl)->ce; + ce = Z_OBJCE_P(tpl); break; default: MSGPACK_ERROR("[msgpack] (%s) object type is unsupported", @@ -344,7 +344,7 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { if (Z_TYPE_P(*value) == IS_OBJECT) { zend_class_entry *vce; - vce = Z_OBJ_P(tpl)->ce; + vce = Z_OBJCE_P(tpl); if (strcmp(ce->name->val, vce->name->val) == 0) { *return_value = **value; diff --git a/msgpack_pack.c b/msgpack_pack.c index 8d4cce7..edfb352 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -49,7 +49,7 @@ inline static int msgpack_var_add( zend_string *zstring; zval zv; - if ((Z_TYPE_P(Z_REF_AWARE_P(var)) == IS_OBJECT) && Z_OBJ_P(var)->ce) { + if ((Z_TYPE_P(Z_REF_AWARE_P(var)) == IS_OBJECT) && Z_OBJCE_P(var)) { p = zend_print_long_to_buf( id + sizeof(id) - 1, (((size_t)Z_OBJCE_P(Z_REF_AWARE_P(var)) << 5) @@ -127,7 +127,7 @@ inline static void msgpack_serialize_class( msgpack_serialize_string(buf, Z_STRVAL_P(value), Z_STRLEN_P(value)); msgpack_serialize_zval(buf, data, var_hash TSRMLS_CC); } else { - zend_class_entry *ce = Z_OBJ_P(val)->ce; + zend_class_entry *ce = Z_OBJCE_P(val); if (ce) { zend_string *priv_name, *prot_name; do @@ -327,7 +327,7 @@ inline static void msgpack_serialize_object( zend_class_entry *ce = NULL; zend_string *sleep_zstring; - if (Z_OBJ_P(Z_REF_AWARE_P(val))->ce) { + if (Z_OBJCE_P(Z_REF_AWARE_P(val))) { ce = Z_OBJCE_P(Z_REF_AWARE_P(val)); } diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 9eefceb..dbeaee9 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -566,13 +566,13 @@ int msgpack_unserialize_map_item( array_init(*container); } - if (Z_TYPE_P(*container) == IS_OBJECT) { + if (Z_TYPE_P(*container) == IS_OBJECT && Z_OBJCE_P(*container) != PHP_IC_ENTRY) { const char *class_name, *prop_name; size_t prop_len; zend_string *key_zstring = zval_get_string(key); zend_unmangle_property_name_ex(key_zstring, &class_name, &prop_name, &prop_len); - zend_update_property(Z_OBJ_P(*container)->ce, *container, prop_name, prop_len, val); + zend_update_property(Z_OBJCE_P(*container), *container, prop_name, prop_len, val); zval_ptr_dtor(key); zend_string_release(key_zstring); @@ -636,7 +636,7 @@ int msgpack_unserialize_map_item( if (MSGPACK_G(php_only) && Z_TYPE_P(*container) == IS_OBJECT && Z_OBJCE_P(*container) != PHP_IC_ENTRY && - zend_hash_exists(&Z_OBJ_P(*container)->ce->function_table, wakeup_zstring)) + zend_hash_exists(&Z_OBJCE_P(*container)->function_table, wakeup_zstring)) { zval f, h; ZVAL_STRING(&f, "__wakeup"); From 3a75af1b91991e2105ce7cb0e3bb5bee82168473 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Mon, 18 May 2015 18:36:26 +0000 Subject: [PATCH 59/75] Cleaner ref handling when unpacking a map item --- msgpack_unpack.c | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index dbeaee9..b1c13b1 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -461,6 +461,7 @@ int msgpack_unserialize_map_item( switch (Z_LVAL_P(val)) { case MSGPACK_SERIALIZE_TYPE_REFERENCE: ZVAL_MAKE_REF(*container); + Z_ADDREF_P(*container); break; case MSGPACK_SERIALIZE_TYPE_RECURSIVE: unpack->type = MSGPACK_SERIALIZE_TYPE_RECURSIVE; @@ -556,30 +557,26 @@ int msgpack_unserialize_map_item( } } - zend_bool container_is_ref = 0; - if (container != NULL && Z_ISREF_P(*container)) { - container_is_ref = 1; - ZVAL_DEREF(*container); - } + zval *container_val = Z_ISREF_P(*container) ? Z_REFVAL_P(*container) : *container; - if (Z_TYPE_P(*container) != IS_ARRAY && Z_TYPE_P(*container) != IS_OBJECT) { - array_init(*container); + if (Z_TYPE_P(container_val) != IS_ARRAY && Z_TYPE_P(container_val) != IS_OBJECT) { + array_init(container_val); } - if (Z_TYPE_P(*container) == IS_OBJECT && Z_OBJCE_P(*container) != PHP_IC_ENTRY) { + if (Z_TYPE_P(container_val) == IS_OBJECT && Z_OBJCE_P(container_val) != PHP_IC_ENTRY) { const char *class_name, *prop_name; size_t prop_len; zend_string *key_zstring = zval_get_string(key); zend_unmangle_property_name_ex(key_zstring, &class_name, &prop_name, &prop_len); - zend_update_property(Z_OBJCE_P(*container), *container, prop_name, prop_len, val); + zend_update_property(Z_OBJCE_P(container_val), container_val, prop_name, prop_len, val); zval_ptr_dtor(key); zend_string_release(key_zstring); } else { switch (Z_TYPE_P(key)) { case IS_LONG: - if ((val = zend_hash_index_update(HASH_OF(*container), Z_LVAL_P(key), val)) == NULL) { + if ((val = zend_hash_index_update(HASH_OF(container_val), Z_LVAL_P(key), val)) == NULL) { zval_ptr_dtor(val); MSGPACK_WARNING( "[msgpack] (%s) illegal offset type, skip this decoding", @@ -588,7 +585,7 @@ int msgpack_unserialize_map_item( zval_ptr_dtor(key); break; case IS_STRING: - if ((val = zend_hash_update(HASH_OF(*container), Z_STR(*key), val)) == NULL) { + if ((val = zend_hash_update(HASH_OF(container_val), Z_STR(*key), val)) == NULL) { zval_ptr_dtor(val); MSGPACK_WARNING( "[msgpack] (%s) illegal offset type, skip this decoding", @@ -600,15 +597,15 @@ int msgpack_unserialize_map_item( MSGPACK_WARNING("[msgpack] (%s) illegal key type", __FUNCTION__); if (MSGPACK_G(illegal_key_insert)) { - if ((key = zend_hash_next_index_insert(HASH_OF(*container), key)) == NULL) { + if ((key = zend_hash_next_index_insert(HASH_OF(container_val), key)) == NULL) { zval_ptr_dtor(val); } - if ((val = zend_hash_next_index_insert(HASH_OF(*container), val)) == NULL) { + if ((val = zend_hash_next_index_insert(HASH_OF(container_val), val)) == NULL) { zval_ptr_dtor(val); } } else { convert_to_string(key); - if ((zend_symtable_update(HASH_OF(*container), zend_string_init(Z_STRVAL_P(key), Z_STRLEN_P(key), 0), val)) == NULL) { + if ((zend_symtable_update(HASH_OF(container_val), zend_string_init(Z_STRVAL_P(key), Z_STRLEN_P(key), 0), val)) == NULL) { zval_ptr_dtor(val); } zval_ptr_dtor(key); @@ -617,11 +614,6 @@ int msgpack_unserialize_map_item( } } - if (container_is_ref) { - ZVAL_MAKE_REF(*container); - Z_TRY_ADDREF_P(*container); - } - msgpack_stack_pop(unpack->var_hash, 2); deps = unpack->deps - 1; @@ -634,14 +626,14 @@ int msgpack_unserialize_map_item( zend_string *wakeup_zstring = zend_string_init("__wakeup", sizeof("__wakeup") - 1, 0); if (MSGPACK_G(php_only) && - Z_TYPE_P(*container) == IS_OBJECT && - Z_OBJCE_P(*container) != PHP_IC_ENTRY && - zend_hash_exists(&Z_OBJCE_P(*container)->function_table, wakeup_zstring)) + Z_TYPE_P(container_val) == IS_OBJECT && + Z_OBJCE_P(container_val) != PHP_IC_ENTRY && + zend_hash_exists(&Z_OBJCE_P(container_val)->function_table, wakeup_zstring)) { zval f, h; ZVAL_STRING(&f, "__wakeup"); - call_user_function_ex(CG(function_table), *container, &f, &h, 0, NULL, 1, NULL TSRMLS_CC); + call_user_function_ex(CG(function_table), container_val, &f, &h, 0, NULL, 1, NULL TSRMLS_CC); zval_ptr_dtor(&h); zval_ptr_dtor(&f); From 676e6bd9bad52a5bf2b977a1c456534f8e76278c Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Wed, 20 May 2015 07:42:42 +0000 Subject: [PATCH 60/75] Update msgpack_unserialize_map_item to remove accidently added Z_ISREF_P --- msgpack_unpack.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index b1c13b1..3b9835f 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -248,7 +248,8 @@ void msgpack_unserialize_var_destroy( var_entries *var_hash = var_hashx->first; if (var_hash) { var_empty = 0; - ZVAL_COPY_VALUE(return_value, &var_hash->data[0]); + ZVAL_COPY(return_value, &var_hash->data[0]); + zval_ptr_dtor(&var_hash->data[0]); } while (var_hash) { next = var_hash->next; @@ -461,7 +462,6 @@ int msgpack_unserialize_map_item( switch (Z_LVAL_P(val)) { case MSGPACK_SERIALIZE_TYPE_REFERENCE: ZVAL_MAKE_REF(*container); - Z_ADDREF_P(*container); break; case MSGPACK_SERIALIZE_TYPE_RECURSIVE: unpack->type = MSGPACK_SERIALIZE_TYPE_RECURSIVE; @@ -542,13 +542,16 @@ int msgpack_unserialize_map_item( *container = rval; - if (type == MSGPACK_SERIALIZE_TYPE_OBJECT && Z_ISREF_P(*container)) { + + if (type == MSGPACK_SERIALIZE_TYPE_OBJECT) { ZVAL_UNREF(*container); - } - else if (type == MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE && Z_ISREF_P(*container)) { + } else if (type == MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE) { ZVAL_MAKE_REF(*container); } + if (Z_REFCOUNTED_P(*container)) Z_TRY_ADDREF_P(*container); + + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); return 0; From 6fbc26a141cb11a882596c41ea9b594490be68c3 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Wed, 20 May 2015 17:59:45 +0000 Subject: [PATCH 61/75] msgpack_unserialize_class now properly handles references, before it would object_init_ex and squash the zval ref --- msgpack_unpack.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 3b9835f..4d4bb81 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -137,10 +137,13 @@ inline static zend_class_entry* msgpack_unserialize_class( { zend_class_entry *ce; zend_bool incomplete_class = 0; - zval user_func, retval, args[1], arg_func_name; + zval user_func, retval, args[1], arg_func_name, *container_val; int func_call_status; zend_string *class_zstring; + container_val = Z_ISREF_P(*container) ? Z_REFVAL_P(*container) : *container; + + do { /* Try to find class directly */ class_zstring = zend_string_init(class_name, name_len, 0); @@ -196,12 +199,12 @@ inline static zend_class_entry* msgpack_unserialize_class( return NULL; } - object_init_ex(*container, ce); + object_init_ex(container_val, ce); /* store incomplete class name */ if (incomplete_class) { - php_store_class_name(*container, class_name, name_len); + php_store_class_name(container_val, class_name, name_len); } return ce; From 88217d0b742af59009863ba4eb780c91c9eb9c7d Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Wed, 20 May 2015 20:04:38 +0000 Subject: [PATCH 62/75] msgpack_serialize_array was incorrectly ported to handle when php_only is 0 --- msgpack_pack.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msgpack_pack.c b/msgpack_pack.c index edfb352..21db49e 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -264,9 +264,9 @@ inline static void msgpack_serialize_array( if (key_str && incomplete_class && strcmp(key_str->val, MAGIC_MEMBER) == 0) { continue; } - if (key_str) { + if (key_str && hash) { msgpack_serialize_string(buf, key_str->val, key_str->len); - } else { + } else if (hash) { msgpack_pack_long(buf, key_long); } From f53f48467c5675feca4ed8a8799b89a79b394319 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Wed, 20 May 2015 21:32:50 +0000 Subject: [PATCH 63/75] Remove MSGPACK_METHOD1 macro which created the necessary opcodes to call a method on an object, use call_user_function_ex instead --- msgpack.c | 1 + msgpack_class.c | 62 +++++++----------------------------------------- msgpack_unpack.c | 6 +++-- 3 files changed, 13 insertions(+), 56 deletions(-) diff --git a/msgpack.c b/msgpack.c index 7eb6095..8412959 100644 --- a/msgpack.c +++ b/msgpack.c @@ -204,6 +204,7 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) PHP_MSGPACK_API void php_msgpack_serialize(smart_string *buf, zval *val TSRMLS_DC) { + msgpack_serialize_data_t var_hash; msgpack_serialize_var_init(&var_hash); diff --git a/msgpack_class.c b/msgpack_class.c index 3e3084e..47c6a46 100644 --- a/msgpack_class.c +++ b/msgpack_class.c @@ -24,47 +24,6 @@ typedef struct { int error; } php_msgpack_unpacker_t; -#if ZEND_MODULE_API_NO >= 20060613 -# define MSGPACK_METHOD_BASE(classname, name) zim_##classname##_##name -#else -# define MSGPACK_METHOD_BASE(classname, name) zif_##classname##_##name -#endif - -#if ZEND_MODULE_API_NO >= 20090115 -# define PUSH_PARAM(arg) zend_vm_stack_push(arg TSRMLS_CC) -# define POP_PARAM() (void)zend_vm_stack_pop(TSRMLS_C) -# define PUSH_EO_PARAM() -# define POP_EO_PARAM() -#else -# define PUSH_PARAM(arg) zend_ptr_stack_push(&EG(argument_stack), arg) -# define POP_PARAM() (void)zend_ptr_stack_pop(&EG(argument_stack)) -# define PUSH_EO_PARAM() zend_ptr_stack_push(&EG(argument_stack), NULL) -# define POP_EO_PARAM() (void)zend_ptr_stack_pop(&EG(argument_stack)) -#endif - -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0) -#define MSGPACK_METHOD_HELPER(classname, name, retval, thisptr, num, param) \ - PUSH_PARAM(param); PUSH_PARAM((void*)num); \ - PUSH_EO_PARAM(); \ - MSGPACK_METHOD_BASE(classname, name)(num, retval, NULL, thisptr, 0 TSRMLS_CC); \ - POP_EO_PARAM(); \ - POP_PARAM(); POP_PARAM(); -#define MSGPACK_METHOD(classname, name, retval, thisptr) \ - MSGPACK_METHOD_BASE(classname, name)(0, retval, NULL, thisptr, 0 TSRMLS_CC) -#else -#define MSGPACK_METHOD_HELPER(classname, name, retval, thisptr, num, param) \ - PUSH_PARAM(param); PUSH_PARAM((void*)num); \ - PUSH_EO_PARAM(); \ - MSGPACK_METHOD_BASE(classname, name)(num, retval, thisptr, 0 TSRMLS_CC); \ - POP_EO_PARAM(); \ - POP_PARAM(); POP_PARAM(); -#define MSGPACK_METHOD(classname, name, retval, thisptr) \ - MSGPACK_METHOD_BASE(classname, name)(0, retval, thisptr, 0 TSRMLS_CC) -#endif - -#define MSGPACK_METHOD1(classname, name, retval, thisptr, param1) \ - MSGPACK_METHOD_HELPER(classname, name, retval, thisptr, 1, param1); - static inline php_msgpack_base_t *msgpack_base_fetch_object(zend_object *obj) { return (php_msgpack_base_t *)((char*)(obj) - XtOffsetOf(php_msgpack_base_t, object)); } @@ -312,16 +271,16 @@ static ZEND_METHOD(msgpack, unpack) static ZEND_METHOD(msgpack, unpacker) { - zval temp, *opt; + zval temp, args[1], func_name, construct_return; php_msgpack_base_t *base = Z_MSGPACK_BASE_P(getThis()); - ZVAL_BOOL(opt, base->php_only); + ZVAL_BOOL(&args[0], base->php_only); + ZVAL_STRING(&func_name, "__construct"); object_init_ex(return_value, msgpack_unpacker_ce); + call_user_function_ex(CG(function_table), return_value, &func_name, &construct_return, 1, args, 0, NULL); - //MSGPACK_METHOD1(msgpack_unpacker, __construct, &temp, return_value, opt); - - zval_ptr_dtor(opt); + zval_ptr_dtor(&func_name); } /* MessagePackUnpacker */ @@ -330,9 +289,7 @@ static ZEND_METHOD(msgpack_unpacker, __construct) zend_bool php_only = MSGPACK_G(php_only); php_msgpack_unpacker_t *unpacker = Z_MSGPACK_UNPACKER_P(getThis()); - if (zend_parse_parameters( - ZEND_NUM_ARGS() TSRMLS_CC, "|b", &php_only) == FAILURE) - { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &php_only) == FAILURE) { return; } @@ -350,8 +307,7 @@ static ZEND_METHOD(msgpack_unpacker, __construct) msgpack_unserialize_var_init(&unpacker->var_hash); - (&unpacker->mp)->user.var_hash = - (msgpack_unserialize_data_t *)&unpacker->var_hash; + (&unpacker->mp)->user.var_hash = (msgpack_unserialize_data_t *)&unpacker->var_hash; } static ZEND_METHOD(msgpack_unpacker, __destruct) @@ -359,9 +315,7 @@ static ZEND_METHOD(msgpack_unpacker, __destruct) php_msgpack_unpacker_t *unpacker = Z_MSGPACK_UNPACKER_P(getThis()); smart_string_free(&unpacker->buffer); - - if (unpacker->retval != NULL) - { + if (unpacker->retval != NULL) { zval_ptr_dtor(unpacker->retval); } diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 4d4bb81..2d64035 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -251,7 +251,9 @@ void msgpack_unserialize_var_destroy( var_entries *var_hash = var_hashx->first; if (var_hash) { var_empty = 0; - ZVAL_COPY(return_value, &var_hash->data[0]); + if (return_value != NULL) { + ZVAL_COPY(return_value, &var_hash->data[0]); + } zval_ptr_dtor(&var_hash->data[0]); } while (var_hash) { @@ -262,7 +264,7 @@ void msgpack_unserialize_var_destroy( var_hash = var_hashx->first_dtor; - if (var_empty) { + if (var_empty && return_value != NULL) { ZVAL_DUP(return_value, &var_hash->data[0]); } while (var_hash) { From b1a2abcaa40149cbcffde2db8cac12186c5432d9 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Fri, 22 May 2015 06:15:39 +0000 Subject: [PATCH 64/75] Update MessagePackUnpacker to use new object API, fixing unpacker tests --- msgpack.c | 14 +++-- msgpack_class.c | 148 ++++++++++++++++++----------------------------- msgpack_unpack.c | 23 ++++---- 3 files changed, 74 insertions(+), 111 deletions(-) diff --git a/msgpack.c b/msgpack.c index 8412959..7c8f05b 100644 --- a/msgpack.c +++ b/msgpack.c @@ -181,7 +181,8 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) ret = template_execute(&mp, val, vallen, &off); if (ret == MSGPACK_UNPACK_EXTRA_BYTES || ret == MSGPACK_UNPACK_SUCCESS) { - msgpack_unserialize_var_destroy(&var_hash, 0, &tmp); + msgpack_unserialize_set_return_value(&var_hash, &tmp); + msgpack_unserialize_var_destroy(&var_hash, 0); ZEND_HASH_FOREACH_KEY_VAL(HASH_OF(&tmp), key_long, key_str, value) { if (key_str) { @@ -193,7 +194,7 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) } ZEND_HASH_FOREACH_END(); } else { - msgpack_unserialize_var_destroy(&var_hash, 1, &tmp); + msgpack_unserialize_var_destroy(&var_hash, 1); } zval_ptr_dtor(&tmp); @@ -241,11 +242,11 @@ PHP_MSGPACK_API void php_msgpack_unserialize( case MSGPACK_UNPACK_PARSE_ERROR: zval_dtor(return_value); ZVAL_FALSE(return_value); - msgpack_unserialize_var_destroy(&var_hash, 1, return_value); + msgpack_unserialize_var_destroy(&var_hash, 1); MSGPACK_WARNING("[msgpack] (%s) Parse error", __FUNCTION__); break; case MSGPACK_UNPACK_CONTINUE: - msgpack_unserialize_var_destroy(&var_hash, 0, return_value); + msgpack_unserialize_var_destroy(&var_hash, 0); ZVAL_FALSE(return_value); MSGPACK_WARNING( "[msgpack] (%s) Insufficient data for unserializing", @@ -253,7 +254,8 @@ PHP_MSGPACK_API void php_msgpack_unserialize( break; case MSGPACK_UNPACK_EXTRA_BYTES: case MSGPACK_UNPACK_SUCCESS: - msgpack_unserialize_var_destroy(&var_hash, 0, return_value); + msgpack_unserialize_set_return_value(&var_hash, return_value); + msgpack_unserialize_var_destroy(&var_hash, 0); if (off < str_len) { MSGPACK_WARNING("[msgpack] (%s) Extra bytes", __FUNCTION__); } @@ -261,7 +263,7 @@ PHP_MSGPACK_API void php_msgpack_unserialize( default: zval_dtor(return_value); ZVAL_FALSE(return_value); - msgpack_unserialize_var_destroy(&var_hash, 0, return_value); + msgpack_unserialize_var_destroy(&var_hash, 0); MSGPACK_WARNING("[msgpack] (%s) Unknown result", __FUNCTION__); break; } diff --git a/msgpack_class.c b/msgpack_class.c index 47c6a46..30a16cd 100644 --- a/msgpack_class.c +++ b/msgpack_class.c @@ -13,15 +13,15 @@ typedef struct { } php_msgpack_base_t; typedef struct { - zend_object object; smart_string buffer; - zval *retval; + zval retval; long offset; msgpack_unpack_t mp; msgpack_unserialize_data_t var_hash; long php_only; zend_bool finished; int error; + zend_object object; } php_msgpack_unpacker_t; static inline php_msgpack_base_t *msgpack_base_fetch_object(zend_object *obj) { @@ -161,11 +161,13 @@ zend_object *php_msgpack_unpacker_new(zend_class_entry *ce TSRMLS_DC) { return &intern->object; } -static void php_msgpack_unpacker_free( - php_msgpack_unpacker_t *unpacker TSRMLS_DC) +static void php_msgpack_unpacker_free(zend_object *object) { - zend_object_std_dtor(&unpacker->object TSRMLS_CC); - efree(unpacker); + php_msgpack_unpacker_t *intern = msgpack_unpacker_fetch_object(object); + if (!intern) { + return; + } + zend_object_std_dtor(&intern->object); } @@ -298,7 +300,6 @@ static ZEND_METHOD(msgpack_unpacker, __construct) unpacker->buffer.c = NULL; unpacker->buffer.len = 0; unpacker->buffer.a = 0; - unpacker->retval = NULL; unpacker->offset = 0; unpacker->finished = 0; unpacker->error = 0; @@ -307,7 +308,7 @@ static ZEND_METHOD(msgpack_unpacker, __construct) msgpack_unserialize_var_init(&unpacker->var_hash); - (&unpacker->mp)->user.var_hash = (msgpack_unserialize_data_t *)&unpacker->var_hash; + (&unpacker->mp)->user.var_hash = &unpacker->var_hash; } static ZEND_METHOD(msgpack_unpacker, __destruct) @@ -315,11 +316,9 @@ static ZEND_METHOD(msgpack_unpacker, __destruct) php_msgpack_unpacker_t *unpacker = Z_MSGPACK_UNPACKER_P(getThis()); smart_string_free(&unpacker->buffer); - if (unpacker->retval != NULL) { - zval_ptr_dtor(unpacker->retval); - } + zval_ptr_dtor(&unpacker->retval); - msgpack_unserialize_var_destroy(&unpacker->var_hash, unpacker->error, unpacker->retval); + msgpack_unserialize_var_destroy(&unpacker->var_hash, unpacker->error); } static ZEND_METHOD(msgpack_unpacker, setOption) @@ -373,63 +372,43 @@ static ZEND_METHOD(msgpack_unpacker, execute) { char *str = NULL, *data; long str_len = 0; - zval *offset = NULL; - int ret; + int ret, error_display = MSGPACK_G(error_display), php_only = MSGPACK_G(php_only); size_t len, off; - int error_display = MSGPACK_G(error_display); - int php_only = MSGPACK_G(php_only); + zval *offset = NULL; php_msgpack_unpacker_t *unpacker = Z_MSGPACK_UNPACKER_P(getThis()); - if (zend_parse_parameters( - ZEND_NUM_ARGS() TSRMLS_CC, "|sz/", - &str, &str_len, &offset) == FAILURE) - { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sz/", &str, &str_len, &offset) == FAILURE) { return; } - if (str != NULL) - { - data = (char *)str; - len = (size_t)str_len; - if (offset != NULL) - { + if (str) { + data = str; + len = str_len; + if (offset != NULL) { off = Z_LVAL_P(offset); - } - else - { + } else { off = 0; } - } - else - { - data = (char *)unpacker->buffer.c; + } else { + data = unpacker->buffer.c; len = unpacker->buffer.len; off = unpacker->offset; } - if (unpacker->retval == NULL) - { - zval zv; - unpacker->retval = &zv; - } - else if (unpacker->finished) - { - zval_ptr_dtor(unpacker->retval); + if (unpacker->finished) { + zval_ptr_dtor(&unpacker->retval); - msgpack_unserialize_var_destroy(&unpacker->var_hash, unpacker->error, unpacker->retval); + msgpack_unserialize_set_return_value(&unpacker->var_hash, &unpacker->retval); + msgpack_unserialize_var_destroy(&unpacker->var_hash, unpacker->error); unpacker->error = 0; - zval zv; - unpacker->retval = &zv; - template_init(&unpacker->mp); msgpack_unserialize_var_init(&unpacker->var_hash); - (&unpacker->mp)->user.var_hash = - (msgpack_unserialize_data_t *)&unpacker->var_hash; + (&unpacker->mp)->user.var_hash = &unpacker->var_hash; } - (&unpacker->mp)->user.retval = (zval *)unpacker->retval; + (&unpacker->mp)->user.retval = &unpacker->retval; MSGPACK_G(error_display) = 0; MSGPACK_G(php_only) = unpacker->php_only; @@ -439,20 +418,15 @@ static ZEND_METHOD(msgpack_unpacker, execute) MSGPACK_G(error_display) = error_display; MSGPACK_G(php_only) = php_only; - if (str != NULL) - { - if (offset != NULL) - { + if (str != NULL) { + if (offset != NULL) { ZVAL_LONG(offset, off); } - } - else - { + } else { unpacker->offset = off; } - switch (ret) - { + switch (ret) { case MSGPACK_UNPACK_EXTRA_BYTES: case MSGPACK_UNPACK_SUCCESS: unpacker->finished = 1; @@ -466,38 +440,35 @@ static ZEND_METHOD(msgpack_unpacker, execute) static ZEND_METHOD(msgpack_unpacker, data) { - zval *object = NULL; + zval *object = NULL, func_name, reset_return; php_msgpack_unpacker_t *unpacker = Z_MSGPACK_UNPACKER_P(getThis()); - if (zend_parse_parameters( - ZEND_NUM_ARGS() TSRMLS_CC, "|z", &object) == FAILURE) - { + if (zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "|z", &object) == FAILURE) { return; } - if (unpacker->retval != NULL) - { - if (object == NULL) - { - ZVAL_ZVAL(return_value, unpacker->retval, 1, 0); - } - else - { - zval *zv; - - ZVAL_ZVAL(zv, unpacker->retval, 1, 0); + if (unpacker->finished) { + msgpack_unserialize_set_return_value(&unpacker->var_hash, &unpacker->retval); + } - if (msgpack_convert_object(return_value, object, &zv) != SUCCESS) - { - RETURN_NULL(); - } - } + if (object == NULL) { + ZVAL_ZVAL(return_value, &unpacker->retval, 1, 0); + } else { + zval zv, *zv_p; + zv_p = &zv; - //MSGPACK_METHOD(msgpack_unpacker, reset, NULL, getThis()); + ZVAL_ZVAL(&zv, &unpacker->retval, 1, 0); - return; + if (msgpack_convert_object(return_value, object, &zv_p) != SUCCESS) { + RETURN_NULL(); + } } + ZVAL_STRING(&func_name, "reset"); + call_user_function_ex(CG(function_table), getThis(), &func_name, &reset_return, 0, NULL, 0, NULL); + zval_ptr_dtor(&func_name); + + return; RETURN_FALSE; } @@ -506,8 +477,7 @@ static ZEND_METHOD(msgpack_unpacker, reset) smart_string buffer = {0}; php_msgpack_unpacker_t *unpacker = Z_MSGPACK_UNPACKER_P(getThis()); - if (unpacker->buffer.len > unpacker->offset) - { + if (unpacker->buffer.len > unpacker->offset) { smart_string_appendl(&buffer, unpacker->buffer.c + unpacker->offset, unpacker->buffer.len - unpacker->offset); } @@ -520,20 +490,13 @@ static ZEND_METHOD(msgpack_unpacker, reset) unpacker->offset = 0; unpacker->finished = 0; - if (buffer.len > 0) - { + if (buffer.len > 0) { smart_string_appendl(&unpacker->buffer, buffer.c, buffer.len); } smart_string_free(&buffer); - if (unpacker->retval != NULL) - { - zval_ptr_dtor(unpacker->retval); - unpacker->retval = NULL; - } - - msgpack_unserialize_var_destroy(&unpacker->var_hash, unpacker->error, unpacker->retval); + msgpack_unserialize_var_destroy(&unpacker->var_hash, unpacker->error); unpacker->error = 0; @@ -541,8 +504,7 @@ static ZEND_METHOD(msgpack_unpacker, reset) msgpack_unserialize_var_init(&unpacker->var_hash); - (&unpacker->mp)->user.var_hash = - (msgpack_unserialize_data_t *)&unpacker->var_hash; + (&unpacker->mp)->user.var_hash = &unpacker->var_hash; } void msgpack_init_class() @@ -566,4 +528,6 @@ void msgpack_init_class() msgpack_unpacker_ce->create_object = php_msgpack_unpacker_new; memcpy(&msgpack_unpacker_handlers, zend_get_std_object_handlers(),sizeof msgpack_unpacker_handlers); msgpack_unpacker_handlers.offset = XtOffsetOf(php_msgpack_unpacker_t, object); + msgpack_handlers.free_obj = php_msgpack_base_free; + } diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 2d64035..1ba99b6 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -241,32 +241,20 @@ void msgpack_unserialize_var_init(msgpack_unserialize_data_t *var_hashx) var_hashx->first_dtor = 0; } -void msgpack_unserialize_var_destroy( - msgpack_unserialize_data_t *var_hashx, zend_bool err, zval *return_value) +void msgpack_unserialize_var_destroy(msgpack_unserialize_data_t *var_hashx, zend_bool err) { void *next; long i; zend_bool var_empty = 1; var_entries *var_hash = var_hashx->first; - if (var_hash) { - var_empty = 0; - if (return_value != NULL) { - ZVAL_COPY(return_value, &var_hash->data[0]); - } - zval_ptr_dtor(&var_hash->data[0]); - } while (var_hash) { next = var_hash->next; efree(var_hash); var_hash = next; } - var_hash = var_hashx->first_dtor; - if (var_empty && return_value != NULL) { - ZVAL_DUP(return_value, &var_hash->data[0]); - } while (var_hash) { for (i = var_hash->used_slots - 1; i >= 0; i--) { zval_ptr_dtor(&var_hash->data[i]); @@ -275,6 +263,15 @@ void msgpack_unserialize_var_destroy( efree(var_hash); var_hash = next; } +} + +void msgpack_unserialize_set_return_value(msgpack_unserialize_data_t *var_hashx, zval *return_value) { + var_entries *var_hash; + if ((var_hash = var_hashx->first) != NULL) { + ZVAL_COPY_VALUE(return_value, &var_hash->data[0]); + } else if ((var_hash = var_hashx->first_dtor) != NULL) { + ZVAL_COPY(return_value, &var_hash->data[0]); + } } From 3fb45c3f5303408bf2b68178c8eb8726c1cc0ff3 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Fri, 22 May 2015 17:15:35 +0000 Subject: [PATCH 65/75] Z_LVAL_P on a boolean is no longer valid, msgpack->setOption incorrectly set php_only using Z_LVAL_P causing it to always be true --- msgpack_class.c | 13 ++++--------- msgpack_unpack.h | 3 +-- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/msgpack_class.c b/msgpack_class.c index 30a16cd..da095e0 100644 --- a/msgpack_class.c +++ b/msgpack_class.c @@ -192,17 +192,14 @@ static ZEND_METHOD(msgpack, setOption) zval *value; php_msgpack_base_t *base = Z_MSGPACK_BASE_P(getThis()); - if (zend_parse_parameters( - ZEND_NUM_ARGS() TSRMLS_CC, "lz", &option, &value) == FAILURE) - { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &option, &value) == FAILURE) { return; } - switch (option) - { + switch (option) { case MSGPACK_CLASS_OPT_PHPONLY: convert_to_boolean(value); - base->php_only = Z_LVAL_P(value); + base->php_only = (Z_TYPE_P(value) == IS_TRUE) ? 1 : 0; break; default: MSGPACK_WARNING("[msgpack] (MessagePack::setOption) " @@ -221,9 +218,7 @@ static ZEND_METHOD(msgpack, pack) int php_only = MSGPACK_G(php_only); php_msgpack_base_t *base = Z_MSGPACK_BASE_P(getThis()); - if (zend_parse_parameters( - ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶meter) == FAILURE) - { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶meter) == FAILURE) { return; } diff --git a/msgpack_unpack.h b/msgpack_unpack.h index 835d76d..a6a288a 100644 --- a/msgpack_unpack.h +++ b/msgpack_unpack.h @@ -29,8 +29,7 @@ typedef struct { void msgpack_serialize_var_init(msgpack_serialize_data_t *var_hash); void msgpack_serialize_var_destroy(msgpack_serialize_data_t *var_hash); void msgpack_unserialize_var_init(msgpack_unserialize_data_t *var_hashx); -void msgpack_unserialize_var_destroy( - msgpack_unserialize_data_t *var_hashx, zend_bool err, zval *return_value); +void msgpack_unserialize_var_destroy(msgpack_unserialize_data_t *var_hashx, zend_bool err); void msgpack_unserialize_init(msgpack_unserialize_data *unpack); From 35729382ad6227f5900ab666b705a57a244c3691 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Tue, 26 May 2015 05:06:35 +0000 Subject: [PATCH 66/75] Began converting msgpack_convert.c from using symtable_update to update properties to proper zend_object handlers --- msgpack.c | 1 + msgpack_convert.c | 295 +++++++++++++++++++++------------------------- 2 files changed, 133 insertions(+), 163 deletions(-) diff --git a/msgpack.c b/msgpack.c index 7c8f05b..c571eb9 100644 --- a/msgpack.c +++ b/msgpack.c @@ -309,5 +309,6 @@ static ZEND_FUNCTION(msgpack_unserialize) if (msgpack_convert_template(return_value, object, &zv_p) != SUCCESS) { RETURN_NULL(); } + zval_ptr_dtor(object); } } diff --git a/msgpack_convert.c b/msgpack_convert.c index d544384..0c53b95 100644 --- a/msgpack_convert.c +++ b/msgpack_convert.c @@ -5,113 +5,118 @@ #include "msgpack_convert.h" #include "msgpack_errors.h" -#define MSGPACK_CONVERT_COPY_ZVAL(_pz, _ppz) \ - //ALLOC_INIT_ZVAL(_pz); \ - //*(_pz) = **(_ppz); \ - //if (PZVAL_IS_REF(*(_ppz))) { \ - // if (Z_REFCOUNT_P(*(_ppz)) > 0) { \ - // zval_copy_ctor(_pz); \ - // } else { \ - // FREE_ZVAL(*(_ppz)); \ - // } \ - // INIT_PZVAL(_pz); \ - // Z_SET_ISREF_P(_pz); \ - //} else { \ - // zval_copy_ctor(_pz); \ - // INIT_PZVAL(_pz); \ - //} - -#define MSGPACK_CONVERT_UPDATE_PROPERTY(_ht, _key, _val, _var) \ - if ((val = zend_symtable_update(_ht, _key, _val)) != NULL) { \ - zend_hash_add(_var, _key, _val); \ - return SUCCESS; \ - } - -static inline int msgpack_convert_long_to_properties(HashTable *ht, HashTable **properties, +inline int msgpack_convert_long_to_properties( + HashTable *ht, zval *object, HashTable **properties, HashPosition *prop_pos, uint key_index, zval *val, HashTable *var) { if (*properties != NULL) { - zend_string *key_str; - ulong key_long; - zval *data; - - //non-iteration - zval *dataval = NULL, *tplval = NULL; - - ZEND_HASH_FOREACH_KEY_VAL(ht, key_long, key_str, data) { - if(key_str) { - switch (Z_TYPE_P(data)) { - case IS_ARRAY: - { - HashTable *dataht; - dataht = HASH_OF(val); - if ((dataval = zend_hash_index_find(dataht, key_long)) != NULL) { - MSGPACK_WARNING( - "[msgpack] (%s) " - "can't get data value by index", - __FUNCTION__); - return FAILURE; - } - - if (msgpack_convert_array(tplval, data, &dataval) == SUCCESS) { - return (zend_symtable_update(ht, key_str, tplval) != NULL); - } - // TODO: de we need to call dtor? - return FAILURE; - } - case IS_OBJECT: - { - if (msgpack_convert_object(tplval, data, &val) == SUCCESS) { - return (zend_symtable_update(ht, key_str, tplval) != NULL); - } - // TODO: de we need to call dtor? - return FAILURE; + zval *data, tplval, *dataval, prop_key_zv; + zend_string *prop_key; + ulong prop_key_index; + const char *class_name, *prop_name; + size_t prop_len; + + for (;; zend_hash_move_forward_ex(*properties, prop_pos)) { + if (zend_hash_get_current_key_ex(*properties, &prop_key, &prop_key_index, prop_pos) == HASH_KEY_IS_STRING) { + zend_unmangle_property_name_ex(prop_key, &class_name, &prop_name, &prop_len); + + if (var == NULL || !zend_hash_exists(var, prop_key)) { + if ((data = zend_hash_find(ht, prop_key)) != NULL) { + prop_key = zend_string_init(prop_name, prop_len, 0); + ZVAL_NEW_STR(&prop_key_zv, prop_key); + + switch (Z_TYPE_P(data)) { + case IS_ARRAY: + { + HashTable *dataht; + dataht = HASH_OF(val); + + if ((dataval = zend_hash_index_find(dataht, prop_key_index)) == NULL) { + MSGPACK_WARNING("[msgpack] (%s) " + "can't get data value by index", + __FUNCTION__); + zend_string_release(prop_key); + return FAILURE; + } + + if (msgpack_convert_array(&tplval, data, &dataval) == SUCCESS) { + zend_hash_move_forward_ex(*properties, prop_pos); + + zend_update_property(Z_OBJCE_P(object), object, prop_name, prop_len, &tplval); + zend_string_release(prop_key); + return SUCCESS; + } + zend_string_release(prop_key); + return FAILURE; + } + case IS_OBJECT: + { + if (msgpack_convert_object(&tplval, data, &val) == SUCCESS) { + zend_hash_move_forward_ex(*properties, prop_pos); + zend_update_property(Z_OBJCE_P(object), object, prop_name, prop_len, &tplval); + zend_string_release(prop_key); + return SUCCESS; + } + zend_string_release(prop_key); + return FAILURE; + } + default: + zend_hash_move_forward_ex(*properties, prop_pos); + zend_update_property(Z_OBJCE_P(object), object, prop_name, prop_len, val); + zend_string_release(prop_key); + return SUCCESS; } - default: - return (zend_symtable_update(ht, key_str, val) != NULL); + } } + zend_string_release(prop_key); + } else { + break; } - } ZEND_HASH_FOREACH_END(); + } *properties = NULL; } - return (zend_hash_index_update(ht, key_index, val) != NULL); + zval key_zv; + ZVAL_LONG(&key_zv, key_index); + zend_std_write_property(object, &key_zv, val, NULL); + return SUCCESS; } static inline int msgpack_convert_string_to_properties( zval *object, char *key, uint key_len, zval *val, HashTable *var) { - zval *data = NULL; - HashTable *ht; - zend_class_entry *ce; - zend_string *priv_name, *prot_name; - - TSRMLS_FETCH(); - - ht = HASH_OF(object); - ce = Z_OBJCE_P(object); - - /* private */ - priv_name = zend_mangle_property_name(ce->name->val, ce->name->len, key, key_len - 1, 1); - if ((data = zend_hash_find(ht, priv_name)) != NULL) { - MSGPACK_CONVERT_UPDATE_PROPERTY(ht, priv_name, val, var); - } - - /* protected */ - prot_name = zend_mangle_property_name("*", 1, key, key_len - 1, 1); - if ((data = zend_hash_find(ht, prot_name)) != NULL) { - MSGPACK_CONVERT_UPDATE_PROPERTY(ht, prot_name, val, var); - } + zend_class_entry *ce = Z_OBJCE_P(object); + HashTable *propers = Z_OBJPROP_P(object); + zend_string *prot_name, *priv_name, *pub_name; + zval pub_name_z; + int return_code; + + ZVAL_STRINGL(&pub_name_z, key, key_len); + priv_name = zend_mangle_property_name(ce->name->val, ce->name->len, key, key_len, 1); + prot_name = zend_mangle_property_name("*", 1, key, key_len, 1); + pub_name = zval_get_string(&pub_name_z); + + if (zend_hash_find(propers, priv_name) != NULL) { + zend_update_property(ce, object, key, key_len, val); + return_code = SUCCESS; + } else if (zend_hash_find(propers, prot_name) != NULL) { + zend_update_property(ce, object, key, key_len, val); + return_code = SUCCESS; + } else { + zend_std_write_property(object, &pub_name_z, val, NULL); + return_code = FAILURE; + } + zend_hash_add(var, pub_name, val); - /* public */ - MSGPACK_CONVERT_UPDATE_PROPERTY(ht, zend_string_init(key, key_len, 1), val, var); + zend_string_release(priv_name); + zend_string_release(prot_name); + zend_string_release(pub_name); + zval_ptr_dtor(&pub_name_z); - return FAILURE; + return return_code; } int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) { - TSRMLS_FETCH(); - if (Z_TYPE_P(tpl) == IS_ARRAY) { HashTable *ht, *htval; @@ -173,8 +178,6 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) return FAILURE; } - MSGPACK_CONVERT_COPY_ZVAL(val, dataval); - if (convert_function) { zval *rv; @@ -265,7 +268,6 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) continue; } else if (key_long) { zval *aryval, *rv; - MSGPACK_CONVERT_COPY_ZVAL(aryval, data); if (convert_function) { if (convert_function(rv, data, &aryval) != SUCCESS) @@ -325,7 +327,6 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { switch (Z_TYPE_P(tpl)) { case IS_STRING: - if ((ce = zend_lookup_class(zval_get_string(tpl))) == NULL) { MSGPACK_ERROR("[msgpack] (%s) Class '%s' not found", __FUNCTION__, Z_STRVAL_P(tpl)); @@ -387,18 +388,15 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { } } - switch (Z_TYPE_P(*value)) - { + switch (Z_TYPE_P(*value)) { case IS_ARRAY: { - HashTable *ht, *ret; - HashTable *var = NULL; + HashTable *ht, *ret, *var = NULL; int num; zend_string *str_key; zval *data; ulong num_key; - ht = HASH_OF(*value); ret = HASH_OF(return_value); @@ -409,23 +407,17 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { } /* string - php_only mode? */ - if (ht->nNumOfElements != ht->nNextFreeElement - || ht->nNumOfElements != ret->nNumOfElements) { + if (ht->nNumOfElements != ht->nNextFreeElement || ht->nNumOfElements != ret->nNumOfElements) { HashTable *properties = NULL; + HashPosition prop_pos; ALLOC_HASHTABLE(var); zend_hash_init(var, num, NULL, NULL, 0); - ZEND_HASH_FOREACH_KEY_VAL(ht, num_key, str_key, data) { - if (str_key && data) { - zval *val; - MSGPACK_CONVERT_COPY_ZVAL(val, &data); - if (msgpack_convert_string_to_properties( - return_value, str_key->val, str_key->len, val, var) != SUCCESS) - { - zval_ptr_dtor(val); - MSGPACK_WARNING( - "[msgpack] (%s) " + ZEND_HASH_FOREACH_STR_KEY_VAL(ht, str_key, data) { + if (str_key) { + if (msgpack_convert_string_to_properties(return_value, str_key->val, str_key->len, data, var) != SUCCESS) { + MSGPACK_WARNING("[msgpack] (%s) " "illegal offset type, skip this decoding", __FUNCTION__); } @@ -434,54 +426,40 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { /* index */ properties = Z_OBJ_HT_P(return_value)->get_properties(return_value TSRMLS_CC); - if (HASH_OF(tpl)) { properties = HASH_OF(tpl); } + zend_hash_internal_pointer_reset_ex(properties, &prop_pos); + ZEND_HASH_FOREACH_KEY_VAL(ht, num_key, str_key, data) { - if (!data) { - continue; - } - if (num_key) { - zval val; - //MSGPACK_CONVERT_COPY_ZVAL(val, &data); - if (msgpack_convert_long_to_properties(ret, &properties, num_key, &val, var) != SUCCESS) { - zval_ptr_dtor(&val); - MSGPACK_WARNING( - "[msgpack] (%s) " + if (str_key == NULL) { + if (msgpack_convert_long_to_properties(ret, return_value, &properties, &prop_pos, num_key, data, var) != SUCCESS) { + MSGPACK_WARNING("[msgpack] (%s) " "illegal offset type, skip this decoding", __FUNCTION__); } - break; - } else if (str_key) { - break; - } else { - MSGPACK_WARNING( - "[msgpack] (%s) key is not string nor array", - __FUNCTION__); - break; } } ZEND_HASH_FOREACH_END(); zend_hash_destroy(var); FREE_HASHTABLE(var); } else { - HashPosition valpos; int (*convert_function)(zval *, zval *, zval **) = NULL; - zval **arydata, aryval, *aryval_p; - aryval_p = &aryval; + const char *class_name, *prop_name; + size_t prop_len; + zval *aryval; - ZEND_HASH_FOREACH_KEY_VAL(ret, num_key, str_key, data) { - if (!data) { - MSGPACK_WARNING( - "[msgpack] (%s) can't get data value by index", - __FUNCTION__); + num_key = 0; + ZEND_HASH_FOREACH_STR_KEY_VAL(ret, str_key, data) { + aryval = zend_hash_index_find(ht, num_key); + + if (data == NULL) { + MSGPACK_WARNING("[msgpack] (%s) can't get data value by index", __FUNCTION__); return FAILURE; } - switch (Z_TYPE_P(data)) - { + switch (Z_TYPE_P(data)) { case IS_ARRAY: convert_function = msgpack_convert_array; break; @@ -490,30 +468,26 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { // class members, so it's not wise to allow convert_function = msgpack_convert_object; break; - default: - break; } - MSGPACK_CONVERT_COPY_ZVAL(aryval, &data); + zend_unmangle_property_name_ex(str_key, &class_name, &prop_name, &prop_len); if (convert_function) { - zval rv; - - if (convert_function(&rv, data, &aryval_p) != SUCCESS) { - zval_ptr_dtor(&aryval); - MSGPACK_WARNING( - "[msgpack] (%s) " - "convert failure in convert_object", - __FUNCTION__); - return FAILURE; - } - - zend_symtable_update(ret, str_key, &rv); + zval nv; + //if (convert_function(&nv, str_key, &data) != SUCCESS) { + // //zval_ptr_dtor(&aryval); + // MSGPACK_WARNING("[msgpack] (%s) " + // "convert failure in convert_object", + // __FUNCTION__); + // return FAILURE; + //} + + //zend_update_property(ce, return_value, str_key->val, str_key->len, &nv); } else { - zend_symtable_update(ret, str_key, &aryval); + zend_update_property(ce, return_value, prop_name, prop_len, aryval); } + num_key++; } ZEND_HASH_FOREACH_END(); - } zval_ptr_dtor(*value); break; @@ -523,16 +497,11 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { HashTable *properties = NULL; HashPosition prop_pos; - properties = Z_OBJ_HT_P(return_value)->get_properties( - return_value TSRMLS_CC); + properties = Z_OBJ_HT_P(return_value)->get_properties(return_value TSRMLS_CC); zend_hash_internal_pointer_reset_ex(properties, &prop_pos); - if (msgpack_convert_long_to_properties( - HASH_OF(return_value), &properties, - 0, *value, NULL) != SUCCESS) - { - MSGPACK_WARNING( - "[msgpack] (%s) illegal offset type, skip this decoding", + if (msgpack_convert_long_to_properties(HASH_OF(return_value), return_value, &properties, &prop_pos, 0, *value, NULL) != SUCCESS) { + MSGPACK_WARNING("[msgpack] (%s) illegal offset type, skip this decoding", __FUNCTION__); } break; From db405c4baddd1fc2971bd7ba1d17f37ecaed360d Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Tue, 26 May 2015 15:39:43 +0000 Subject: [PATCH 67/75] Fix memory leak when serializing a class with a unserialize entry --- msgpack_unpack.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 1ba99b6..700e220 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -133,7 +133,7 @@ inline static void msgpack_stack_pop(msgpack_unserialize_data_t *var_hashx, long } inline static zend_class_entry* msgpack_unserialize_class( - zval **container, char *class_name, size_t name_len) + zval **container, char *class_name, size_t name_len, zend_bool init_class) { zend_class_entry *ce; zend_bool incomplete_class = 0; @@ -199,7 +199,9 @@ inline static zend_class_entry* msgpack_unserialize_class( return NULL; } - object_init_ex(container_val, ce); + if (init_class || incomplete_class) { + object_init_ex(container_val, ce); + } /* store incomplete class name */ if (incomplete_class) @@ -481,8 +483,7 @@ int msgpack_unserialize_map_item( break; } } else if (Z_TYPE_P(val) == IS_STRING) { - ce = msgpack_unserialize_class( - container, Z_STRVAL_P(val), Z_STRLEN_P(val)); + ce = msgpack_unserialize_class(container, Z_STRVAL_P(val), Z_STRLEN_P(val), 1); if (ce == NULL) { MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); @@ -499,7 +500,7 @@ int msgpack_unserialize_map_item( case MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT: unpack->type = MSGPACK_SERIALIZE_TYPE_NONE; - ce = msgpack_unserialize_class(container, Z_STRVAL_P(key), Z_STRLEN_P(key)); + ce = msgpack_unserialize_class(container, Z_STRVAL_P(key), Z_STRLEN_P(key), 0); if (ce == NULL) { MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); From 38669349f95e986601587e0ce27e384a9058ae44 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Wed, 27 May 2015 03:43:35 +0000 Subject: [PATCH 68/75] Update msgpack_convert_long_to_properties to properly detect keys --- msgpack.c | 9 ++------- msgpack_convert.c | 28 +++++++++++++--------------- msgpack_unpack.c | 11 ++++------- 3 files changed, 19 insertions(+), 29 deletions(-) diff --git a/msgpack.c b/msgpack.c index c571eb9..bf09ea2 100644 --- a/msgpack.c +++ b/msgpack.c @@ -124,9 +124,7 @@ static ZEND_MINFO_FUNCTION(msgpack) } zend_module_entry msgpack_module_entry = { -#if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, -#endif "msgpack", msgpack_functions, ZEND_MINIT(msgpack), @@ -134,9 +132,7 @@ zend_module_entry msgpack_module_entry = { NULL, NULL, ZEND_MINFO(msgpack), -#if ZEND_MODULE_API_NO >= 20010901 PHP_MSGPACK_VERSION, -#endif STANDARD_MODULE_PROPERTIES }; @@ -192,13 +188,12 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) //unhandled non-string key } } ZEND_HASH_FOREACH_END(); + zval_ptr_dtor(&tmp); } else { msgpack_unserialize_var_destroy(&var_hash, 1); } - zval_ptr_dtor(&tmp); - return SUCCESS; } #endif @@ -309,6 +304,6 @@ static ZEND_FUNCTION(msgpack_unserialize) if (msgpack_convert_template(return_value, object, &zv_p) != SUCCESS) { RETURN_NULL(); } - zval_ptr_dtor(object); + } } diff --git a/msgpack_convert.c b/msgpack_convert.c index 0c53b95..1373ae7 100644 --- a/msgpack_convert.c +++ b/msgpack_convert.c @@ -11,7 +11,7 @@ inline int msgpack_convert_long_to_properties( { if (*properties != NULL) { zval *data, tplval, *dataval, prop_key_zv; - zend_string *prop_key; + zend_string *prop_key, *unmangled_prop_key; ulong prop_key_index; const char *class_name, *prop_name; size_t prop_len; @@ -19,12 +19,11 @@ inline int msgpack_convert_long_to_properties( for (;; zend_hash_move_forward_ex(*properties, prop_pos)) { if (zend_hash_get_current_key_ex(*properties, &prop_key, &prop_key_index, prop_pos) == HASH_KEY_IS_STRING) { zend_unmangle_property_name_ex(prop_key, &class_name, &prop_name, &prop_len); + ZVAL_NEW_STR(&prop_key_zv, prop_key); + unmangled_prop_key = zend_string_init(prop_name, prop_len, 0); - if (var == NULL || !zend_hash_exists(var, prop_key)) { + if (var == NULL || !zend_hash_exists(var, unmangled_prop_key)) { if ((data = zend_hash_find(ht, prop_key)) != NULL) { - prop_key = zend_string_init(prop_name, prop_len, 0); - ZVAL_NEW_STR(&prop_key_zv, prop_key); - switch (Z_TYPE_P(data)) { case IS_ARRAY: { @@ -35,7 +34,7 @@ inline int msgpack_convert_long_to_properties( MSGPACK_WARNING("[msgpack] (%s) " "can't get data value by index", __FUNCTION__); - zend_string_release(prop_key); + zend_string_release(unmangled_prop_key); return FAILURE; } @@ -43,10 +42,10 @@ inline int msgpack_convert_long_to_properties( zend_hash_move_forward_ex(*properties, prop_pos); zend_update_property(Z_OBJCE_P(object), object, prop_name, prop_len, &tplval); - zend_string_release(prop_key); + zend_string_release(unmangled_prop_key); return SUCCESS; } - zend_string_release(prop_key); + zend_string_release(unmangled_prop_key); return FAILURE; } case IS_OBJECT: @@ -54,21 +53,21 @@ inline int msgpack_convert_long_to_properties( if (msgpack_convert_object(&tplval, data, &val) == SUCCESS) { zend_hash_move_forward_ex(*properties, prop_pos); zend_update_property(Z_OBJCE_P(object), object, prop_name, prop_len, &tplval); - zend_string_release(prop_key); + zend_string_release(unmangled_prop_key); return SUCCESS; } - zend_string_release(prop_key); + zend_string_release(unmangled_prop_key); return FAILURE; } default: zend_hash_move_forward_ex(*properties, prop_pos); zend_update_property(Z_OBJCE_P(object), object, prop_name, prop_len, val); - zend_string_release(prop_key); + zend_string_release(unmangled_prop_key); return SUCCESS; } } } - zend_string_release(prop_key); + zend_string_release(unmangled_prop_key); } else { break; } @@ -345,9 +344,8 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { if (Z_TYPE_P(*value) == IS_OBJECT) { zend_class_entry *vce; - vce = Z_OBJCE_P(tpl); - if (strcmp(ce->name->val, vce->name->val) == 0) - { + vce = Z_OBJCE_P(*value); + if (zend_string_equals(ce->name, vce->name)) { *return_value = **value; zval_copy_ctor(return_value); zval_ptr_dtor(*value); diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 700e220..e3d0a99 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -544,15 +544,12 @@ int msgpack_unserialize_map_item( } *container = rval; - - - if (type == MSGPACK_SERIALIZE_TYPE_OBJECT) { - ZVAL_UNREF(*container); - } else if (type == MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE) { + if (type == MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE) { ZVAL_MAKE_REF(*container); } - - if (Z_REFCOUNTED_P(*container)) Z_TRY_ADDREF_P(*container); + if (Z_REFCOUNTED_P(*container)) { + Z_TRY_ADDREF_P(*container); + } MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); From fd19e23e28131ddbfb0e7903e329b0410907fa0d Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Thu, 28 May 2015 05:11:10 +0000 Subject: [PATCH 69/75] Finish converting msgpack_convert_array --- msgpack_convert.c | 321 ++++++++++++++++++++++------------------------ 1 file changed, 152 insertions(+), 169 deletions(-) diff --git a/msgpack_convert.c b/msgpack_convert.c index 1373ae7..afe8040 100644 --- a/msgpack_convert.c +++ b/msgpack_convert.c @@ -116,211 +116,194 @@ static inline int msgpack_convert_string_to_properties( int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) { - if (Z_TYPE_P(tpl) == IS_ARRAY) - { - HashTable *ht, *htval; - int num; - zend_string *key_str; - ulong key_long; - zval *data; + if (Z_TYPE_P(tpl) != IS_ARRAY) { + MSGPACK_WARNING("[msgpack] (%s) template is not array", __FUNCTION__); + zval_ptr_dtor(*value); + return FAILURE; + } + zend_string *key; + int key_type; + ulong key_index; + zval *data, *arydata; + HashPosition pos, valpos; + HashTable *ht, *htval; - ht = HASH_OF(tpl); - // TODO: maybe need to release memory? - array_init(return_value); + ht = HASH_OF(tpl); + array_init(return_value); - num = zend_hash_num_elements(ht); - if (num <= 0) - { - MSGPACK_WARNING( - "[msgpack] (%s) template array length is 0", + if (zend_hash_num_elements(ht) <= 0) { + MSGPACK_WARNING("[msgpack] (%s) template array length is 0", __FUNCTION__); + zval_ptr_dtor(*value); + return FAILURE; + } + + /* string */ + if (ht->nNumOfElements != ht->nNextFreeElement) { + htval = HASH_OF(*value); + if (!htval) { + MSGPACK_WARNING( + "[msgpack] (%s) input data is not array", + __FUNCTION__); zval_ptr_dtor(*value); return FAILURE; } - /* string */ - if (ht->nNumOfElements != ht->nNextFreeElement) + zend_hash_internal_pointer_reset_ex(ht, &pos); + zend_hash_internal_pointer_reset_ex(htval, &valpos); + for (;; zend_hash_move_forward_ex(ht, &pos), zend_hash_move_forward_ex(htval, &valpos)) { - htval = HASH_OF(*value); - if (!htval) - { - MSGPACK_WARNING( - "[msgpack] (%s) input data is not array", - __FUNCTION__); - zval_ptr_dtor(*value); - return FAILURE; + key_type = zend_hash_get_current_key_ex(ht, &key, &key_index, &pos); + + if (key_type == HASH_KEY_NON_EXISTENT) { + break; } - ZEND_HASH_FOREACH_KEY_VAL(ht, key_long, key_str, data) { - if (key_str) { - int (*convert_function)(zval *, zval *, zval **) = NULL; - zval **dataval, *val; + if ((data = zend_hash_get_current_data_ex(ht, &pos)) == NULL) { + continue; + } - switch (Z_TYPE_P(data)) - { - case IS_ARRAY: - convert_function = msgpack_convert_array; - break; - case IS_OBJECT: - convert_function = msgpack_convert_object; - break; - default: - break; - } + if (key_type == HASH_KEY_IS_STRING) { + int (*convert_function)(zval *, zval *, zval **) = NULL; + zval *dataval, *val; - if (!data) { - MSGPACK_WARNING( - "[msgpack] (%s) can't get data", - __FUNCTION__); - zval_ptr_dtor(*value); - return FAILURE; - } + switch (Z_TYPE_P(data)) { + case IS_ARRAY: + convert_function = msgpack_convert_array; + break; + case IS_OBJECT: + // case IS_STRING: + convert_function = msgpack_convert_object; + break; + default: + break; + } - if (convert_function) - { - zval *rv; - if (convert_function(rv, data, &val) != SUCCESS) - { - zval_ptr_dtor(val); - return FAILURE; - } - add_assoc_zval_ex(return_value, key_str->val, key_str->len, rv); - } - else - { - add_assoc_zval_ex(return_value, key_str->val, key_str->len, val); - } + if ((dataval = zend_hash_get_current_data_ex(htval, &valpos)) == NULL) { + MSGPACK_WARNING("[msgpack] (%s) can't get data", __FUNCTION__); + zval_ptr_dtor(*value); + return FAILURE; + } + MSGPACK_CONVERT_COPY_ZVAL(val, dataval); + if (convert_function) { + zval rv; + if (convert_function(&rv, data, &val) != SUCCESS) { + zval_ptr_dtor(val); + return FAILURE; + } + add_assoc_zval_ex(return_value, key->val, key->len, &rv); + } else { + add_assoc_zval_ex(return_value, key->val, key->len, val); } + } + } - } ZEND_HASH_FOREACH_END(); + zval_ptr_dtor(*value); + return SUCCESS; + } else { + /* index */ + int (*convert_function)(zval *, zval *, zval **) = NULL; + if (Z_TYPE_P(*value) != IS_ARRAY) { + MSGPACK_WARNING("[msgpack] (%s) unserialized data must be array.", __FUNCTION__); zval_ptr_dtor(*value); - - return SUCCESS; + return FAILURE; } - else - { - /* index */ - int (*convert_function)(zval *, zval *, zval **) = NULL; - int first_loop = 0; - - if (Z_TYPE_P(*value) != IS_ARRAY) - { - MSGPACK_WARNING( - "[msgpack] (%s) unserialized data must be array.", + + zend_hash_internal_pointer_reset_ex(ht, &pos); + key_type = zend_hash_get_current_key_ex(ht, &key, &key_index, &pos); + + if (key_type == HASH_KEY_NON_EXISTENT) { + MSGPACK_WARNING( + "[msgpack] (%s) first element in template array is empty", __FUNCTION__); - zval_ptr_dtor(*value); - return FAILURE; - } + zval_ptr_dtor(*value); + return FAILURE; + } - ZEND_HASH_FOREACH_KEY_VAL(ht, key_long, key_str, data) { - if (first_loop) { - if (!key_long && !key_str) { - MSGPACK_WARNING( - "[msgpack] (%s) first element in template array is empty", - __FUNCTION__); - zval_ptr_dtor(*value); - return FAILURE; - } + if ((data = zend_hash_get_current_data_ex(ht, &pos)) == NULL) { + MSGPACK_WARNING("[msgpack] (%s) invalid template: empty array?", __FUNCTION__); + zval_ptr_dtor(*value); + return FAILURE; + } - if (!data) { - MSGPACK_WARNING( - "[msgpack] (%s) invalid template: empty array?", - __FUNCTION__); - zval_ptr_dtor(*value); - return FAILURE; - } + switch (Z_TYPE_P(data)) + { + case IS_ARRAY: + convert_function = msgpack_convert_array; + break; + case IS_OBJECT: + case IS_STRING: + convert_function = msgpack_convert_object; + break; + default: + break; + } - switch (Z_TYPE_P(data)) { - case IS_ARRAY: - convert_function = msgpack_convert_array; - break; - case IS_OBJECT: - case IS_STRING: - convert_function = msgpack_convert_object; - break; - default: - break; - } + htval = HASH_OF(*value); + if (zend_hash_num_elements(htval) <= 0) { + MSGPACK_WARNING("[msgpack] (%s) array length is 0 in unserialized data", __FUNCTION__); + zval_ptr_dtor(*value); + return FAILURE; + } - htval = HASH_OF(*value); - num = zend_hash_num_elements(htval); - if (num <= 0) { - MSGPACK_WARNING( - "[msgpack] (%s) array length is 0 in unserialized data", - __FUNCTION__); - zval_ptr_dtor(*value); - return FAILURE; - } + zend_hash_internal_pointer_reset_ex(htval, &valpos); + for (;; zend_hash_move_forward_ex(htval, &valpos)) { + key_type = zend_hash_get_current_key_ex(htval, &key, &key_index, &valpos); + if (key_type == HASH_KEY_NON_EXISTENT) { + break; + } - first_loop = 1; - } else { - if (!data) { - MSGPACK_WARNING( - "[msgpack] (%s) can't get next data in indexed array", - __FUNCTION__); - continue; - } else if (key_long) { - zval *aryval, *rv; - if (convert_function) - { - if (convert_function(rv, data, &aryval) != SUCCESS) - { - zval_ptr_dtor(aryval); + if ((arydata = zend_hash_get_current_data_ex(htval, &valpos)) == NULL) { + MSGPACK_WARNING( "[msgpack] (%s) can't get next data in indexed array", __FUNCTION__); + continue; + } + + switch (key_type) { + case HASH_KEY_IS_LONG: { + zval rv; + if (convert_function) { + if (convert_function(&rv, data, &arydata) != SUCCESS) { MSGPACK_WARNING( - "[msgpack] (%s) " - "convert failure in HASH_KEY_IS_LONG " - "in indexed array", - __FUNCTION__); + "[msgpack] (%s) " + "convert failure in HASH_KEY_IS_LONG " + "in indexed array", + __FUNCTION__); zval_ptr_dtor(*value); return FAILURE; } - add_next_index_zval(return_value, rv); - } - else - { - add_next_index_zval(return_value, aryval); + add_next_index_zval(return_value, &rv); + } else { + add_next_index_zval(return_value, arydata); } break; - } else if (key_str) { - MSGPACK_WARNING( - "[msgpack] (%s) key is string", - __FUNCTION__); - zval_ptr_dtor(*value); - return FAILURE; - } else { - MSGPACK_WARNING( - "[msgpack] (%s) key is not string nor array", - __FUNCTION__); - zval_ptr_dtor(*value); - return FAILURE; } - } - } ZEND_HASH_FOREACH_END(); - - zval_ptr_dtor(*value); - return SUCCESS; + case HASH_KEY_IS_STRING: + MSGPACK_WARNING("[msgpack] (%s) key is string", __FUNCTION__); + zval_ptr_dtor(*value); + return FAILURE; + default: + MSGPACK_WARNING("[msgpack] (%s) key is not string nor array", __FUNCTION__); + zval_ptr_dtor(*value); + return FAILURE; + } } - } - else - { - // shouldn't reach - MSGPACK_WARNING( - "[msgpack] (%s) template is not array", - __FUNCTION__); - zval_ptr_dtor(*value); - return FAILURE; + + //zval_ptr_dtor(*value); + return SUCCESS; } // shouldn't reach zval_ptr_dtor(*value); return FAILURE; + } + int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { zend_class_entry *ce; @@ -472,13 +455,13 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { if (convert_function) { zval nv; - //if (convert_function(&nv, str_key, &data) != SUCCESS) { - // //zval_ptr_dtor(&aryval); - // MSGPACK_WARNING("[msgpack] (%s) " - // "convert failure in convert_object", - // __FUNCTION__); - // return FAILURE; - //} + if (convert_function(&nv, data, &aryval) != SUCCESS) { + zval_ptr_dtor(aryval); + MSGPACK_WARNING("[msgpack] (%s) " + "convert failure in convert_object", + __FUNCTION__); + return FAILURE; + } //zend_update_property(ce, return_value, str_key->val, str_key->len, &nv); } else { From edcaedac46d95045d1a01d9da78bbbc240836625 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Fri, 29 May 2015 05:09:23 +0000 Subject: [PATCH 70/75] ZEND_HASH_FOREACH_KEY_VAL -> ZEND_HASH_FOREACH_STR_KEY_VAL ulong key was unused --- msgpack.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/msgpack.c b/msgpack.c index bf09ea2..502d225 100644 --- a/msgpack.c +++ b/msgpack.c @@ -93,11 +93,8 @@ static ZEND_MINIT_FUNCTION(msgpack) msgpack_init_class(); -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 1) - REGISTER_LONG_CONSTANT( - "MESSAGEPACK_OPT_PHPONLY", MSGPACK_CLASS_OPT_PHPONLY, - CONST_CS | CONST_PERSISTENT); -#endif + REGISTER_LONG_CONSTANT("MESSAGEPACK_OPT_PHPONLY", + MSGPACK_CLASS_OPT_PHPONLY, CONST_CS | CONST_PERSISTENT); return SUCCESS; } @@ -161,7 +158,6 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) { int ret; zend_string *key_str; - ulong key_long; zval tmp, *value; size_t off = 0; msgpack_unpack_t mp; @@ -180,7 +176,7 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) msgpack_unserialize_set_return_value(&var_hash, &tmp); msgpack_unserialize_var_destroy(&var_hash, 0); - ZEND_HASH_FOREACH_KEY_VAL(HASH_OF(&tmp), key_long, key_str, value) { + ZEND_HASH_FOREACH_STR_KEY_VAL(HASH_OF(&tmp), key_str, value) { if (key_str) { php_set_session_var(key_str, value, NULL); php_add_session_var(key_str); @@ -189,8 +185,7 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) } } ZEND_HASH_FOREACH_END(); zval_ptr_dtor(&tmp); - } - else { + } else { msgpack_unserialize_var_destroy(&var_hash, 1); } From c51a4999666ead927fbe12d367b1ee07f14a7e52 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sat, 30 May 2015 04:37:43 +0000 Subject: [PATCH 71/75] Fix unpacking code, we can't just reuse the stack anymore since the zval's are still used by non_dtor members --- msgpack_convert.c | 4 +--- msgpack_unpack.c | 35 +++-------------------------------- 2 files changed, 4 insertions(+), 35 deletions(-) diff --git a/msgpack_convert.c b/msgpack_convert.c index afe8040..2eaf194 100644 --- a/msgpack_convert.c +++ b/msgpack_convert.c @@ -186,11 +186,9 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) return FAILURE; } - MSGPACK_CONVERT_COPY_ZVAL(val, dataval); - if (convert_function) { zval rv; - if (convert_function(&rv, data, &val) != SUCCESS) { + if (convert_function(&rv, data, &dataval) != SUCCESS) { zval_ptr_dtor(val); return FAILURE; } diff --git a/msgpack_unpack.c b/msgpack_unpack.c index e3d0a99..49b1011 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -17,7 +17,6 @@ typedef struct { } var_entries; #define MSGPACK_UNSERIALIZE_FINISH_ITEM(_unpack, _count) \ - msgpack_stack_pop(_unpack->var_hash, _count); \ _unpack->stack[_unpack->deps-1]--; \ if (_unpack->stack[_unpack->deps-1] == 0) { \ _unpack->deps--; \ @@ -109,29 +108,6 @@ inline static void msgpack_stack_push(msgpack_unserialize_data_t *var_hashx, zva *rval = &var_hash->data[var_hash->used_slots++]; } - -inline static void msgpack_stack_pop(msgpack_unserialize_data_t *var_hashx, long count) -{ - long i; - var_entries *var_hash = var_hashx->first_dtor; - - while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) { - var_hash = var_hash->next; - } - - if (!var_hash || count <= 0) { - return; - } - - for (i = count; i > 0; i--) { - var_hash->used_slots--; - if (var_hash->used_slots < 0) { - var_hash->used_slots = 0; - break; - } - } -} - inline static zend_class_entry* msgpack_unserialize_class( zval **container, char *class_name, size_t name_len, zend_bool init_class) { @@ -258,9 +234,6 @@ void msgpack_unserialize_var_destroy(msgpack_unserialize_data_t *var_hashx, zend var_hash = var_hashx->first_dtor; while (var_hash) { - for (i = var_hash->used_slots - 1; i >= 0; i--) { - zval_ptr_dtor(&var_hash->data[i]); - } next = var_hash->next; efree(var_hash); var_hash = next; @@ -272,7 +245,7 @@ void msgpack_unserialize_set_return_value(msgpack_unserialize_data_t *var_hashx, if ((var_hash = var_hashx->first) != NULL) { ZVAL_COPY_VALUE(return_value, &var_hash->data[0]); } else if ((var_hash = var_hashx->first_dtor) != NULL) { - ZVAL_COPY(return_value, &var_hash->data[0]); + ZVAL_COPY_VALUE(return_value, &var_hash->data[0]); } } @@ -406,7 +379,7 @@ int msgpack_unserialize_raw( if (len == 0) { ZVAL_STRINGL(*obj, "", 0); } else { - ZVAL_STRINGL(*obj, (char *)data, len); + ZVAL_STRINGL(*obj, data, len); } return 0; @@ -574,8 +547,8 @@ int msgpack_unserialize_map_item( zend_unmangle_property_name_ex(key_zstring, &class_name, &prop_name, &prop_len); zend_update_property(Z_OBJCE_P(container_val), container_val, prop_name, prop_len, val); - zval_ptr_dtor(key); zend_string_release(key_zstring); + zval_ptr_dtor(key); } else { switch (Z_TYPE_P(key)) { case IS_LONG: @@ -617,8 +590,6 @@ int msgpack_unserialize_map_item( } } - msgpack_stack_pop(unpack->var_hash, 2); - deps = unpack->deps - 1; unpack->stack[deps]--; if (unpack->stack[deps] == 0) From 0ecf768a2d81b72a566e387821565e00834fbe05 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sun, 31 May 2015 04:13:31 +0000 Subject: [PATCH 72/75] Finish 'unpack of template convertor' test fails, memory leaks unfixed --- msgpack_class.c | 9 ++------- msgpack_convert.c | 21 ++++++++++++++------- msgpack_unpack.c | 3 --- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/msgpack_class.c b/msgpack_class.c index da095e0..34608dd 100644 --- a/msgpack_class.c +++ b/msgpack_class.c @@ -309,10 +309,7 @@ static ZEND_METHOD(msgpack_unpacker, __construct) static ZEND_METHOD(msgpack_unpacker, __destruct) { php_msgpack_unpacker_t *unpacker = Z_MSGPACK_UNPACKER_P(getThis()); - smart_string_free(&unpacker->buffer); - zval_ptr_dtor(&unpacker->retval); - msgpack_unserialize_var_destroy(&unpacker->var_hash, unpacker->error); } @@ -391,8 +388,6 @@ static ZEND_METHOD(msgpack_unpacker, execute) } if (unpacker->finished) { - zval_ptr_dtor(&unpacker->retval); - msgpack_unserialize_set_return_value(&unpacker->var_hash, &unpacker->retval); msgpack_unserialize_var_destroy(&unpacker->var_hash, unpacker->error); unpacker->error = 0; @@ -447,12 +442,12 @@ static ZEND_METHOD(msgpack_unpacker, data) } if (object == NULL) { - ZVAL_ZVAL(return_value, &unpacker->retval, 1, 0); + ZVAL_COPY_VALUE(return_value, &unpacker->retval); } else { zval zv, *zv_p; zv_p = &zv; - ZVAL_ZVAL(&zv, &unpacker->retval, 1, 0); + ZVAL_COPY_VALUE(return_value, &unpacker->retval); if (msgpack_convert_object(return_value, object, &zv_p) != SUCCESS) { RETURN_NULL(); diff --git a/msgpack_convert.c b/msgpack_convert.c index 2eaf194..067c149 100644 --- a/msgpack_convert.c +++ b/msgpack_convert.c @@ -121,6 +121,9 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) zval_ptr_dtor(*value); return FAILURE; } + if (Z_TYPE_P(*value) == IS_INDIRECT) { + *value = Z_INDIRECT_P(*value); + } zend_string *key; int key_type; @@ -166,7 +169,7 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) if (key_type == HASH_KEY_IS_STRING) { int (*convert_function)(zval *, zval *, zval **) = NULL; - zval *dataval, *val; + zval *dataval; switch (Z_TYPE_P(data)) { case IS_ARRAY: @@ -189,17 +192,17 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) if (convert_function) { zval rv; if (convert_function(&rv, data, &dataval) != SUCCESS) { - zval_ptr_dtor(val); + //zval_ptr_dtor(&val); return FAILURE; } add_assoc_zval_ex(return_value, key->val, key->len, &rv); } else { - add_assoc_zval_ex(return_value, key->val, key->len, val); + add_assoc_zval_ex(return_value, key->val, key->len, dataval); } } } - zval_ptr_dtor(*value); + //zval_ptr_dtor(*value); return SUCCESS; } else { @@ -437,6 +440,10 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { MSGPACK_WARNING("[msgpack] (%s) can't get data value by index", __FUNCTION__); return FAILURE; } + if (Z_TYPE_P(data) == IS_INDIRECT) { + data = Z_INDIRECT_P(data); + } + switch (Z_TYPE_P(data)) { case IS_ARRAY: @@ -454,21 +461,21 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { if (convert_function) { zval nv; if (convert_function(&nv, data, &aryval) != SUCCESS) { - zval_ptr_dtor(aryval); + //zval_ptr_dtor(aryval); MSGPACK_WARNING("[msgpack] (%s) " "convert failure in convert_object", __FUNCTION__); return FAILURE; } - //zend_update_property(ce, return_value, str_key->val, str_key->len, &nv); + zend_update_property(ce, return_value, str_key->val, str_key->len, &nv); } else { zend_update_property(ce, return_value, prop_name, prop_len, aryval); } num_key++; } ZEND_HASH_FOREACH_END(); } - zval_ptr_dtor(*value); + //zval_ptr_dtor(*value); break; } default: diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 49b1011..7df9b15 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -222,9 +222,6 @@ void msgpack_unserialize_var_init(msgpack_unserialize_data_t *var_hashx) void msgpack_unserialize_var_destroy(msgpack_unserialize_data_t *var_hashx, zend_bool err) { void *next; - long i; - zend_bool var_empty = 1; - var_entries *var_hash = var_hashx->first; while (var_hash) { next = var_hash->next; From 138072b17beffa36a78627027a03c9b5ac20fc93 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Wed, 3 Jun 2015 03:36:13 +0000 Subject: [PATCH 73/75] Fixes from review by @zxcvdavid --- msgpack_class.c | 8 ++------ msgpack_convert.c | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/msgpack_class.c b/msgpack_class.c index 34608dd..98aa7dc 100644 --- a/msgpack_class.c +++ b/msgpack_class.c @@ -363,9 +363,8 @@ static ZEND_METHOD(msgpack_unpacker, feed) static ZEND_METHOD(msgpack_unpacker, execute) { char *str = NULL, *data; - long str_len = 0; + size_t len, off, str_len = 0; int ret, error_display = MSGPACK_G(error_display), php_only = MSGPACK_G(php_only); - size_t len, off; zval *offset = NULL; php_msgpack_unpacker_t *unpacker = Z_MSGPACK_UNPACKER_P(getThis()); @@ -376,7 +375,7 @@ static ZEND_METHOD(msgpack_unpacker, execute) if (str) { data = str; len = str_len; - if (offset != NULL) { + if (offset != NULL && (Z_TYPE_P(offset) == IS_LONG || Z_TYPE_P(offset) == IS_DOUBLE)) { off = Z_LVAL_P(offset); } else { off = 0; @@ -457,9 +456,6 @@ static ZEND_METHOD(msgpack_unpacker, data) ZVAL_STRING(&func_name, "reset"); call_user_function_ex(CG(function_table), getThis(), &func_name, &reset_return, 0, NULL, 0, NULL); zval_ptr_dtor(&func_name); - - return; - RETURN_FALSE; } static ZEND_METHOD(msgpack_unpacker, reset) diff --git a/msgpack_convert.c b/msgpack_convert.c index 067c149..caa0373 100644 --- a/msgpack_convert.c +++ b/msgpack_convert.c @@ -80,7 +80,7 @@ inline int msgpack_convert_long_to_properties( return SUCCESS; } -static inline int msgpack_convert_string_to_properties( +static inline int msgpack_convert_string_to_properties( zval *object, char *key, uint key_len, zval *val, HashTable *var) { zend_class_entry *ce = Z_OBJCE_P(object); From 94ad5fdf341aca1bd0ea264bc8a15ecb1866f8e3 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Wed, 3 Jun 2015 05:37:19 +0000 Subject: [PATCH 74/75] Update msgpack_convert_template tests to assert we can create create invalid objects (non-string and 0 length keys) --- msgpack_class.c | 2 +- tests/090.phpt | 141 +----------------------------------------------- tests/091.phpt | 141 +----------------------------------------------- tests/092.phpt | 14 +---- tests/093.phpt | 14 +---- tests/094.phpt | 141 +----------------------------------------------- tests/095.phpt | 141 +----------------------------------------------- tests/096.phpt | 14 +---- tests/097.phpt | 14 +---- tests/098.phpt | 14 +---- tests/099.phpt | 141 +----------------------------------------------- tests/100.phpt | 141 +----------------------------------------------- tests/101.phpt | 14 +---- tests/102.phpt | 14 +---- tests/103.phpt | 14 +---- 15 files changed, 15 insertions(+), 945 deletions(-) diff --git a/msgpack_class.c b/msgpack_class.c index 98aa7dc..9d1de81 100644 --- a/msgpack_class.c +++ b/msgpack_class.c @@ -446,7 +446,7 @@ static ZEND_METHOD(msgpack_unpacker, data) zval zv, *zv_p; zv_p = &zv; - ZVAL_COPY_VALUE(return_value, &unpacker->retval); + ZVAL_COPY_VALUE(zv_p, &unpacker->retval); if (msgpack_convert_object(return_value, object, &zv_p) != SUCCESS) { RETURN_NULL(); diff --git a/tests/090.phpt b/tests/090.phpt index b2a1224..92a4ee7 100644 --- a/tests/090.phpt +++ b/tests/090.phpt @@ -76,7 +76,6 @@ test('array(1, 2, 3, 4)', array(1, 2, 3, 4), 'Obj'); test('array("foo", "foobar", "foohoge")', array("foo", "foobar", "hoge"), 'Obj', new Obj("foo", "foobar", "hoge")); test('array("a" => 1, "b" => 2))', array("a" => 1, "b" => 2), 'Obj', new Obj(1, 2, null)); test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), 'Obj', new Obj(null, null, null, array("one" => 1, "two" => 2))); -test('array("" => "empty")', array("" => "empty"), 'Obj'); test('array("a" => 1, "b" => 2, 3))', array("a" => 1, "b" => 2, 3), 'Obj', new Obj(1, 2, 3)); test('array(3, "a" => 1, "b" => 2))', array(3, "a" => 1, "b" => 2), 'Obj', new Obj(1, 2, 3)); @@ -84,10 +83,6 @@ test('array("a" => 1, 3, "b" => 2))', array("a" => 1, 3, "b" => 2), 'Obj', new O $a = array('foo'); test('array($a, $a)', array($a, $a), 'Obj', new Obj($a, $a, null)); -test('array(&$a, &$a)', array(&$a, &$a), 'Obj', new Obj($a, $a, null)); - -test('array(&$a, $a)', array($a, &$a), 'Obj', new Obj($a, $a, null)); -test('array(&$a, $a)', array(&$a, $a), 'Obj', new Obj($a, $a, null)); $a = array( 'a' => array( @@ -122,15 +117,6 @@ $o1 = new Obj2(1, 2, 3); $o2 = new Obj2(4, 5, 6); test('object', array($o1, $o2), 'Obj', new Obj($o1, $o2)); -$o = new Obj2(1, 2, 3); -test('object', array(&$o, &$o), 'Obj', new Obj($o, $o)); - -$o = new Obj2(1, 2, 3); -test('object', array(&$o, $o), 'Obj', new Obj($o, $o)); - -$o = new Obj2(1, 2, 3); -test('object', array($o, &$o), 'Obj', new Obj($o, $o)); - --EXPECTF-- object(Obj)#%d (3) { ["a"]=> @@ -304,7 +290,7 @@ object(Obj)#%d (4) { int(2) [%r"?c"?:("Obj":)?private"?%r]=> int(3) - [3]=> + ["3"]=> int(4) } SKIP @@ -339,17 +325,6 @@ object(Obj)#%d (5) { int(2) } OK -object(Obj)#%d (4) { - ["a"]=> - NULL - [%r"?b"?:protected"?%r]=> - NULL - [%r"?c"?:("Obj":)?private"?%r]=> - NULL - [""]=> - string(5) "empty" -} -SKIP object(Obj)#%d (3) { ["a"]=> int(1) @@ -392,51 +367,6 @@ object(Obj)#%d (3) { NULL } OK -object(Obj)#%d (3) { - ["a"]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?b"?:protected"?%r]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - array(1) { - [0]=> - string(3) "foo" - } - [%r"?b"?:protected"?%r]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?b"?:protected"?%r]=> - array(1) { - [0]=> - string(3) "foo" - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK object(Obj)#%d (4) { ["a"]=> array(2) { @@ -504,72 +434,3 @@ object(Obj)#%d (3) { NULL } OK -object(Obj)#%d (3) { - ["a"]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?b"?:protected"?%r]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?b"?:protected"?%r]=> - object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?b"?:protected"?%r]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK diff --git a/tests/091.phpt b/tests/091.phpt index 33bb875..80ad0a5 100644 --- a/tests/091.phpt +++ b/tests/091.phpt @@ -78,7 +78,6 @@ test('array(1, 2, 3, 4)', array(1, 2, 3, 4), new Obj()); test('array("foo", "foobar", "foohoge")', array("foo", "foobar", "hoge"), new Obj(), new Obj("foo", "foobar", "hoge")); test('array("a" => 1, "b" => 2))', array("a" => 1, "b" => 2), new Obj(), new Obj(1, 2, null)); test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), new Obj(), new Obj(null, null, null, array("one" => 1, "two" => 2))); -test('array("" => "empty")', array("" => "empty"), new Obj()); test('array("a" => 1, "b" => 2, 3))', array("a" => 1, "b" => 2, 3), new Obj(), new Obj(1, 2, 3)); test('array(3, "a" => 1, "b" => 2))', array(3, "a" => 1, "b" => 2), new Obj(), new Obj(1, 2, 3)); @@ -86,10 +85,6 @@ test('array("a" => 1, 3, "b" => 2))', array("a" => 1, 3, "b" => 2), new Obj(), n $a = array('foo'); test('array($a, $a)', array($a, $a), new Obj(), new Obj($a, $a, null)); -test('array(&$a, &$a)', array(&$a, &$a), new Obj(), new Obj($a, $a, null)); - -test('array(&$a, $a)', array($a, &$a), new Obj(), new Obj($a, $a, null)); -test('array(&$a, $a)', array(&$a, $a), new Obj(), new Obj($a, $a, null)); $a = array( 'a' => array( @@ -124,15 +119,6 @@ $o1 = new Obj2(1, 2, 3); $o2 = new Obj2(4, 5, 6); test('object', array($o1, $o2), new Obj(), new Obj($o1, $o2)); -$o = new Obj2(1, 2, 3); -test('object', array(&$o, &$o), new Obj(), new Obj($o, $o)); - -$o = new Obj2(1, 2, 3); -test('object', array(&$o, $o), new Obj(), new Obj($o, $o)); - -$o = new Obj2(1, 2, 3); -test('object', array($o, &$o), new Obj(), new Obj($o, $o)); - --EXPECTF-- object(Obj)#%d (3) { ["a"]=> @@ -306,7 +292,7 @@ object(Obj)#%d (4) { int(2) [%r"?c"?:("Obj":)?private"?%r]=> int(3) - [3]=> + ["3"]=> int(4) } SKIP @@ -341,17 +327,6 @@ object(Obj)#%d (5) { int(2) } OK -object(Obj)#%d (4) { - ["a"]=> - NULL - [%r"?b"?:protected"?%r]=> - NULL - [%r"?c"?:("Obj":)?private"?%r]=> - NULL - [""]=> - string(5) "empty" -} -SKIP object(Obj)#%d (3) { ["a"]=> int(1) @@ -394,51 +369,6 @@ object(Obj)#%d (3) { NULL } OK -object(Obj)#%d (3) { - ["a"]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?b"?:protected"?%r]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - array(1) { - [0]=> - string(3) "foo" - } - [%r"?b"?:protected"?%r]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?b"?:protected"?%r]=> - array(1) { - [0]=> - string(3) "foo" - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK object(Obj)#%d (4) { ["a"]=> array(2) { @@ -506,72 +436,3 @@ object(Obj)#%d (3) { NULL } OK -object(Obj)#%d (3) { - ["a"]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?b"?:protected"?%r]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?b"?:protected"?%r]=> - object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?b"?:protected"?%r]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK diff --git a/tests/092.phpt b/tests/092.phpt index 9c5dd1a..8c342bf 100644 --- a/tests/092.phpt +++ b/tests/092.phpt @@ -77,7 +77,6 @@ test('array(1, 2, 3, 4)', array(1, 2, 3, 4), 'Obj'); test('array("foo", "foobar", "foohoge")', array("foo", "foobar", "hoge"), 'Obj', new Obj("foo", "foobar", "hoge")); test('array("a" => 1, "b" => 2))', array("a" => 1, "b" => 2), 'Obj', new Obj(1, 2, null)); test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), 'Obj', new Obj(null, null, null, array("one" => 1, "two" => 2))); -test('array("" => "empty")', array("" => "empty"), 'Obj'); test('array("a" => 1, "b" => 2, 3))', array("a" => 1, "b" => 2, 3), 'Obj', new Obj(1, 2, 3)); test('array(3, "a" => 1, "b" => 2))', array(3, "a" => 1, "b" => 2), 'Obj', new Obj(1, 2, 3)); @@ -292,7 +291,7 @@ object(Obj)#%d (4) { int(2) [%r"?c"?:("Obj":)?private"?%r]=> int(3) - [3]=> + ["3"]=> int(4) } SKIP @@ -327,17 +326,6 @@ object(Obj)#%d (5) { int(2) } OK -object(Obj)#%d (4) { - ["a"]=> - NULL - [%r"?b"?:protected"?%r]=> - NULL - [%r"?c"?:("Obj":)?private"?%r]=> - NULL - [""]=> - string(5) "empty" -} -SKIP object(Obj)#%d (3) { ["a"]=> int(1) diff --git a/tests/093.phpt b/tests/093.phpt index f66511e..73980ab 100644 --- a/tests/093.phpt +++ b/tests/093.phpt @@ -79,7 +79,6 @@ test('array(1, 2, 3, 4)', array(1, 2, 3, 4), new Obj()); test('array("foo", "foobar", "foohoge")', array("foo", "foobar", "hoge"), new Obj(), new Obj("foo", "foobar", "hoge")); test('array("a" => 1, "b" => 2))', array("a" => 1, "b" => 2), new Obj(), new Obj(1, 2, null)); test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), new Obj(), new Obj(null, null, null, array("one" => 1, "two" => 2))); -test('array("" => "empty")', array("" => "empty"), new Obj()); test('array("a" => 1, "b" => 2, 3))', array("a" => 1, "b" => 2, 3), new Obj(), new Obj(1, 2, 3)); test('array(3, "a" => 1, "b" => 2))', array(3, "a" => 1, "b" => 2), new Obj(), new Obj(1, 2, 3)); @@ -294,7 +293,7 @@ object(Obj)#%d (4) { int(2) [%r"?c"?:("Obj":)?private"?%r]=> int(3) - [3]=> + ["3"]=> int(4) } SKIP @@ -329,17 +328,6 @@ object(Obj)#%d (5) { int(2) } OK -object(Obj)#%d (4) { - ["a"]=> - NULL - [%r"?b"?:protected"?%r]=> - NULL - [%r"?c"?:("Obj":)?private"?%r]=> - NULL - [""]=> - string(5) "empty" -} -SKIP object(Obj)#%d (3) { ["a"]=> int(1) diff --git a/tests/094.phpt b/tests/094.phpt index a0a40d6..6f6f5b5 100644 --- a/tests/094.phpt +++ b/tests/094.phpt @@ -79,7 +79,6 @@ test('array(1, 2, 3, 4)', array(1, 2, 3, 4), 'Obj'); test('array("foo", "foobar", "foohoge")', array("foo", "foobar", "hoge"), 'Obj', new Obj("foo", "foobar", "hoge")); test('array("a" => 1, "b" => 2))', array("a" => 1, "b" => 2), 'Obj', new Obj(1, 2, null)); test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), 'Obj', new Obj(null, null, null, array("one" => 1, "two" => 2))); -test('array("" => "empty")', array("" => "empty"), 'Obj'); test('array("a" => 1, "b" => 2, 3))', array("a" => 1, "b" => 2, 3), 'Obj', new Obj(1, 2, 3)); test('array(3, "a" => 1, "b" => 2))', array(3, "a" => 1, "b" => 2), 'Obj', new Obj(1, 2, 3)); @@ -87,10 +86,6 @@ test('array("a" => 1, 3, "b" => 2))', array("a" => 1, 3, "b" => 2), 'Obj', new O $a = array('foo'); test('array($a, $a)', array($a, $a), 'Obj', new Obj($a, $a, null)); -test('array(&$a, &$a)', array(&$a, &$a), 'Obj', new Obj($a, $a, null)); - -test('array(&$a, $a)', array($a, &$a), 'Obj', new Obj($a, $a, null)); -test('array(&$a, $a)', array(&$a, $a), 'Obj', new Obj($a, $a, null)); $a = array( 'a' => array( @@ -125,15 +120,6 @@ $o1 = new Obj2(1, 2, 3); $o2 = new Obj2(4, 5, 6); test('object', array($o1, $o2), 'Obj', new Obj($o1, $o2)); -$o = new Obj2(1, 2, 3); -test('object', array(&$o, &$o), 'Obj', new Obj($o, $o)); - -$o = new Obj2(1, 2, 3); -test('object', array(&$o, $o), 'Obj', new Obj($o, $o)); - -$o = new Obj2(1, 2, 3); -test('object', array($o, &$o), 'Obj', new Obj($o, $o)); - --EXPECTF-- object(Obj)#%d (3) { ["a"]=> @@ -307,7 +293,7 @@ object(Obj)#%d (4) { int(2) [%r"?c"?:("Obj":)?private"?%r]=> int(3) - [3]=> + ["3"]=> int(4) } SKIP @@ -342,17 +328,6 @@ object(Obj)#%d (5) { int(2) } OK -object(Obj)#%d (4) { - ["a"]=> - NULL - [%r"?b"?:protected"?%r]=> - NULL - [%r"?c"?:("Obj":)?private"?%r]=> - NULL - [""]=> - string(5) "empty" -} -SKIP object(Obj)#%d (3) { ["a"]=> int(1) @@ -395,51 +370,6 @@ object(Obj)#%d (3) { NULL } OK -object(Obj)#%d (3) { - ["a"]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?b"?:protected"?%r]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - array(1) { - [0]=> - string(3) "foo" - } - [%r"?b"?:protected"?%r]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?b"?:protected"?%r]=> - array(1) { - [0]=> - string(3) "foo" - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK object(Obj)#%d (4) { ["a"]=> array(2) { @@ -507,72 +437,3 @@ object(Obj)#%d (3) { NULL } OK -object(Obj)#%d (3) { - ["a"]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?b"?:protected"?%r]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?b"?:protected"?%r]=> - object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?b"?:protected"?%r]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK diff --git a/tests/095.phpt b/tests/095.phpt index a0feafc..b03eb60 100644 --- a/tests/095.phpt +++ b/tests/095.phpt @@ -81,7 +81,6 @@ test('array(1, 2, 3, 4)', array(1, 2, 3, 4), new Obj()); test('array("foo", "foobar", "foohoge")', array("foo", "foobar", "hoge"), new Obj(), new Obj("foo", "foobar", "hoge")); test('array("a" => 1, "b" => 2))', array("a" => 1, "b" => 2), new Obj(), new Obj(1, 2, null)); test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), new Obj(), new Obj(null, null, null, array("one" => 1, "two" => 2))); -test('array("" => "empty")', array("" => "empty"), new Obj()); test('array("a" => 1, "b" => 2, 3))', array("a" => 1, "b" => 2, 3), new Obj(), new Obj(1, 2, 3)); test('array(3, "a" => 1, "b" => 2))', array(3, "a" => 1, "b" => 2), new Obj(), new Obj(1, 2, 3)); @@ -89,10 +88,6 @@ test('array("a" => 1, 3, "b" => 2))', array("a" => 1, 3, "b" => 2), new Obj(), n $a = array('foo'); test('array($a, $a)', array($a, $a), new Obj(), new Obj($a, $a, null)); -test('array(&$a, &$a)', array(&$a, &$a), new Obj(), new Obj($a, $a, null)); - -test('array(&$a, $a)', array($a, &$a), new Obj(), new Obj($a, $a, null)); -test('array(&$a, $a)', array(&$a, $a), new Obj(), new Obj($a, $a, null)); $a = array( 'a' => array( @@ -127,15 +122,6 @@ $o1 = new Obj2(1, 2, 3); $o2 = new Obj2(4, 5, 6); test('object', array($o1, $o2), new Obj(), new Obj($o1, $o2)); -$o = new Obj2(1, 2, 3); -test('object', array(&$o, &$o), new Obj(), new Obj($o, $o)); - -$o = new Obj2(1, 2, 3); -test('object', array(&$o, $o), new Obj(), new Obj($o, $o)); - -$o = new Obj2(1, 2, 3); -test('object', array($o, &$o), new Obj(), new Obj($o, $o)); - --EXPECTF-- object(Obj)#%d (3) { ["a"]=> @@ -309,7 +295,7 @@ object(Obj)#%d (4) { int(2) [%r"?c"?:("Obj":)?private"?%r]=> int(3) - [3]=> + ["3"]=> int(4) } SKIP @@ -344,17 +330,6 @@ object(Obj)#%d (5) { int(2) } OK -object(Obj)#%d (4) { - ["a"]=> - NULL - [%r"?b"?:protected"?%r]=> - NULL - [%r"?c"?:("Obj":)?private"?%r]=> - NULL - [""]=> - string(5) "empty" -} -SKIP object(Obj)#%d (3) { ["a"]=> int(1) @@ -397,51 +372,6 @@ object(Obj)#%d (3) { NULL } OK -object(Obj)#%d (3) { - ["a"]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?b"?:protected"?%r]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - array(1) { - [0]=> - string(3) "foo" - } - [%r"?b"?:protected"?%r]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?b"?:protected"?%r]=> - array(1) { - [0]=> - string(3) "foo" - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK object(Obj)#%d (4) { ["a"]=> array(2) { @@ -509,72 +439,3 @@ object(Obj)#%d (3) { NULL } OK -object(Obj)#%d (3) { - ["a"]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?b"?:protected"?%r]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?b"?:protected"?%r]=> - object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?b"?:protected"?%r]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK diff --git a/tests/096.phpt b/tests/096.phpt index 06ff215..3ef47e4 100644 --- a/tests/096.phpt +++ b/tests/096.phpt @@ -80,7 +80,6 @@ test('array(1, 2, 3, 4)', array(1, 2, 3, 4), 'Obj'); test('array("foo", "foobar", "foohoge")', array("foo", "foobar", "hoge"), 'Obj', new Obj("foo", "foobar", "hoge")); test('array("a" => 1, "b" => 2))', array("a" => 1, "b" => 2), 'Obj', new Obj(1, 2, null)); test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), 'Obj', new Obj(null, null, null, array("one" => 1, "two" => 2))); -test('array("" => "empty")', array("" => "empty"), 'Obj'); test('array("a" => 1, "b" => 2, 3))', array("a" => 1, "b" => 2, 3), 'Obj', new Obj(1, 2, 3)); test('array(3, "a" => 1, "b" => 2))', array(3, "a" => 1, "b" => 2), 'Obj', new Obj(1, 2, 3)); @@ -295,7 +294,7 @@ object(Obj)#%d (4) { int(2) [%r"?c"?:("Obj":)?private"?%r]=> int(3) - [3]=> + ["3"]=> int(4) } SKIP @@ -330,17 +329,6 @@ object(Obj)#%d (5) { int(2) } OK -object(Obj)#%d (4) { - ["a"]=> - NULL - [%r"?b"?:protected"?%r]=> - NULL - [%r"?c"?:("Obj":)?private"?%r]=> - NULL - [""]=> - string(5) "empty" -} -SKIP object(Obj)#%d (3) { ["a"]=> int(1) diff --git a/tests/097.phpt b/tests/097.phpt index 055a5e4..dd0e4b9 100644 --- a/tests/097.phpt +++ b/tests/097.phpt @@ -82,7 +82,6 @@ test('array(1, 2, 3, 4)', array(1, 2, 3, 4), new Obj()); test('array("foo", "foobar", "foohoge")', array("foo", "foobar", "hoge"), new Obj(), new Obj("foo", "foobar", "hoge")); test('array("a" => 1, "b" => 2))', array("a" => 1, "b" => 2), new Obj(), new Obj(1, 2, null)); test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), new Obj(), new Obj(null, null, null, array("one" => 1, "two" => 2))); -test('array("" => "empty")', array("" => "empty"), new Obj()); test('array("a" => 1, "b" => 2, 3))', array("a" => 1, "b" => 2, 3), new Obj(), new Obj(1, 2, 3)); test('array(3, "a" => 1, "b" => 2))', array(3, "a" => 1, "b" => 2), new Obj(), new Obj(1, 2, 3)); @@ -297,7 +296,7 @@ object(Obj)#%d (4) { int(2) [%r"?c"?:("Obj":)?private"?%r]=> int(3) - [3]=> + ["3"]=> int(4) } SKIP @@ -332,17 +331,6 @@ object(Obj)#%d (5) { int(2) } OK -object(Obj)#%d (4) { - ["a"]=> - NULL - [%r"?b"?:protected"?%r]=> - NULL - [%r"?c"?:("Obj":)?private"?%r]=> - NULL - [""]=> - string(5) "empty" -} -SKIP object(Obj)#%d (3) { ["a"]=> int(1) diff --git a/tests/098.phpt b/tests/098.phpt index 23f3427..0687401 100644 --- a/tests/098.phpt +++ b/tests/098.phpt @@ -80,7 +80,6 @@ test('array(1, 2, 3, 4)', array(1, 2, 3, 4), 'Obj'); test('array("foo", "foobar", "foohoge")', array("foo", "foobar", "hoge"), 'Obj', new Obj("foo", "foobar", "hoge")); test('array("a" => 1, "b" => 2))', array("a" => 1, "b" => 2), 'Obj', new Obj(1, 2, null)); test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), 'Obj', new Obj(null, null, null, array("one" => 1, "two" => 2))); -test('array("" => "empty")', array("" => "empty"), 'Obj'); test('array("a" => 1, "b" => 2, 3))', array("a" => 1, "b" => 2, 3), 'Obj', new Obj(1, 2, 3)); test('array(3, "a" => 1, "b" => 2))', array(3, "a" => 1, "b" => 2), 'Obj', new Obj(1, 2, 3)); @@ -295,7 +294,7 @@ object(Obj)#%d (4) { int(2) [%r"?c"?:("Obj":)?private"?%r]=> int(3) - [3]=> + ["3"]=> int(4) } SKIP @@ -330,17 +329,6 @@ object(Obj)#%d (5) { int(2) } OK -object(Obj)#%d (4) { - ["a"]=> - NULL - [%r"?b"?:protected"?%r]=> - NULL - [%r"?c"?:("Obj":)?private"?%r]=> - NULL - [""]=> - string(5) "empty" -} -SKIP object(Obj)#%d (3) { ["a"]=> int(1) diff --git a/tests/099.phpt b/tests/099.phpt index 01da2ac..3b7e4e8 100644 --- a/tests/099.phpt +++ b/tests/099.phpt @@ -85,7 +85,6 @@ test('array(1, 2, 3, 4)', array(1, 2, 3, 4), 'Obj'); test('array("foo", "foobar", "foohoge")', array("foo", "foobar", "hoge"), 'Obj', new Obj("foo", "foobar", "hoge")); test('array("a" => 1, "b" => 2))', array("a" => 1, "b" => 2), 'Obj', new Obj(1, 2, null)); test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), 'Obj', new Obj(null, null, null, array("one" => 1, "two" => 2))); -test('array("" => "empty")', array("" => "empty"), 'Obj'); test('array("a" => 1, "b" => 2, 3))', array("a" => 1, "b" => 2, 3), 'Obj', new Obj(1, 2, 3)); test('array(3, "a" => 1, "b" => 2))', array(3, "a" => 1, "b" => 2), 'Obj', new Obj(1, 2, 3)); @@ -93,10 +92,6 @@ test('array("a" => 1, 3, "b" => 2))', array("a" => 1, 3, "b" => 2), 'Obj', new O $a = array('foo'); test('array($a, $a)', array($a, $a), 'Obj', new Obj($a, $a, null)); -test('array(&$a, &$a)', array(&$a, &$a), 'Obj', new Obj($a, $a, null)); - -test('array(&$a, $a)', array($a, &$a), 'Obj', new Obj($a, $a, null)); -test('array(&$a, $a)', array(&$a, $a), 'Obj', new Obj($a, $a, null)); $a = array( 'a' => array( @@ -131,15 +126,6 @@ $o1 = new Obj2(1, 2, 3); $o2 = new Obj2(4, 5, 6); test('object', array($o1, $o2), 'Obj', new Obj($o1, $o2)); -$o = new Obj2(1, 2, 3); -test('object', array(&$o, &$o), 'Obj', new Obj($o, $o)); - -$o = new Obj2(1, 2, 3); -test('object', array(&$o, $o), 'Obj', new Obj($o, $o)); - -$o = new Obj2(1, 2, 3); -test('object', array($o, &$o), 'Obj', new Obj($o, $o)); - --EXPECTF-- object(Obj)#%d (3) { ["a"]=> @@ -313,7 +299,7 @@ object(Obj)#%d (4) { int(2) [%r"?c"?:("Obj":)?private"?%r]=> int(3) - [3]=> + ["3"]=> int(4) } SKIP @@ -348,17 +334,6 @@ object(Obj)#%d (5) { int(2) } OK -object(Obj)#%d (4) { - ["a"]=> - NULL - [%r"?b"?:protected"?%r]=> - NULL - [%r"?c"?:("Obj":)?private"?%r]=> - NULL - [""]=> - string(5) "empty" -} -SKIP object(Obj)#%d (3) { ["a"]=> int(1) @@ -401,51 +376,6 @@ object(Obj)#%d (3) { NULL } OK -object(Obj)#%d (3) { - ["a"]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?b"?:protected"?%r]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - array(1) { - [0]=> - string(3) "foo" - } - [%r"?b"?:protected"?%r]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?b"?:protected"?%r]=> - array(1) { - [0]=> - string(3) "foo" - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK object(Obj)#%d (4) { ["a"]=> array(2) { @@ -513,72 +443,3 @@ object(Obj)#%d (3) { NULL } OK -object(Obj)#%d (3) { - ["a"]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?b"?:protected"?%r]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?b"?:protected"?%r]=> - object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?b"?:protected"?%r]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK diff --git a/tests/100.phpt b/tests/100.phpt index 0b82563..270cdb8 100644 --- a/tests/100.phpt +++ b/tests/100.phpt @@ -87,7 +87,6 @@ test('array(1, 2, 3, 4)', array(1, 2, 3, 4), new Obj()); test('array("foo", "foobar", "foohoge")', array("foo", "foobar", "hoge"), new Obj(), new Obj("foo", "foobar", "hoge")); test('array("a" => 1, "b" => 2))', array("a" => 1, "b" => 2), new Obj(), new Obj(1, 2, null)); test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), new Obj(), new Obj(null, null, null, array("one" => 1, "two" => 2))); -test('array("" => "empty")', array("" => "empty"), new Obj()); test('array("a" => 1, "b" => 2, 3))', array("a" => 1, "b" => 2, 3), new Obj(), new Obj(1, 2, 3)); test('array(3, "a" => 1, "b" => 2))', array(3, "a" => 1, "b" => 2), new Obj(), new Obj(1, 2, 3)); @@ -95,10 +94,6 @@ test('array("a" => 1, 3, "b" => 2))', array("a" => 1, 3, "b" => 2), new Obj(), n $a = array('foo'); test('array($a, $a)', array($a, $a), new Obj(), new Obj($a, $a, null)); -test('array(&$a, &$a)', array(&$a, &$a), new Obj(), new Obj($a, $a, null)); - -test('array(&$a, $a)', array($a, &$a), new Obj(), new Obj($a, $a, null)); -test('array(&$a, $a)', array(&$a, $a), new Obj(), new Obj($a, $a, null)); $a = array( 'a' => array( @@ -133,15 +128,6 @@ $o1 = new Obj2(1, 2, 3); $o2 = new Obj2(4, 5, 6); test('object', array($o1, $o2), new Obj(), new Obj($o1, $o2)); -$o = new Obj2(1, 2, 3); -test('object', array(&$o, &$o), new Obj(), new Obj($o, $o)); - -$o = new Obj2(1, 2, 3); -test('object', array(&$o, $o), new Obj(), new Obj($o, $o)); - -$o = new Obj2(1, 2, 3); -test('object', array($o, &$o), new Obj(), new Obj($o, $o)); - --EXPECTF-- object(Obj)#%d (3) { ["a"]=> @@ -315,7 +301,7 @@ object(Obj)#%d (4) { int(2) [%r"?c"?:("Obj":)?private"?%r]=> int(3) - [3]=> + ["3"]=> int(4) } SKIP @@ -350,17 +336,6 @@ object(Obj)#%d (5) { int(2) } OK -object(Obj)#%d (4) { - ["a"]=> - NULL - [%r"?b"?:protected"?%r]=> - NULL - [%r"?c"?:("Obj":)?private"?%r]=> - NULL - [""]=> - string(5) "empty" -} -SKIP object(Obj)#%d (3) { ["a"]=> int(1) @@ -403,51 +378,6 @@ object(Obj)#%d (3) { NULL } OK -object(Obj)#%d (3) { - ["a"]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?b"?:protected"?%r]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - array(1) { - [0]=> - string(3) "foo" - } - [%r"?b"?:protected"?%r]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - &array(1) { - [0]=> - string(3) "foo" - } - [%r"?b"?:protected"?%r]=> - array(1) { - [0]=> - string(3) "foo" - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK object(Obj)#%d (4) { ["a"]=> array(2) { @@ -515,72 +445,3 @@ object(Obj)#%d (3) { NULL } OK -object(Obj)#%d (3) { - ["a"]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?b"?:protected"?%r]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?b"?:protected"?%r]=> - object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK -object(Obj)#%d (3) { - ["a"]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?b"?:protected"?%r]=> - &object(Obj2)#%d (3) { - ["A"]=> - int(1) - [%r"?B"?:protected"?%r]=> - int(2) - [%r"?C"?:("Obj2":)?private"?%r]=> - int(3) - } - [%r"?c"?:("Obj":)?private"?%r]=> - NULL -} -OK diff --git a/tests/101.phpt b/tests/101.phpt index c6f09d5..ba64390 100644 --- a/tests/101.phpt +++ b/tests/101.phpt @@ -86,7 +86,6 @@ test('array(1, 2, 3, 4)', array(1, 2, 3, 4), 'Obj'); test('array("foo", "foobar", "foohoge")', array("foo", "foobar", "hoge"), 'Obj', new Obj("foo", "foobar", "hoge")); test('array("a" => 1, "b" => 2))', array("a" => 1, "b" => 2), 'Obj', new Obj(1, 2, null)); test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), 'Obj', new Obj(null, null, null, array("one" => 1, "two" => 2))); -test('array("" => "empty")', array("" => "empty"), 'Obj'); test('array("a" => 1, "b" => 2, 3))', array("a" => 1, "b" => 2, 3), 'Obj', new Obj(1, 2, 3)); test('array(3, "a" => 1, "b" => 2))', array(3, "a" => 1, "b" => 2), 'Obj', new Obj(1, 2, 3)); @@ -301,7 +300,7 @@ object(Obj)#%d (4) { int(2) [%r"?c"?:("Obj":)?private"?%r]=> int(3) - [3]=> + ["3"]=> int(4) } SKIP @@ -336,17 +335,6 @@ object(Obj)#%d (5) { int(2) } OK -object(Obj)#%d (4) { - ["a"]=> - NULL - [%r"?b"?:protected"?%r]=> - NULL - [%r"?c"?:("Obj":)?private"?%r]=> - NULL - [""]=> - string(5) "empty" -} -SKIP object(Obj)#%d (3) { ["a"]=> int(1) diff --git a/tests/102.phpt b/tests/102.phpt index c91eba5..7644635 100644 --- a/tests/102.phpt +++ b/tests/102.phpt @@ -88,7 +88,6 @@ test('array(1, 2, 3, 4)', array(1, 2, 3, 4), new Obj()); test('array("foo", "foobar", "foohoge")', array("foo", "foobar", "hoge"), new Obj(), new Obj("foo", "foobar", "hoge")); test('array("a" => 1, "b" => 2))', array("a" => 1, "b" => 2), new Obj(), new Obj(1, 2, null)); test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), new Obj(), new Obj(null, null, null, array("one" => 1, "two" => 2))); -test('array("" => "empty")', array("" => "empty"), new Obj()); test('array("a" => 1, "b" => 2, 3))', array("a" => 1, "b" => 2, 3), new Obj(), new Obj(1, 2, 3)); test('array(3, "a" => 1, "b" => 2))', array(3, "a" => 1, "b" => 2), new Obj(), new Obj(1, 2, 3)); @@ -303,7 +302,7 @@ object(Obj)#%d (4) { int(2) [%r"?c"?:("Obj":)?private"?%r]=> int(3) - [3]=> + ["3"]=> int(4) } SKIP @@ -338,17 +337,6 @@ object(Obj)#%d (5) { int(2) } OK -object(Obj)#%d (4) { - ["a"]=> - NULL - [%r"?b"?:protected"?%r]=> - NULL - [%r"?c"?:("Obj":)?private"?%r]=> - NULL - [""]=> - string(5) "empty" -} -SKIP object(Obj)#%d (3) { ["a"]=> int(1) diff --git a/tests/103.phpt b/tests/103.phpt index 60b3da1..d563781 100644 --- a/tests/103.phpt +++ b/tests/103.phpt @@ -86,7 +86,6 @@ test('array(1, 2, 3, 4)', array(1, 2, 3, 4), 'Obj'); test('array("foo", "foobar", "foohoge")', array("foo", "foobar", "hoge"), 'Obj', new Obj("foo", "foobar", "hoge")); test('array("a" => 1, "b" => 2))', array("a" => 1, "b" => 2), 'Obj', new Obj(1, 2, null)); test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), 'Obj', new Obj(null, null, null, array("one" => 1, "two" => 2))); -test('array("" => "empty")', array("" => "empty"), 'Obj'); test('array("a" => 1, "b" => 2, 3))', array("a" => 1, "b" => 2, 3), 'Obj', new Obj(1, 2, 3)); test('array(3, "a" => 1, "b" => 2))', array(3, "a" => 1, "b" => 2), 'Obj', new Obj(1, 2, 3)); @@ -301,7 +300,7 @@ object(Obj)#%d (4) { int(2) [%r"?c"?:("Obj":)?private"?%r]=> int(3) - [3]=> + ["3"]=> int(4) } SKIP @@ -336,17 +335,6 @@ object(Obj)#%d (5) { int(2) } OK -object(Obj)#%d (4) { - ["a"]=> - NULL - [%r"?b"?:protected"?%r]=> - NULL - [%r"?c"?:("Obj":)?private"?%r]=> - NULL - [""]=> - string(5) "empty" -} -SKIP object(Obj)#%d (3) { ["a"]=> int(1) From 7bdfe4b3ab068afe11ecf40593bcf2e4d466cbc5 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Sun, 7 Jun 2015 23:16:48 +0000 Subject: [PATCH 75/75] Cleaning up memory leaks in msgpack_convert.c --- msgpack.c | 2 -- msgpack_class.c | 2 +- msgpack_convert.c | 33 +++++++++++++++++++++------------ msgpack_unpack.c | 1 + 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/msgpack.c b/msgpack.c index 502d225..9663146 100644 --- a/msgpack.c +++ b/msgpack.c @@ -180,8 +180,6 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) if (key_str) { php_set_session_var(key_str, value, NULL); php_add_session_var(key_str); - } else { - //unhandled non-string key } } ZEND_HASH_FOREACH_END(); zval_ptr_dtor(&tmp); diff --git a/msgpack_class.c b/msgpack_class.c index 9d1de81..1b92dc1 100644 --- a/msgpack_class.c +++ b/msgpack_class.c @@ -251,7 +251,7 @@ static ZEND_METHOD(msgpack, unpack) MSGPACK_G(php_only) = base->php_only; if (object == NULL) { - php_msgpack_unserialize(return_value, str->val, str->len TSRMLS_CC); + php_msgpack_unserialize(return_value, str->val, str->len); } else { zval zv, *zv_p; zv_p = &zv; diff --git a/msgpack_convert.c b/msgpack_convert.c index caa0373..ea6d86c 100644 --- a/msgpack_convert.c +++ b/msgpack_convert.c @@ -128,7 +128,7 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) zend_string *key; int key_type; ulong key_index; - zval *data, *arydata; + zval *data, *arydata, nv, *nv_p; HashPosition pos, valpos; HashTable *ht, *htval; @@ -188,22 +188,24 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) zval_ptr_dtor(*value); return FAILURE; } + nv = *dataval; + nv_p = &nv; + zval_copy_ctor(&nv); if (convert_function) { zval rv; - if (convert_function(&rv, data, &dataval) != SUCCESS) { - //zval_ptr_dtor(&val); + if (convert_function(&rv, data, &nv_p) != SUCCESS) { + zval_ptr_dtor(*value); return FAILURE; } add_assoc_zval_ex(return_value, key->val, key->len, &rv); } else { - add_assoc_zval_ex(return_value, key->val, key->len, dataval); + add_assoc_zval_ex(return_value, key->val, key->len, &nv); } } } - //zval_ptr_dtor(*value); - + zval_ptr_dtor(*value); return SUCCESS; } else { /* index */ @@ -264,12 +266,15 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) MSGPACK_WARNING( "[msgpack] (%s) can't get next data in indexed array", __FUNCTION__); continue; } + nv = *arydata; + nv_p = &nv; + zval_copy_ctor(&nv); switch (key_type) { case HASH_KEY_IS_LONG: { zval rv; if (convert_function) { - if (convert_function(&rv, data, &arydata) != SUCCESS) { + if (convert_function(&rv, data, &nv_p) != SUCCESS) { MSGPACK_WARNING( "[msgpack] (%s) " "convert failure in HASH_KEY_IS_LONG " @@ -280,7 +285,7 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) } add_next_index_zval(return_value, &rv); } else { - add_next_index_zval(return_value, arydata); + add_next_index_zval(return_value, &nv); } break; } @@ -295,7 +300,7 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) } } - //zval_ptr_dtor(*value); + zval_ptr_dtor(*value); return SUCCESS; } @@ -307,10 +312,14 @@ int msgpack_convert_array(zval *return_value, zval *tpl, zval **value) int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { zend_class_entry *ce; + zend_string *tpl_zstring; switch (Z_TYPE_P(tpl)) { case IS_STRING: - if ((ce = zend_lookup_class(zval_get_string(tpl))) == NULL) { + tpl_zstring = zval_get_string(tpl); + ce = zend_lookup_class(tpl_zstring); + zend_string_release(tpl_zstring); + if (ce == NULL) { MSGPACK_ERROR("[msgpack] (%s) Class '%s' not found", __FUNCTION__, Z_STRVAL_P(tpl)); return FAILURE; @@ -475,7 +484,7 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { num_key++; } ZEND_HASH_FOREACH_END(); } - //zval_ptr_dtor(*value); + zval_ptr_dtor(*value); break; } default: @@ -490,7 +499,7 @@ int msgpack_convert_object(zval *return_value, zval *tpl, zval **value) { MSGPACK_WARNING("[msgpack] (%s) illegal offset type, skip this decoding", __FUNCTION__); } - break; + zval_ptr_dtor(*value); } } diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 7df9b15..0d49645 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -546,6 +546,7 @@ int msgpack_unserialize_map_item( zend_string_release(key_zstring); zval_ptr_dtor(key); + zval_ptr_dtor(val); } else { switch (Z_TYPE_P(key)) { case IS_LONG: