From c00d83b26a4ae5211e2e7a92c6b8c377aded7b4e Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Sat, 28 Jan 2012 03:57:58 +0000 Subject: [PATCH] Thrift-1453:Don't change types of arguments when serializing with thrift php extension Client:php patch: Dave Watson Don't change types of arguments when serializing with thrift php extension git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1236972 13f79535-47bb-0310-9956-ffa450edef68 --- .../thrift_protocol/php_thrift_protocol.cpp | 74 ++++++++++++++++--- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp b/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp index 3e32cb92..4a0a02f4 100644 --- a/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp +++ b/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp @@ -57,6 +57,10 @@ typedef unsigned long long uint64_t; #error Unknown __BYTE_ORDER #endif +#ifndef Z_ADDREF_P +#define Z_ADDREF_P ZVAL_ADDREF +#endif + enum TType { T_STOP = 0, T_VOID = 1, @@ -764,6 +768,7 @@ void binary_deserialize_spec(zval* zthis, PHPInputTransport& transport, HashTabl } void binary_serialize(int8_t thrift_typeID, PHPOutputTransport& transport, zval** value, HashTable* fieldspec) { + Z_ADDREF_P(*value); // At this point the typeID (and field num, if applicable) should've already been written to the output so all we need to do is write the payload. switch (thrift_typeID) { case T_STOP: @@ -781,29 +786,51 @@ void binary_serialize(int8_t thrift_typeID, PHPOutputTransport& transport, zval* binary_serialize_spec(*value, transport, Z_ARRVAL_P(spec)); } return; case T_BOOL: - if (Z_TYPE_PP(value) != IS_BOOL) convert_to_boolean(*value); + if (Z_TYPE_PP(value) != IS_BOOL) { + SEPARATE_ZVAL(value); + convert_to_boolean(*value); + } transport.writeI8(Z_BVAL_PP(value) ? 1 : 0); + zval_ptr_dtor(value); return; case T_BYTE: - if (Z_TYPE_PP(value) != IS_LONG) convert_to_long(*value); + if (Z_TYPE_PP(value) != IS_LONG) { + SEPARATE_ZVAL(value); + convert_to_long(*value); + } transport.writeI8(Z_LVAL_PP(value)); + zval_ptr_dtor(value); return; case T_I16: - if (Z_TYPE_PP(value) != IS_LONG) convert_to_long(*value); + if (Z_TYPE_PP(value) != IS_LONG) { + SEPARATE_ZVAL(value); + convert_to_long(*value); + } transport.writeI16(Z_LVAL_PP(value)); + zval_ptr_dtor(value); return; case T_I32: - if (Z_TYPE_PP(value) != IS_LONG) convert_to_long(*value); + if (Z_TYPE_PP(value) != IS_LONG) { + SEPARATE_ZVAL(value); + convert_to_long(*value); + } transport.writeI32(Z_LVAL_PP(value)); + zval_ptr_dtor(value); return; case T_I64: case T_U64: { int64_t l_data; #if defined(_LP64) || defined(_WIN64) - if (Z_TYPE_PP(value) != IS_LONG) convert_to_long(*value); + if (Z_TYPE_PP(value) != IS_LONG) { + SEPARATE_ZVAL(value); + convert_to_long(*value); + } l_data = Z_LVAL_PP(value); #else - if (Z_TYPE_PP(value) != IS_DOUBLE) convert_to_double(*value); + if (Z_TYPE_PP(value) != IS_DOUBLE) { + SEPARATE_ZVAL(value); + convert_to_double(*value); + } l_data = (int64_t)Z_DVAL_PP(value); #endif transport.writeI64(l_data); @@ -813,20 +840,32 @@ void binary_serialize(int8_t thrift_typeID, PHPOutputTransport& transport, zval* int64_t c; double d; } a; - if (Z_TYPE_PP(value) != IS_DOUBLE) convert_to_double(*value); + if (Z_TYPE_PP(value) != IS_DOUBLE) { + SEPARATE_ZVAL(value); + convert_to_double(*value); + } a.d = Z_DVAL_PP(value); transport.writeI64(a.c); + zval_ptr_dtor(value); } return; //case T_UTF7: case T_UTF8: case T_UTF16: case T_STRING: - if (Z_TYPE_PP(value) != IS_STRING) convert_to_string(*value); + if (Z_TYPE_PP(value) != IS_STRING) { + SEPARATE_ZVAL(value); + convert_to_string(*value); + } transport.writeString(Z_STRVAL_PP(value), Z_STRLEN_PP(value)); + zval_ptr_dtor(value); return; case T_MAP: { - if (Z_TYPE_PP(value) != IS_ARRAY) convert_to_array(*value); if (Z_TYPE_PP(value) != IS_ARRAY) { + SEPARATE_ZVAL(value); + convert_to_array(*value); + } + if (Z_TYPE_PP(value) != IS_ARRAY) { + zval_ptr_dtor(value); throw_tprotocolexception("Attempt to send an incompatible type as an array (T_MAP)", INVALID_DATA); } HashTable* ht = Z_ARRVAL_PP(value); @@ -850,10 +889,15 @@ void binary_serialize(int8_t thrift_typeID, PHPOutputTransport& transport, zval* binary_serialize_hashtable_key(keytype, transport, ht, key_ptr); binary_serialize(valtype, transport, val_ptr, valspec); } + zval_ptr_dtor(value); } return; case T_LIST: { - if (Z_TYPE_PP(value) != IS_ARRAY) convert_to_array(*value); if (Z_TYPE_PP(value) != IS_ARRAY) { + SEPARATE_ZVAL(value); + convert_to_array(*value); + } + if (Z_TYPE_PP(value) != IS_ARRAY) { + zval_ptr_dtor(value); throw_tprotocolexception("Attempt to send an incompatible type as an array (T_LIST)", INVALID_DATA); } HashTable* ht = Z_ARRVAL_PP(value); @@ -872,10 +916,15 @@ void binary_serialize(int8_t thrift_typeID, PHPOutputTransport& transport, zval* for (zend_hash_internal_pointer_reset_ex(ht, &key_ptr); zend_hash_get_current_data_ex(ht, (void**)&val_ptr, &key_ptr) == SUCCESS; zend_hash_move_forward_ex(ht, &key_ptr)) { binary_serialize(valtype, transport, val_ptr, valspec); } + zval_ptr_dtor(value); } return; case T_SET: { - if (Z_TYPE_PP(value) != IS_ARRAY) convert_to_array(*value); if (Z_TYPE_PP(value) != IS_ARRAY) { + SEPARATE_ZVAL(value); + convert_to_array(*value); + } + if (Z_TYPE_PP(value) != IS_ARRAY) { + zval_ptr_dtor(value); throw_tprotocolexception("Attempt to send an incompatible type as an array (T_SET)", INVALID_DATA); } HashTable* ht = Z_ARRVAL_PP(value); @@ -891,8 +940,11 @@ void binary_serialize(int8_t thrift_typeID, PHPOutputTransport& transport, zval* for (zend_hash_internal_pointer_reset_ex(ht, &key_ptr); zend_hash_get_current_data_ex(ht, (void**)&val_ptr, &key_ptr) == SUCCESS; zend_hash_move_forward_ex(ht, &key_ptr)) { binary_serialize_hashtable_key(keytype, transport, ht, key_ptr); } + zval_ptr_dtor(value); } return; }; + + zval_ptr_dtor(value); char errbuf[128]; sprintf(errbuf, "Unknown thrift typeID %d", thrift_typeID); throw_tprotocolexception(errbuf, INVALID_DATA); -- 2.17.1