2
+----------------------------------------------------------------------+
3
| See COPYING file for further copyright information |
4
+----------------------------------------------------------------------+
5
| Author: Oleg Grenrus <oleg.grenrus@dynamoid.com> |
6
| See CREDITS for contributors |
7
+----------------------------------------------------------------------+
15
# include "ig_win32.h"
20
#include "zend_dynamic_array.h"
21
#include "zend_alloc.h"
22
#include "ext/standard/info.h"
23
#include "ext/standard/php_var.h"
26
# include "ext/session/php_session.h"
27
#endif /* HAVE_PHP_SESSION */
29
#include "ext/standard/php_incomplete_class.h"
31
#if defined(HAVE_APCU_SUPPORT)
32
# include "ext/apcu/apc_serializer.h"
33
#elif defined(HAVE_APC_SUPPORT)
35
# include "apc_serializer.h"
37
# include "ext/apc/apc_serializer.h"
39
#endif /* HAVE_APCU_SUPPORT || HAVE_APC_SUPPORT */
41
#include "php_igbinary.h"
48
# include <inttypes.h>
58
/** Session serializer function prototypes. */
59
PS_SERIALIZER_FUNCS(igbinary);
60
#endif /* HAVE_PHP_SESSION */
62
#if defined(HAVE_APC_SUPPORT) || defined(HAVE_APCU_SUPPORT)
63
/** Apc serializer function prototypes */
64
static int APC_SERIALIZER_NAME(igbinary) (APC_SERIALIZER_ARGS);
65
static int APC_UNSERIALIZER_NAME(igbinary) (APC_UNSERIALIZER_ARGS);
70
/* 00 */ igbinary_type_null, /**< Null. */
72
/* 01 */ igbinary_type_ref8, /**< Array reference. */
73
/* 02 */ igbinary_type_ref16, /**< Array reference. */
74
/* 03 */ igbinary_type_ref32, /**< Array reference. */
76
/* 04 */ igbinary_type_bool_false, /**< Boolean true. */
77
/* 05 */ igbinary_type_bool_true, /**< Boolean false. */
79
/* 06 */ igbinary_type_long8p, /**< Long 8bit positive. */
80
/* 07 */ igbinary_type_long8n, /**< Long 8bit negative. */
81
/* 08 */ igbinary_type_long16p, /**< Long 16bit positive. */
82
/* 09 */ igbinary_type_long16n, /**< Long 16bit negative. */
83
/* 0a */ igbinary_type_long32p, /**< Long 32bit positive. */
84
/* 0b */ igbinary_type_long32n, /**< Long 32bit negative. */
86
/* 0c */ igbinary_type_double, /**< Double. */
88
/* 0d */ igbinary_type_string_empty, /**< Empty string. */
90
/* 0e */ igbinary_type_string_id8, /**< String id. */
91
/* 0f */ igbinary_type_string_id16, /**< String id. */
92
/* 10 */ igbinary_type_string_id32, /**< String id. */
94
/* 11 */ igbinary_type_string8, /**< String. */
95
/* 12 */ igbinary_type_string16, /**< String. */
96
/* 13 */ igbinary_type_string32, /**< String. */
98
/* 14 */ igbinary_type_array8, /**< Array. */
99
/* 15 */ igbinary_type_array16, /**< Array. */
100
/* 16 */ igbinary_type_array32, /**< Array. */
102
/* 17 */ igbinary_type_object8, /**< Object. */
103
/* 18 */ igbinary_type_object16, /**< Object. */
104
/* 19 */ igbinary_type_object32, /**< Object. */
106
/* 1a */ igbinary_type_object_id8, /**< Object string id. */
107
/* 1b */ igbinary_type_object_id16, /**< Object string id. */
108
/* 1c */ igbinary_type_object_id32, /**< Object string id. */
110
/* 1d */ igbinary_type_object_ser8, /**< Object serialized data. */
111
/* 1e */ igbinary_type_object_ser16, /**< Object serialized data. */
112
/* 1f */ igbinary_type_object_ser32, /**< Object serialized data. */
114
/* 20 */ igbinary_type_long64p, /**< Long 64bit positive. */
115
/* 21 */ igbinary_type_long64n, /**< Long 64bit negative. */
117
/* 22 */ igbinary_type_objref8, /**< Object reference. */
118
/* 23 */ igbinary_type_objref16, /**< Object reference. */
119
/* 24 */ igbinary_type_objref32, /**< Object reference. */
121
/* 25 */ igbinary_type_ref, /**< Simple reference */
125
* @author Oleg Grenrus <oleg.grenrus@dynamoid.com>
127
struct igbinary_serialize_data {
128
uint8_t *buffer; /**< Buffer. */
129
size_t buffer_size; /**< Buffer size. */
130
size_t buffer_capacity; /**< Buffer capacity. */
131
bool scalar; /**< Serializing scalar. */
132
bool compact_strings; /**< Check for duplicate strings. */
133
struct hash_si strings; /**< Hash of already serialized strings. */
134
struct hash_si objects; /**< Hash of already serialized objects. */
135
int string_count; /**< Serialized string count, used for back referencing */
136
int error; /**< Error number. Not used. */
137
struct igbinary_memory_manager mm; /**< Memory management functions. */
140
/** String/len pair for the igbinary_unserializer_data.
141
* @author Oleg Grenrus <oleg.grenrus@dynamoid.com>
142
* @see igbinary_unserialize_data.
144
struct igbinary_unserialize_string_pair {
145
char *data; /**< Data. */
146
size_t len; /**< Data length. */
149
/** Unserializer data.
150
* @author Oleg Grenrus <oleg.grenrus@dynamoid.com>
152
struct igbinary_unserialize_data {
153
uint8_t *buffer; /**< Buffer. */
154
size_t buffer_size; /**< Buffer size. */
155
size_t buffer_offset; /**< Current read offset. */
157
struct igbinary_unserialize_string_pair *strings; /**< Unserialized strings. */
158
size_t strings_count; /**< Unserialized string count. */
159
size_t strings_capacity; /**< Unserialized string array capacity. */
161
void **references; /**< Unserialized Arrays/Objects. */
162
size_t references_count; /**< Unserialized array/objects count. */
163
size_t references_capacity; /**< Unserialized array/object array capacity. */
165
int error; /**< Error number. Not used. */
166
smart_str string0_buf; /**< Temporary buffer for strings */
169
/* {{{ Memory allocator wrapper prototypes */
170
static inline void *igbinary_mm_wrapper_malloc(size_t size, void *context);
171
static inline void *igbinary_mm_wrapper_realloc(void *ptr, size_t size, void *context);
172
static inline void igbinary_mm_wrapper_free(void *ptr, void *context);
174
/* {{{ Serializing functions prototypes */
175
inline static int igbinary_serialize_data_init(struct igbinary_serialize_data *igsd, bool scalar, struct igbinary_memory_manager *memory_manager TSRMLS_DC);
176
inline static void igbinary_serialize_data_deinit(struct igbinary_serialize_data *igsd, int free_buffer TSRMLS_DC);
178
inline static int igbinary_serialize_header(struct igbinary_serialize_data *igsd TSRMLS_DC);
180
inline static int igbinary_serialize8(struct igbinary_serialize_data *igsd, uint8_t i TSRMLS_DC);
181
inline static int igbinary_serialize16(struct igbinary_serialize_data *igsd, uint16_t i TSRMLS_DC);
182
inline static int igbinary_serialize32(struct igbinary_serialize_data *igsd, uint32_t i TSRMLS_DC);
183
inline static int igbinary_serialize64(struct igbinary_serialize_data *igsd, uint64_t i TSRMLS_DC);
185
inline static int igbinary_serialize_null(struct igbinary_serialize_data *igsd TSRMLS_DC);
186
inline static int igbinary_serialize_bool(struct igbinary_serialize_data *igsd, int b TSRMLS_DC);
187
inline static int igbinary_serialize_long(struct igbinary_serialize_data *igsd, long l TSRMLS_DC);
188
inline static int igbinary_serialize_double(struct igbinary_serialize_data *igsd, double d TSRMLS_DC);
189
inline static int igbinary_serialize_string(struct igbinary_serialize_data *igsd, char *s, size_t len TSRMLS_DC);
190
inline static int igbinary_serialize_chararray(struct igbinary_serialize_data *igsd, const char *s, size_t len TSRMLS_DC);
192
inline static int igbinary_serialize_array(struct igbinary_serialize_data *igsd, zval *z, bool object, bool incomplete_class TSRMLS_DC);
193
inline static int igbinary_serialize_array_ref(struct igbinary_serialize_data *igsd, zval *z, bool object TSRMLS_DC);
194
inline static int igbinary_serialize_array_sleep(struct igbinary_serialize_data *igsd, zval *z, HashTable *ht, zend_class_entry *ce, bool incomplete_class TSRMLS_DC);
195
inline static int igbinary_serialize_object_name(struct igbinary_serialize_data *igsd, const char *name, size_t name_len TSRMLS_DC);
196
inline static int igbinary_serialize_object(struct igbinary_serialize_data *igsd, zval *z TSRMLS_DC);
198
static int igbinary_serialize_zval(struct igbinary_serialize_data *igsd, zval *z TSRMLS_DC);
200
/* {{{ Unserializing functions prototypes */
201
inline static int igbinary_unserialize_data_init(struct igbinary_unserialize_data *igsd TSRMLS_DC);
202
inline static void igbinary_unserialize_data_deinit(struct igbinary_unserialize_data *igsd TSRMLS_DC);
204
inline static int igbinary_unserialize_header(struct igbinary_unserialize_data *igsd TSRMLS_DC);
206
inline static uint8_t igbinary_unserialize8(struct igbinary_unserialize_data *igsd TSRMLS_DC);
207
inline static uint16_t igbinary_unserialize16(struct igbinary_unserialize_data *igsd TSRMLS_DC);
208
inline static uint32_t igbinary_unserialize32(struct igbinary_unserialize_data *igsd TSRMLS_DC);
209
inline static uint64_t igbinary_unserialize64(struct igbinary_unserialize_data *igsd TSRMLS_DC);
211
inline static int igbinary_unserialize_long(struct igbinary_unserialize_data *igsd, enum igbinary_type t, long *ret TSRMLS_DC);
212
inline static int igbinary_unserialize_double(struct igbinary_unserialize_data *igsd, enum igbinary_type t, double *ret TSRMLS_DC);
213
inline static int igbinary_unserialize_string(struct igbinary_unserialize_data *igsd, enum igbinary_type t, char **s, size_t *len TSRMLS_DC);
214
inline static int igbinary_unserialize_chararray(struct igbinary_unserialize_data *igsd, enum igbinary_type t, char **s, size_t *len TSRMLS_DC);
216
inline static int igbinary_unserialize_array(struct igbinary_unserialize_data *igsd, enum igbinary_type t, zval **z, int object TSRMLS_DC);
217
inline static int igbinary_unserialize_object(struct igbinary_unserialize_data *igsd, enum igbinary_type t, zval **z TSRMLS_DC);
218
inline static int igbinary_unserialize_object_ser(struct igbinary_unserialize_data *igsd, enum igbinary_type t, zval **z, zend_class_entry *ce TSRMLS_DC);
219
inline static int igbinary_unserialize_ref(struct igbinary_unserialize_data *igsd, enum igbinary_type t, zval **z TSRMLS_DC);
221
static int igbinary_unserialize_zval(struct igbinary_unserialize_data *igsd, zval **z TSRMLS_DC);
224
ZEND_BEGIN_ARG_INFO_EX(arginfo_igbinary_serialize, 0, 0, 1)
225
ZEND_ARG_INFO(0, value)
228
ZEND_BEGIN_ARG_INFO_EX(arginfo_igbinary_unserialize, 0, 0, 1)
229
ZEND_ARG_INFO(0, str)
232
/* {{{ igbinary_functions[] */
233
/** Exported php functions. */
234
zend_function_entry igbinary_functions[] = {
235
PHP_FE(igbinary_serialize, arginfo_igbinary_serialize)
236
PHP_FE(igbinary_unserialize, arginfo_igbinary_unserialize)
241
/* {{{ igbinary dependencies */
242
#if ZEND_MODULE_API_NO >= 20050922
243
static const zend_module_dep igbinary_module_deps[] = {
244
ZEND_MOD_REQUIRED("standard")
245
#ifdef HAVE_PHP_SESSION
246
ZEND_MOD_REQUIRED("session")
248
#if defined(HAVE_APCU_SUPPORT)
249
ZEND_MOD_OPTIONAL("apcu")
250
#elif defined(HAVE_APC_SUPPORT)
251
ZEND_MOD_OPTIONAL("apc")
258
/* {{{ igbinary_module_entry */
259
zend_module_entry igbinary_module_entry = {
260
#if ZEND_MODULE_API_NO >= 20050922
261
STANDARD_MODULE_HEADER_EX, NULL,
262
igbinary_module_deps,
263
#elif ZEND_MODULE_API_NO >= 20010901
264
STANDARD_MODULE_HEADER,
269
PHP_MSHUTDOWN(igbinary),
273
#if ZEND_MODULE_API_NO >= 20010901
274
PHP_IGBINARY_VERSION, /* Replace with version number for your extension */
276
STANDARD_MODULE_PROPERTIES
280
ZEND_DECLARE_MODULE_GLOBALS(igbinary)
282
/* {{{ ZEND_GET_MODULE */
283
#ifdef COMPILE_DL_IGBINARY
284
ZEND_GET_MODULE(igbinary)
288
/* {{{ INI entries */
290
STD_PHP_INI_BOOLEAN("igbinary.compact_strings", "1", PHP_INI_ALL, OnUpdateBool, compact_strings, zend_igbinary_globals, igbinary_globals)
294
/* {{{ php_igbinary_init_globals */
295
static void php_igbinary_init_globals(zend_igbinary_globals *igbinary_globals) {
296
igbinary_globals->compact_strings = 1;
300
/* {{{ PHP_MINIT_FUNCTION */
301
PHP_MINIT_FUNCTION(igbinary) {
303
(void) module_number;
304
ZEND_INIT_MODULE_GLOBALS(igbinary, php_igbinary_init_globals, NULL);
307
php_session_register_serializer("igbinary",
308
PS_SERIALIZER_ENCODE_NAME(igbinary),
309
PS_SERIALIZER_DECODE_NAME(igbinary));
312
#if defined(HAVE_APC_SUPPORT) || defined(HAVE_APCU_SUPPORT)
313
apc_register_serializer("igbinary",
314
APC_SERIALIZER_NAME(igbinary),
315
APC_UNSERIALIZER_NAME(igbinary),
319
REGISTER_INI_ENTRIES();
324
/* {{{ PHP_MSHUTDOWN_FUNCTION */
325
PHP_MSHUTDOWN_FUNCTION(igbinary) {
327
(void) module_number;
330
ts_free_id(igbinary_globals_id);
334
* unregister serializer?
336
UNREGISTER_INI_ENTRIES();
341
/* {{{ PHP_MINFO_FUNCTION */
342
PHP_MINFO_FUNCTION(igbinary) {
344
php_info_print_table_start();
345
php_info_print_table_row(2, "igbinary support", "enabled");
346
php_info_print_table_row(2, "igbinary version", PHP_IGBINARY_VERSION);
347
#if defined(HAVE_APCU_SUPPORT)
348
php_info_print_table_row(2, "igbinary APCU serializer ABI", APC_SERIALIZER_ABI);
349
#elif defined(HAVE_APC_SUPPORT)
350
php_info_print_table_row(2, "igbinary APC serializer ABI", APC_SERIALIZER_ABI);
352
php_info_print_table_row(2, "igbinary APC serializer ABI", "no");
355
php_info_print_table_row(2, "igbinary session support", "yes");
357
php_info_print_table_row(2, "igbinary session support", "no");
359
php_info_print_table_end();
361
DISPLAY_INI_ENTRIES();
364
/* {{{ Memory allocator wrappers */
365
static inline void *igbinary_mm_wrapper_malloc(size_t size, void *context)
367
return emalloc(size);
370
static inline void *igbinary_mm_wrapper_realloc(void *ptr, size_t size, void *context)
372
return erealloc(ptr, size);
375
static inline void igbinary_mm_wrapper_free(void *ptr, void *context)
380
/* {{{ int igbinary_serialize(uint8_t**, size_t*, zval*) */
381
IGBINARY_API int igbinary_serialize(uint8_t **ret, size_t *ret_len, zval *z TSRMLS_DC) {
382
return igbinary_serialize_ex(ret, ret_len, z, NULL TSRMLS_CC);
385
/* {{{ int igbinary_serialize_ex(uint8_t**, size_t*, zval*, igbinary_memory_manager*) */
386
IGBINARY_API int igbinary_serialize_ex(uint8_t **ret, size_t *ret_len, zval *z, struct igbinary_memory_manager *memory_manager TSRMLS_DC) {
387
struct igbinary_serialize_data igsd;
390
if (igbinary_serialize_data_init(&igsd, Z_TYPE_P(z) != IS_OBJECT && Z_TYPE_P(z) != IS_ARRAY, memory_manager TSRMLS_CC)) {
391
zend_error(E_WARNING, "igbinary_serialize: cannot init igsd");
395
if (igbinary_serialize_header(&igsd TSRMLS_CC) != 0) {
396
zend_error(E_WARNING, "igbinary_serialize: cannot write header");
397
igbinary_serialize_data_deinit(&igsd, 1 TSRMLS_CC);
401
if (igbinary_serialize_zval(&igsd, z TSRMLS_CC) != 0) {
402
igbinary_serialize_data_deinit(&igsd, 1 TSRMLS_CC);
406
/* Explicit nul termination */
407
if (igbinary_serialize8(&igsd, 0 TSRMLS_CC) != 0) {
408
igbinary_serialize_data_deinit(&igsd, 1 TSRMLS_CC);
412
/* shrink buffer to the real length, ignore errors */
413
tmpbuf = (uint8_t *) igsd.mm.realloc(igsd.buffer, igsd.buffer_size, igsd.mm.context);
414
if (tmpbuf != NULL) {
415
igsd.buffer = tmpbuf;
418
/* Set return values */
419
*ret_len = igsd.buffer_size - 1;
422
igbinary_serialize_data_deinit(&igsd, 0 TSRMLS_CC);
427
/* {{{ int igbinary_unserialize(const uint8_t *, size_t, zval **) */
428
IGBINARY_API int igbinary_unserialize(const uint8_t *buf, size_t buf_len, zval **z TSRMLS_DC) {
429
struct igbinary_unserialize_data igsd;
431
igbinary_unserialize_data_init(&igsd TSRMLS_CC);
433
igsd.buffer = (uint8_t *) buf;
434
igsd.buffer_size = buf_len;
436
if (igbinary_unserialize_header(&igsd TSRMLS_CC)) {
437
igbinary_unserialize_data_deinit(&igsd TSRMLS_CC);
441
if (igbinary_unserialize_zval(&igsd, z TSRMLS_CC)) {
442
igbinary_unserialize_data_deinit(&igsd TSRMLS_CC);
446
igbinary_unserialize_data_deinit(&igsd TSRMLS_CC);
451
/* {{{ proto string igbinary_unserialize(mixed value) */
452
PHP_FUNCTION(igbinary_unserialize) {
456
(void) return_value_ptr;
458
(void) return_value_used;
460
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &string_len) == FAILURE) {
464
if (string_len <= 0) {
468
if (igbinary_unserialize((uint8_t *) string, string_len, &return_value TSRMLS_CC) != 0) {
473
/* {{{ proto mixed igbinary_serialize(string value) */
474
PHP_FUNCTION(igbinary_serialize) {
479
(void) return_value_ptr;
481
(void) return_value_used;
484
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &z) == FAILURE) {
488
if (igbinary_serialize(&string, &string_len, z TSRMLS_CC) != 0) {
492
RETVAL_STRINGL((char *)string, string_len, 0);
495
#ifdef HAVE_PHP_SESSION
496
/* {{{ Serializer encode function */
497
PS_SERIALIZER_ENCODE_FUNC(igbinary)
499
struct igbinary_serialize_data igsd;
502
if (igbinary_serialize_data_init(&igsd, false, NULL TSRMLS_CC)) {
503
zend_error(E_WARNING, "igbinary_serialize: cannot init igsd");
507
if (igbinary_serialize_header(&igsd TSRMLS_CC) != 0) {
508
zend_error(E_WARNING, "igbinary_serialize: cannot write header");
509
igbinary_serialize_data_deinit(&igsd, 1 TSRMLS_CC);
513
if (igbinary_serialize_array(&igsd, PS(http_session_vars), false, false TSRMLS_CC) != 0) {
514
igbinary_serialize_data_deinit(&igsd, 1 TSRMLS_CC);
518
if (igbinary_serialize8(&igsd, 0 TSRMLS_CC) != 0) {
519
igbinary_serialize_data_deinit(&igsd, 1 TSRMLS_CC);
523
/* shrink buffer to the real length, ignore errors */
524
tmpbuf = (uint8_t *)igsd.mm.realloc(igsd.buffer, igsd.buffer_size, igsd.mm.context);
525
if (tmpbuf != NULL) {
526
igsd.buffer = tmpbuf;
529
*newstr = (char *)igsd.buffer;
531
*newlen = igsd.buffer_size - 1;
534
igbinary_serialize_data_deinit(&igsd, 0 TSRMLS_CC);
539
/* {{{ Serializer decode function */
540
PS_SERIALIZER_DECODE_FUNC(igbinary) {
541
HashPosition tmp_hash_pos;
550
struct igbinary_unserialize_data igsd;
552
if (!val || vallen==0)
555
if (igbinary_unserialize_data_init(&igsd TSRMLS_CC) != 0) {
559
igsd.buffer = (uint8_t *)val;
560
igsd.buffer_size = vallen;
562
if (igbinary_unserialize_header(&igsd TSRMLS_CC)) {
563
igbinary_unserialize_data_deinit(&igsd TSRMLS_CC);
568
if (igbinary_unserialize_zval(&igsd, &z TSRMLS_CC)) {
569
igbinary_unserialize_data_deinit(&igsd TSRMLS_CC);
575
igbinary_unserialize_data_deinit(&igsd TSRMLS_CC);
577
tmp_hash = HASH_OF(z);
579
zend_hash_internal_pointer_reset_ex(tmp_hash, &tmp_hash_pos);
580
while (zend_hash_get_current_data_ex(tmp_hash, (void *) &d, &tmp_hash_pos) == SUCCESS) {
581
tmp_int = zend_hash_get_current_key_ex(tmp_hash, &key_str, &key_len, &key_long, 0, &tmp_hash_pos);
584
case HASH_KEY_IS_LONG:
587
case HASH_KEY_IS_STRING:
588
php_set_session_var(key_str, key_len-1, *d, NULL TSRMLS_CC);
589
php_add_session_var(key_str, key_len-1 TSRMLS_CC);
592
zend_hash_move_forward_ex(tmp_hash, &tmp_hash_pos);
600
#endif /* HAVE_PHP_SESSION */
602
#if defined(HAVE_APC_SUPPORT) || defined(HAVE_APCU_SUPPORT)
603
/* {{{ apc_serialize function */
604
static int APC_SERIALIZER_NAME(igbinary) ( APC_SERIALIZER_ARGS ) {
607
if (igbinary_serialize(buf, buf_len, (zval *)value TSRMLS_CC) == 0) {
608
/* flipped semantics */
614
/* {{{ apc_unserialize function */
615
static int APC_UNSERIALIZER_NAME(igbinary) ( APC_UNSERIALIZER_ARGS ) {
618
if (igbinary_unserialize(buf, buf_len, value TSRMLS_CC) == 0) {
619
/* flipped semantics */
623
(*value)->type = IS_NULL;
629
/* {{{ igbinary_serialize_data_init */
630
/** Inits igbinary_serialize_data. */
631
inline static int igbinary_serialize_data_init(struct igbinary_serialize_data *igsd, bool scalar, struct igbinary_memory_manager *memory_manager TSRMLS_DC) {
634
if (memory_manager == NULL) {
635
igsd->mm.alloc = igbinary_mm_wrapper_malloc;
636
igsd->mm.realloc = igbinary_mm_wrapper_realloc;
637
igsd->mm.free = igbinary_mm_wrapper_free;
638
igsd->mm.context = NULL;
640
igsd->mm = *memory_manager;
644
igsd->buffer_size = 0;
645
igsd->buffer_capacity = 32;
646
igsd->string_count = 0;
649
igsd->buffer = (uint8_t *) igsd->mm.alloc(igsd->buffer_capacity, igsd->mm.context);
650
if (igsd->buffer == NULL) {
654
igsd->scalar = scalar;
656
hash_si_init(&igsd->strings, 16);
657
hash_si_init(&igsd->objects, 16);
660
igsd->compact_strings = (bool)IGBINARY_G(compact_strings);
665
/* {{{ igbinary_serialize_data_deinit */
666
/** Deinits igbinary_serialize_data. */
667
inline static void igbinary_serialize_data_deinit(struct igbinary_serialize_data *igsd, int free_buffer TSRMLS_DC) {
668
if (free_buffer && igsd->buffer) {
669
igsd->mm.free(igsd->buffer, igsd->mm.context);
673
hash_si_deinit(&igsd->strings);
674
hash_si_deinit(&igsd->objects);
678
/* {{{ igbinary_serialize_header */
679
/** Serializes header. */
680
inline static int igbinary_serialize_header(struct igbinary_serialize_data *igsd TSRMLS_DC) {
681
return igbinary_serialize32(igsd, IGBINARY_FORMAT_VERSION TSRMLS_CC); /* version */
684
/* {{{ igbinary_serialize_resize */
685
/** Expands igbinary_serialize_data. */
686
inline static int igbinary_serialize_resize(struct igbinary_serialize_data *igsd, size_t size TSRMLS_DC) {
687
if (igsd->buffer_size + size < igsd->buffer_capacity) {
691
while (igsd->buffer_size + size >= igsd->buffer_capacity) {
692
igsd->buffer_capacity *= 2;
695
igsd->buffer = (uint8_t *) igsd->mm.realloc(igsd->buffer, igsd->buffer_capacity, igsd->mm.context);
696
if (igsd->buffer == NULL)
702
/* {{{ igbinary_serialize8 */
703
/** Serialize 8bit value. */
704
inline static int igbinary_serialize8(struct igbinary_serialize_data *igsd, uint8_t i TSRMLS_DC) {
705
if (igbinary_serialize_resize(igsd, 1 TSRMLS_CC)) {
709
igsd->buffer[igsd->buffer_size++] = i;
713
/* {{{ igbinary_serialize16 */
714
/** Serialize 16bit value. */
715
inline static int igbinary_serialize16(struct igbinary_serialize_data *igsd, uint16_t i TSRMLS_DC) {
716
if (igbinary_serialize_resize(igsd, 2 TSRMLS_CC)) {
720
igsd->buffer[igsd->buffer_size++] = (uint8_t) (i >> 8 & 0xff);
721
igsd->buffer[igsd->buffer_size++] = (uint8_t) (i & 0xff);
726
/* {{{ igbinary_serialize32 */
727
/** Serialize 32bit value. */
728
inline static int igbinary_serialize32(struct igbinary_serialize_data *igsd, uint32_t i TSRMLS_DC) {
729
if (igbinary_serialize_resize(igsd, 4 TSRMLS_CC)) {
733
igsd->buffer[igsd->buffer_size++] = (uint8_t) (i >> 24 & 0xff);
734
igsd->buffer[igsd->buffer_size++] = (uint8_t) (i >> 16 & 0xff);
735
igsd->buffer[igsd->buffer_size++] = (uint8_t) (i >> 8 & 0xff);
736
igsd->buffer[igsd->buffer_size++] = (uint8_t) (i & 0xff);
741
/* {{{ igbinary_serialize64 */
742
/** Serialize 64bit value. */
743
inline static int igbinary_serialize64(struct igbinary_serialize_data *igsd, uint64_t i TSRMLS_DC) {
744
if (igbinary_serialize_resize(igsd, 8 TSRMLS_CC)) {
748
igsd->buffer[igsd->buffer_size++] = (uint8_t) (i >> 56 & 0xff);
749
igsd->buffer[igsd->buffer_size++] = (uint8_t) (i >> 48 & 0xff);
750
igsd->buffer[igsd->buffer_size++] = (uint8_t) (i >> 40 & 0xff);
751
igsd->buffer[igsd->buffer_size++] = (uint8_t) (i >> 32 & 0xff);
752
igsd->buffer[igsd->buffer_size++] = (uint8_t) (i >> 24 & 0xff);
753
igsd->buffer[igsd->buffer_size++] = (uint8_t) (i >> 16 & 0xff);
754
igsd->buffer[igsd->buffer_size++] = (uint8_t) (i >> 8 & 0xff);
755
igsd->buffer[igsd->buffer_size++] = (uint8_t) (i & 0xff);
760
/* {{{ igbinary_serialize_null */
761
/** Serializes null. */
762
inline static int igbinary_serialize_null(struct igbinary_serialize_data *igsd TSRMLS_DC) {
763
return igbinary_serialize8(igsd, igbinary_type_null TSRMLS_CC);
766
/* {{{ igbinary_serialize_bool */
767
/** Serializes bool. */
768
inline static int igbinary_serialize_bool(struct igbinary_serialize_data *igsd, int b TSRMLS_DC) {
769
return igbinary_serialize8(igsd, (uint8_t) (b ? igbinary_type_bool_true : igbinary_type_bool_false) TSRMLS_CC);
772
/* {{{ igbinary_serialize_long */
773
/** Serializes long. */
774
inline static int igbinary_serialize_long(struct igbinary_serialize_data *igsd, long l TSRMLS_DC) {
775
long k = l >= 0 ? l : -l;
776
bool p = l >= 0 ? true : false;
778
/* -LONG_MIN is 0 otherwise. */
781
if (igbinary_serialize8(igsd, (uint8_t) igbinary_type_long64n TSRMLS_CC) != 0) {
785
if (igbinary_serialize64(igsd, (uint64_t) 0x8000000000000000 TSRMLS_CC) != 0) {
788
#elif SIZEOF_LONG == 4
789
if (igbinary_serialize8(igsd, (uint8_t) igbinary_type_long32n TSRMLS_CC) != 0) {
792
if (igbinary_serialize32(igsd, (uint32_t) 0x80000000 TSRMLS_CC) != 0) {
796
#error "Strange sizeof(long)."
802
if (igbinary_serialize8(igsd, (uint8_t) (p ? igbinary_type_long8p : igbinary_type_long8n) TSRMLS_CC) != 0) {
806
if (igbinary_serialize8(igsd, (uint8_t) k TSRMLS_CC) != 0) {
809
} else if (k <= 0xffff) {
810
if (igbinary_serialize8(igsd, (uint8_t) (p ? igbinary_type_long16p : igbinary_type_long16n) TSRMLS_CC) != 0) {
814
if (igbinary_serialize16(igsd, (uint16_t) k TSRMLS_CC) != 0) {
818
} else if (k <= 0xffffffff) {
819
if (igbinary_serialize8(igsd, (uint8_t) (p ? igbinary_type_long32p : igbinary_type_long32n) TSRMLS_CC) != 0) {
823
if (igbinary_serialize32(igsd, (uint32_t) k TSRMLS_CC) != 0) {
827
if (igbinary_serialize8(igsd, (uint8_t) (p ? igbinary_type_long64p : igbinary_type_long64n) TSRMLS_CC) != 0) {
830
if (igbinary_serialize64(igsd, (uint64_t) k TSRMLS_CC) != 0) {
834
#elif SIZEOF_LONG == 4
836
if (igbinary_serialize8(igsd, (uint8_t) (p ? igbinary_type_long32p : igbinary_type_long32n) TSRMLS_CC) != 0) {
839
if (igbinary_serialize32(igsd, (uint32_t) k TSRMLS_CC) != 0) {
844
#error "Strange sizeof(long)."
850
/* {{{ igbinary_serialize_double */
851
/** Serializes double. */
852
inline static int igbinary_serialize_double(struct igbinary_serialize_data *igsd, double d TSRMLS_DC) {
858
if (igbinary_serialize8(igsd, igbinary_type_double TSRMLS_CC) != 0) {
864
return igbinary_serialize64(igsd, u.u TSRMLS_CC);
867
/* {{{ igbinary_serialize_string */
868
/** Serializes string.
869
* Serializes each string once, after first time uses pointers.
871
inline static int igbinary_serialize_string(struct igbinary_serialize_data *igsd, char *s, size_t len TSRMLS_DC) {
876
if (igbinary_serialize8(igsd, igbinary_type_string_empty TSRMLS_CC) != 0) {
883
if (igsd->scalar || !igsd->compact_strings || hash_si_find(&igsd->strings, s, len, i) == 1) {
884
if (!igsd->scalar && igsd->compact_strings) {
885
hash_si_insert(&igsd->strings, s, len, igsd->string_count);
888
igsd->string_count += 1;
890
if (igbinary_serialize_chararray(igsd, s, len TSRMLS_CC) != 0) {
895
if (igbinary_serialize8(igsd, (uint8_t) igbinary_type_string_id8 TSRMLS_CC) != 0) {
899
if (igbinary_serialize8(igsd, (uint8_t) *i TSRMLS_CC) != 0) {
902
} else if (*i <= 0xffff) {
903
if (igbinary_serialize8(igsd, (uint8_t) igbinary_type_string_id16 TSRMLS_CC) != 0) {
907
if (igbinary_serialize16(igsd, (uint16_t) *i TSRMLS_CC) != 0) {
911
if (igbinary_serialize8(igsd, (uint8_t) igbinary_type_string_id32 TSRMLS_CC) != 0) {
915
if (igbinary_serialize32(igsd, (uint32_t) *i TSRMLS_CC) != 0) {
924
/* {{{ igbinary_serialize_chararray */
925
/** Serializes string data. */
926
inline static int igbinary_serialize_chararray(struct igbinary_serialize_data *igsd, const char *s, size_t len TSRMLS_DC) {
928
if (igbinary_serialize8(igsd, igbinary_type_string8 TSRMLS_CC) != 0) {
932
if (igbinary_serialize8(igsd, len TSRMLS_CC) != 0) {
935
} else if (len <= 0xffff) {
936
if (igbinary_serialize8(igsd, igbinary_type_string16 TSRMLS_CC) != 0) {
940
if (igbinary_serialize16(igsd, len TSRMLS_CC) != 0) {
944
if (igbinary_serialize8(igsd, igbinary_type_string32 TSRMLS_CC) != 0) {
948
if (igbinary_serialize32(igsd, len TSRMLS_CC) != 0) {
953
if (igbinary_serialize_resize(igsd, len TSRMLS_CC)) {
957
memcpy(igsd->buffer+igsd->buffer_size, s, len);
958
igsd->buffer_size += len;
963
/* {{{ igbinay_serialize_array */
964
/** Serializes array or objects inner properties. */
965
inline static int igbinary_serialize_array(struct igbinary_serialize_data *igsd, zval *z, bool object, bool incomplete_class TSRMLS_DC) {
977
h = object ? Z_OBJPROP_P(z) : HASH_OF(z);
980
n = h ? zend_hash_num_elements(h) : 0;
982
/* incomplete class magic member */
983
if (n > 0 && incomplete_class) {
987
if (!object && igbinary_serialize_array_ref(igsd, z, object TSRMLS_CC) == 0) {
992
if (igbinary_serialize8(igsd, igbinary_type_array8 TSRMLS_CC) != 0) {
996
if (igbinary_serialize8(igsd, n TSRMLS_CC) != 0) {
999
} else if (n <= 0xffff) {
1000
if (igbinary_serialize8(igsd, igbinary_type_array16 TSRMLS_CC) != 0) {
1004
if (igbinary_serialize16(igsd, n TSRMLS_CC) != 0) {
1008
if (igbinary_serialize8(igsd, igbinary_type_array32 TSRMLS_CC) != 0) {
1012
if (igbinary_serialize32(igsd, n TSRMLS_CC) != 0) {
1021
/* serialize properties. */
1022
zend_hash_internal_pointer_reset_ex(h, &pos);
1023
for (;; zend_hash_move_forward_ex(h, &pos)) {
1024
key_type = zend_hash_get_current_key_ex(h, &key, &key_len, &key_index, 0, &pos);
1027
if (key_type == HASH_KEY_NON_EXISTANT) {
1031
/* skip magic member in incomplete classes */
1032
if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) {
1037
case HASH_KEY_IS_LONG:
1038
if (igbinary_serialize_long(igsd, key_index TSRMLS_CC) != 0) {
1043
case HASH_KEY_IS_STRING:
1044
if (igbinary_serialize_string(igsd, key, key_len-1 TSRMLS_CC) != 0) {
1050
zend_error(E_ERROR, "igbinary_serialize_array: key is not string nor array");
1055
/* we should still add element even if it's not OK,
1056
* since we already wrote the length of the array before */
1057
if (zend_hash_get_current_data_ex(h, (void *) &d, &pos) != SUCCESS || d == NULL) {
1058
if (igbinary_serialize_null(igsd TSRMLS_CC)) {
1062
if (igbinary_serialize_zval(igsd, *d TSRMLS_CC)) {
1071
/* {{{ igbinary_serialize_array_ref */
1072
/** Serializes array reference. */
1073
inline static int igbinary_serialize_array_ref(struct igbinary_serialize_data *igsd, zval *z, bool object TSRMLS_DC) {
1079
zend_class_entry *ce;
1080
zend_object_handle handle;
1084
if (object && Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_class_entry) {
1085
key.obj.ce = Z_OBJCE_P(z);
1086
key.obj.handle = Z_OBJ_HANDLE_P(z);
1091
if (hash_si_find(&igsd->objects, (char *)&key, sizeof(key), i) == 1) {
1092
t = hash_si_size(&igsd->objects);
1093
hash_si_insert(&igsd->objects, (char *)&key, sizeof(key), t);
1096
enum igbinary_type type;
1098
type = object ? igbinary_type_objref8 : igbinary_type_ref8;
1099
if (igbinary_serialize8(igsd, (uint8_t) type TSRMLS_CC) != 0) {
1103
if (igbinary_serialize8(igsd, (uint8_t) *i TSRMLS_CC) != 0) {
1106
} else if (*i <= 0xffff) {
1107
type = object ? igbinary_type_objref16 : igbinary_type_ref16;
1108
if (igbinary_serialize8(igsd, (uint8_t) type TSRMLS_CC) != 0) {
1112
if (igbinary_serialize16(igsd, (uint16_t) *i TSRMLS_CC) != 0) {
1116
type = object ? igbinary_type_objref32 : igbinary_type_ref32;
1117
if (igbinary_serialize8(igsd, (uint8_t) type TSRMLS_CC) != 0) {
1121
if (igbinary_serialize32(igsd, (uint32_t) *i TSRMLS_CC) != 0) {
1132
/* {{{ igbinary_serialize_array_sleep */
1133
/** Serializes object's properties array with __sleep -function. */
1134
inline static int igbinary_serialize_array_sleep(struct igbinary_serialize_data *igsd, zval *z, HashTable *h, zend_class_entry *ce, bool incomplete_class TSRMLS_DC) {
1136
size_t n = zend_hash_num_elements(h);
1145
/* Decrease array size by one, because of magic member (with class name) */
1146
if (n > 0 && incomplete_class) {
1150
/* Serialize array id. */
1152
if (igbinary_serialize8(igsd, igbinary_type_array8 TSRMLS_CC) != 0) {
1156
if (igbinary_serialize8(igsd, n TSRMLS_CC) != 0) {
1159
} else if (n <= 0xffff) {
1160
if (igbinary_serialize8(igsd, igbinary_type_array16 TSRMLS_CC) != 0) {
1164
if (igbinary_serialize16(igsd, n TSRMLS_CC) != 0) {
1168
if (igbinary_serialize8(igsd, igbinary_type_array32 TSRMLS_CC) != 0) {
1172
if (igbinary_serialize32(igsd, n TSRMLS_CC) != 0) {
1181
zend_hash_internal_pointer_reset_ex(h, &pos);
1183
for (;; zend_hash_move_forward_ex(h, &pos)) {
1184
key_type = zend_hash_get_current_key_ex(h, &key, &key_len, &key_index, 0, &pos);
1187
if (key_type == HASH_KEY_NON_EXISTANT) {
1191
/* skip magic member in incomplete classes */
1192
if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) {
1196
if (zend_hash_get_current_data_ex(h, (void *) &d, &pos) != SUCCESS || d == NULL || Z_TYPE_PP(d) != IS_STRING) {
1197
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "__sleep should return an array only "
1198
"containing the names of instance-variables to "
1201
/* we should still add element even if it's not OK,
1202
* since we already wrote the length of the array before
1203
* serialize null as key-value pair */
1204
if (igbinary_serialize_null(igsd TSRMLS_CC) != 0) {
1209
if (zend_hash_find(Z_OBJPROP_P(z), Z_STRVAL_PP(d), Z_STRLEN_PP(d) + 1, (void *) &v) == SUCCESS) {
1210
if (igbinary_serialize_string(igsd, Z_STRVAL_PP(d), Z_STRLEN_PP(d) TSRMLS_CC) != 0) {
1214
if (igbinary_serialize_zval(igsd, *v TSRMLS_CC) != 0) {
1218
char *prot_name = NULL;
1219
char *priv_name = NULL;
1220
int prop_name_length;
1224
zend_mangle_property_name(&priv_name, &prop_name_length, ce->name, ce->name_length,
1225
Z_STRVAL_PP(d), Z_STRLEN_PP(d), ce->type & ZEND_INTERNAL_CLASS);
1226
if (zend_hash_find(Z_OBJPROP_P(z), priv_name, prop_name_length+1, (void *) &v) == SUCCESS) {
1227
if (igbinary_serialize_string(igsd, priv_name, prop_name_length TSRMLS_CC) != 0) {
1233
if (igbinary_serialize_zval(igsd, *v TSRMLS_CC) != 0) {
1241
zend_mangle_property_name(&prot_name, &prop_name_length, "*", 1,
1242
Z_STRVAL_PP(d), Z_STRLEN_PP(d), ce->type & ZEND_INTERNAL_CLASS);
1243
if (zend_hash_find(Z_OBJPROP_P(z), prot_name, prop_name_length+1, (void *) &v) == SUCCESS) {
1244
if (igbinary_serialize_string(igsd, prot_name, prop_name_length TSRMLS_CC) != 0) {
1250
if (igbinary_serialize_zval(igsd, *v TSRMLS_CC) != 0) {
1258
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "\"%s\" returned as member variable from __sleep() but does not exist", Z_STRVAL_PP(d));
1259
if (igbinary_serialize_string(igsd, Z_STRVAL_PP(d), Z_STRLEN_PP(d) TSRMLS_CC) != 0) {
1263
if (igbinary_serialize_null(igsd TSRMLS_CC) != 0) {
1269
// if all else fails, just serialize the value in anyway.
1270
if (igbinary_serialize_string(igsd, Z_STRVAL_PP(d), Z_STRLEN_PP(d) TSRMLS_CC) != 0) {
1274
if (igbinary_serialize_zval(igsd, *v TSRMLS_CC) != 0) {
1284
/* {{{ igbinary_serialize_object_name */
1285
/** Serialize object name. */
1286
inline static int igbinary_serialize_object_name(struct igbinary_serialize_data *igsd, const char *class_name, size_t name_len TSRMLS_DC) {
1290
if (hash_si_find(&igsd->strings, class_name, name_len, i) == 1) {
1291
hash_si_insert(&igsd->strings, class_name, name_len, igsd->string_count);
1292
igsd->string_count += 1;
1294
if (name_len <= 0xff) {
1295
if (igbinary_serialize8(igsd, (uint8_t) igbinary_type_object8 TSRMLS_CC) != 0) {
1299
if (igbinary_serialize8(igsd, (uint8_t) name_len TSRMLS_CC) != 0) {
1302
} else if (name_len <= 0xffff) {
1303
if (igbinary_serialize8(igsd, (uint8_t) igbinary_type_object16 TSRMLS_CC) != 0) {
1307
if (igbinary_serialize16(igsd, (uint16_t) name_len TSRMLS_CC) != 0) {
1311
if (igbinary_serialize8(igsd, (uint8_t) igbinary_type_object32 TSRMLS_CC) != 0) {
1315
if (igbinary_serialize32(igsd, (uint32_t) name_len TSRMLS_CC) != 0) {
1320
if (igbinary_serialize_resize(igsd, name_len TSRMLS_CC)) {
1324
memcpy(igsd->buffer+igsd->buffer_size, class_name, name_len);
1325
igsd->buffer_size += name_len;
1327
/* already serialized string */
1329
if (igbinary_serialize8(igsd, (uint8_t) igbinary_type_object_id8 TSRMLS_CC) != 0) {
1333
if (igbinary_serialize8(igsd, (uint8_t) *i TSRMLS_CC) != 0) {
1336
} else if (*i <= 0xffff) {
1337
if (igbinary_serialize8(igsd, (uint8_t) igbinary_type_object_id16 TSRMLS_CC) != 0) {
1341
if (igbinary_serialize16(igsd, (uint16_t) *i TSRMLS_CC) != 0) {
1345
if (igbinary_serialize8(igsd, (uint8_t) igbinary_type_object_id32 TSRMLS_CC) != 0) {
1349
if (igbinary_serialize32(igsd, (uint32_t) *i TSRMLS_CC) != 0) {
1358
/* {{{ igbinary_serialize_object */
1359
/** Serialize object.
1360
* @see ext/standard/var.c
1362
inline static int igbinary_serialize_object(struct igbinary_serialize_data *igsd, zval *z TSRMLS_DC) {
1363
zend_class_entry *ce;
1370
unsigned char *serialized_data = NULL;
1371
zend_uint serialized_len;
1373
PHP_CLASS_ATTRIBUTES;
1375
if (igbinary_serialize_array_ref(igsd, z, true TSRMLS_CC) == 0) {
1381
/* custom serializer */
1382
if (ce && ce->serialize != NULL) {
1383
if (ce->serialize(z, &serialized_data, &serialized_len, (zend_serialize_data *)NULL TSRMLS_CC) == SUCCESS && !EG(exception)) {
1384
if (igbinary_serialize_object_name(igsd, ce->name, ce->name_length TSRMLS_CC) != 0) {
1385
if (serialized_data) {
1386
efree(serialized_data);
1392
if (serialized_len <= 0xff) {
1393
if (igbinary_serialize8(igsd, (uint8_t) igbinary_type_object_ser8 TSRMLS_CC) != 0) {
1394
if (serialized_data) {
1395
efree(serialized_data);
1400
if (igbinary_serialize8(igsd, (uint8_t) serialized_len TSRMLS_CC) != 0) {
1401
if (serialized_data) {
1402
efree(serialized_data);
1406
} else if (serialized_len <= 0xffff) {
1407
if (igbinary_serialize8(igsd, (uint8_t) igbinary_type_object_ser16 TSRMLS_CC) != 0) {
1408
if (serialized_data) {
1409
efree(serialized_data);
1414
if (igbinary_serialize16(igsd, (uint16_t) serialized_len TSRMLS_CC) != 0) {
1415
if (serialized_data) {
1416
efree(serialized_data);
1421
if (igbinary_serialize8(igsd, (uint8_t) igbinary_type_object_ser32 TSRMLS_CC) != 0) {
1422
if (serialized_data) {
1423
efree(serialized_data);
1428
if (igbinary_serialize32(igsd, (uint32_t) serialized_len TSRMLS_CC) != 0) {
1429
if (serialized_data) {
1430
efree(serialized_data);
1436
if (igbinary_serialize_resize(igsd, serialized_len TSRMLS_CC)) {
1437
if (serialized_data) {
1438
efree(serialized_data);
1444
memcpy(igsd->buffer+igsd->buffer_size, serialized_data, serialized_len);
1445
igsd->buffer_size += serialized_len;
1446
} else if (EG(exception)) {
1447
/* exception, return failure */
1450
/* Serialization callback failed, assume null output */
1451
r = igbinary_serialize_null(igsd TSRMLS_CC);
1454
if (serialized_data) {
1455
efree(serialized_data);
1461
/* serialize class name */
1462
PHP_SET_CLASS_ATTRIBUTES(z);
1463
if (igbinary_serialize_object_name(igsd, class_name, name_len TSRMLS_CC) != 0) {
1464
PHP_CLEANUP_CLASS_ATTRIBUTES();
1467
PHP_CLEANUP_CLASS_ATTRIBUTES();
1469
if (ce && ce != PHP_IC_ENTRY && zend_hash_exists(&ce->function_table, "__sleep", sizeof("__sleep"))) {
1470
/* function name string */
1472
ZVAL_STRINGL(&f, "__sleep", sizeof("__sleep") - 1, 0);
1474
/* calling z->__sleep */
1475
r = call_user_function_ex(CG(function_table), &z, &f, &h, 0, 0, 1, NULL TSRMLS_CC);
1477
if (r == SUCCESS && !EG(exception)) {
1481
if (Z_TYPE_P(h) == IS_ARRAY) {
1482
r = igbinary_serialize_array_sleep(igsd, z, HASH_OF(h), ce, incomplete_class TSRMLS_CC);
1484
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "__sleep should return an array only "
1485
"containing the names of instance-variables to "
1489
r = igbinary_serialize8(igsd, igbinary_type_array8 TSRMLS_CC);
1491
r = igbinary_serialize8(igsd, 0 TSRMLS_CC);
1506
return igbinary_serialize_array(igsd, z, true, incomplete_class TSRMLS_CC);
1510
/* {{{ igbinary_serialize_zval */
1511
/** Serialize zval. */
1512
static int igbinary_serialize_zval(struct igbinary_serialize_data *igsd, zval *z TSRMLS_DC) {
1514
if (igbinary_serialize8(igsd, (uint8_t) igbinary_type_ref TSRMLS_CC) != 0) {
1518
/* Complex types serialize a reference, scalars do not... */
1519
/* FIXME: Absolutely wrong level to check this. */
1520
switch (Z_TYPE_P(z)) {
1527
/* Serialize a reference if zval already added */
1528
if (igbinary_serialize_array_ref(igsd, z, false TSRMLS_CC) == 0) {
1531
/* otherwise fall through */
1534
switch (Z_TYPE_P(z)) {
1536
return igbinary_serialize_null(igsd TSRMLS_CC);
1538
return igbinary_serialize_object(igsd, z TSRMLS_CC);
1540
return igbinary_serialize_array(igsd, z, false, false TSRMLS_CC);
1542
return igbinary_serialize_string(igsd, Z_STRVAL_P(z), Z_STRLEN_P(z) TSRMLS_CC);
1544
return igbinary_serialize_long(igsd, Z_LVAL_P(z) TSRMLS_CC);
1546
return igbinary_serialize_null(igsd TSRMLS_CC);
1548
return igbinary_serialize_bool(igsd, Z_LVAL_P(z) ? 1 : 0 TSRMLS_CC);
1550
return igbinary_serialize_double(igsd, Z_DVAL_P(z) TSRMLS_CC);
1552
zend_error(E_ERROR, "igbinary_serialize_zval: zval has unknown type %d", (int)Z_TYPE_P(z));
1560
/* {{{ igbinary_unserialize_data_init */
1561
/** Inits igbinary_unserialize_data_init. */
1562
inline static int igbinary_unserialize_data_init(struct igbinary_unserialize_data *igsd TSRMLS_DC) {
1563
smart_str empty_str = { 0 };
1565
igsd->buffer = NULL;
1566
igsd->buffer_size = 0;
1567
igsd->buffer_offset = 0;
1569
igsd->strings = NULL;
1570
igsd->strings_count = 0;
1571
igsd->strings_capacity = 4;
1572
igsd->string0_buf = empty_str;
1575
igsd->references = NULL;
1576
igsd->references_count = 0;
1577
igsd->references_capacity = 4;
1579
igsd->references = (void **) emalloc(sizeof(void *) * igsd->references_capacity);
1580
if (igsd->references == NULL) {
1584
igsd->strings = (struct igbinary_unserialize_string_pair *) emalloc(sizeof(struct igbinary_unserialize_string_pair) * igsd->strings_capacity);
1585
if (igsd->strings == NULL) {
1586
efree(igsd->references);
1593
/* {{{ igbinary_unserialize_data_deinit */
1594
/** Deinits igbinary_unserialize_data_init. */
1595
inline static void igbinary_unserialize_data_deinit(struct igbinary_unserialize_data *igsd TSRMLS_DC) {
1596
if (igsd->strings) {
1597
efree(igsd->strings);
1600
if (igsd->references) {
1601
efree(igsd->references);
1604
smart_str_free(&igsd->string0_buf);
1609
/* {{{ igbinary_unserialize_header */
1610
/** Unserialize header. Check for version. */
1611
inline static int igbinary_unserialize_header(struct igbinary_unserialize_data *igsd TSRMLS_DC) {
1614
if (igsd->buffer_offset + 4 >= igsd->buffer_size) {
1618
version = igbinary_unserialize32(igsd TSRMLS_CC);
1620
/* Support older version 1 and the current format 2 */
1621
if (version == IGBINARY_FORMAT_VERSION || version == 0x00000001) {
1624
zend_error(E_WARNING, "igbinary_unserialize_header: unsupported version: %u, should be %u or %u", (unsigned int) version, 0x00000001, (unsigned int) IGBINARY_FORMAT_VERSION);
1629
/* {{{ igbinary_unserialize8 */
1630
/** Unserialize 8bit value. */
1631
inline static uint8_t igbinary_unserialize8(struct igbinary_unserialize_data *igsd TSRMLS_DC) {
1633
ret = igsd->buffer[igsd->buffer_offset++];
1637
/* {{{ igbinary_unserialize16 */
1638
/** Unserialize 16bit value. */
1639
inline static uint16_t igbinary_unserialize16(struct igbinary_unserialize_data *igsd TSRMLS_DC) {
1641
ret |= ((uint16_t) igsd->buffer[igsd->buffer_offset++] << 8);
1642
ret |= ((uint16_t) igsd->buffer[igsd->buffer_offset++] << 0);
1646
/* {{{ igbinary_unserialize32 */
1647
/** Unserialize 32bit value. */
1648
inline static uint32_t igbinary_unserialize32(struct igbinary_unserialize_data *igsd TSRMLS_DC) {
1650
ret |= ((uint32_t) igsd->buffer[igsd->buffer_offset++] << 24);
1651
ret |= ((uint32_t) igsd->buffer[igsd->buffer_offset++] << 16);
1652
ret |= ((uint32_t) igsd->buffer[igsd->buffer_offset++] << 8);
1653
ret |= ((uint32_t) igsd->buffer[igsd->buffer_offset++] << 0);
1657
/* {{{ igbinary_unserialize64 */
1658
/** Unserialize 64bit value. */
1659
inline static uint64_t igbinary_unserialize64(struct igbinary_unserialize_data *igsd TSRMLS_DC) {
1661
ret |= ((uint64_t) igsd->buffer[igsd->buffer_offset++] << 56);
1662
ret |= ((uint64_t) igsd->buffer[igsd->buffer_offset++] << 48);
1663
ret |= ((uint64_t) igsd->buffer[igsd->buffer_offset++] << 40);
1664
ret |= ((uint64_t) igsd->buffer[igsd->buffer_offset++] << 32);
1665
ret |= ((uint64_t) igsd->buffer[igsd->buffer_offset++] << 24);
1666
ret |= ((uint64_t) igsd->buffer[igsd->buffer_offset++] << 16);
1667
ret |= ((uint64_t) igsd->buffer[igsd->buffer_offset++] << 8);
1668
ret |= ((uint64_t) igsd->buffer[igsd->buffer_offset++] << 0);
1672
/* {{{ igbinary_unserialize_long */
1673
/** Unserializes long */
1674
inline static int igbinary_unserialize_long(struct igbinary_unserialize_data *igsd, enum igbinary_type t, long *ret TSRMLS_DC) {
1676
#if SIZEOF_LONG == 8
1680
if (t == igbinary_type_long8p || t == igbinary_type_long8n) {
1681
if (igsd->buffer_offset + 1 > igsd->buffer_size) {
1682
zend_error(E_WARNING, "igbinary_unserialize_long: end-of-data");
1686
*ret = (long) (t == igbinary_type_long8n ? -1 : 1) * igbinary_unserialize8(igsd TSRMLS_CC);
1687
} else if (t == igbinary_type_long16p || t == igbinary_type_long16n) {
1688
if (igsd->buffer_offset + 2 > igsd->buffer_size) {
1689
zend_error(E_WARNING, "igbinary_unserialize_long: end-of-data");
1693
*ret = (long) (t == igbinary_type_long16n ? -1 : 1) * igbinary_unserialize16(igsd TSRMLS_CC);
1694
} else if (t == igbinary_type_long32p || t == igbinary_type_long32n) {
1695
if (igsd->buffer_offset + 4 > igsd->buffer_size) {
1696
zend_error(E_WARNING, "igbinary_unserialize_long: end-of-data");
1700
/* check for boundaries */
1701
tmp32 = igbinary_unserialize32(igsd TSRMLS_CC);
1702
#if SIZEOF_LONG == 4
1703
if (tmp32 > 0x80000000 || (tmp32 == 0x80000000 && t == igbinary_type_long32p)) {
1704
zend_error(E_WARNING, "igbinary_unserialize_long: 64bit long on 32bit platform?");
1705
tmp32 = 0; /* t == igbinary_type_long32p ? LONG_MAX : LONG_MIN; */
1708
*ret = (long) (t == igbinary_type_long32n ? -1 : 1) * tmp32;
1709
} else if (t == igbinary_type_long64p || t == igbinary_type_long64n) {
1710
#if SIZEOF_LONG == 8
1711
if (igsd->buffer_offset + 8 > igsd->buffer_size) {
1712
zend_error(E_WARNING, "igbinary_unserialize_long: end-of-data");
1716
/* check for boundaries */
1717
tmp64 = igbinary_unserialize64(igsd TSRMLS_CC);
1718
if (tmp64 > 0x8000000000000000 || (tmp64 == 0x8000000000000000 && t == igbinary_type_long64p)) {
1719
zend_error(E_WARNING, "igbinary_unserialize_long: too big 64bit long.");
1720
tmp64 = 0; /* t == igbinary_type_long64p ? LONG_MAX : LONG_MIN */;
1723
*ret = (long) (t == igbinary_type_long64n ? -1 : 1) * tmp64;
1724
#elif SIZEOF_LONG == 4
1725
/* can't put 64bit long into 32bit one, placeholder zero */
1727
igbinary_unserialize64(igsd TSRMLS_CC);
1728
zend_error(E_WARNING, "igbinary_unserialize_long: 64bit long on 32bit platform");
1730
#error "Strange sizeof(long)."
1734
zend_error(E_WARNING, "igbinary_unserialize_long: unknown type '%02x', position %zu", t, igsd->buffer_offset);
1741
/* {{{ igbinary_unserialize_double */
1742
/** Unserializes double. */
1743
inline static int igbinary_unserialize_double(struct igbinary_unserialize_data *igsd, enum igbinary_type t, double *ret TSRMLS_DC) {
1751
if (igsd->buffer_offset + 8 > igsd->buffer_size) {
1752
zend_error(E_WARNING, "igbinary_unserialize_double: end-of-data");
1757
u.u = igbinary_unserialize64(igsd TSRMLS_CC);
1764
/* {{{ igbinary_unserialize_string */
1765
/** Unserializes string. Unserializes both actual string or by string id. */
1766
inline static int igbinary_unserialize_string(struct igbinary_unserialize_data *igsd, enum igbinary_type t, char **s, size_t *len TSRMLS_DC) {
1768
if (t == igbinary_type_string_id8 || t == igbinary_type_object_id8) {
1769
if (igsd->buffer_offset + 1 > igsd->buffer_size) {
1770
zend_error(E_WARNING, "igbinary_unserialize_string: end-of-data");
1773
i = igbinary_unserialize8(igsd TSRMLS_CC);
1774
} else if (t == igbinary_type_string_id16 || t == igbinary_type_object_id16) {
1775
if (igsd->buffer_offset + 2 > igsd->buffer_size) {
1776
zend_error(E_WARNING, "igbinary_unserialize_string: end-of-data");
1779
i = igbinary_unserialize16(igsd TSRMLS_CC);
1780
} else if (t == igbinary_type_string_id32 || t == igbinary_type_object_id32) {
1781
if (igsd->buffer_offset + 4 > igsd->buffer_size) {
1782
zend_error(E_WARNING, "igbinary_unserialize_string: end-of-data");
1785
i = igbinary_unserialize32(igsd TSRMLS_CC);
1787
zend_error(E_WARNING, "igbinary_unserialize_string: unknown type '%02x', position %zu", t, igsd->buffer_offset);
1791
if (i >= igsd->strings_count) {
1792
zend_error(E_WARNING, "igbinary_unserialize_string: string index is out-of-bounds");
1796
*s = igsd->strings[i].data;
1797
*len = igsd->strings[i].len;
1802
/* {{{ igbinary_unserialize_chararray */
1803
/** Unserializes chararray of string. */
1804
inline static int igbinary_unserialize_chararray(struct igbinary_unserialize_data *igsd, enum igbinary_type t, char **s, size_t *len TSRMLS_DC) {
1807
if (t == igbinary_type_string8 || t == igbinary_type_object8) {
1808
if (igsd->buffer_offset + 1 > igsd->buffer_size) {
1809
zend_error(E_WARNING, "igbinary_unserialize_chararray: end-of-data");
1812
l = igbinary_unserialize8(igsd TSRMLS_CC);
1813
if (igsd->buffer_offset + l > igsd->buffer_size) {
1814
zend_error(E_WARNING, "igbinary_unserialize_chararray: end-of-data");
1817
} else if (t == igbinary_type_string16 || t == igbinary_type_object16) {
1818
if (igsd->buffer_offset + 2 > igsd->buffer_size) {
1819
zend_error(E_WARNING, "igbinary_unserialize_chararray: end-of-data");
1822
l = igbinary_unserialize16(igsd TSRMLS_CC);
1823
if (igsd->buffer_offset + l > igsd->buffer_size) {
1824
zend_error(E_WARNING, "igbinary_unserialize_chararray: end-of-data");
1827
} else if (t == igbinary_type_string32 || t == igbinary_type_object32) {
1828
if (igsd->buffer_offset + 4 > igsd->buffer_size) {
1829
zend_error(E_WARNING, "igbinary_unserialize_chararray: end-of-data");
1832
l = igbinary_unserialize32(igsd TSRMLS_CC);
1833
if (igsd->buffer_offset + l > igsd->buffer_size) {
1834
zend_error(E_WARNING, "igbinary_unserialize_chararray: end-of-data");
1838
zend_error(E_WARNING, "igbinary_unserialize_chararray: unknown type '%02x', position %zu", t, igsd->buffer_offset);
1842
if (igsd->strings_count + 1 > igsd->strings_capacity) {
1843
while (igsd->strings_count + 1 > igsd->strings_capacity) {
1844
igsd->strings_capacity *= 2;
1847
igsd->strings = (struct igbinary_unserialize_string_pair *) erealloc(igsd->strings, sizeof(struct igbinary_unserialize_string_pair) * igsd->strings_capacity);
1848
if (igsd->strings == NULL) {
1853
igsd->strings[igsd->strings_count].data = (char *) (igsd->buffer + igsd->buffer_offset);
1854
igsd->strings[igsd->strings_count].len = l;
1856
igsd->buffer_offset += l;
1858
if (igsd->strings[igsd->strings_count].data == NULL) {
1862
*len = igsd->strings[igsd->strings_count].len;
1863
*s = igsd->strings[igsd->strings_count].data;
1865
igsd->strings_count += 1;
1870
/* {{{ igbinary_unserialize_array */
1871
/** Unserializes array. */
1872
inline static int igbinary_unserialize_array(struct igbinary_unserialize_data *igsd, enum igbinary_type t, zval **z, int object TSRMLS_DC) {
1883
enum igbinary_type key_type;
1887
if (t == igbinary_type_array8) {
1888
if (igsd->buffer_offset + 1 > igsd->buffer_size) {
1889
zend_error(E_WARNING, "igbinary_unserialize_array: end-of-data");
1892
n = igbinary_unserialize8(igsd TSRMLS_CC);
1893
} else if (t == igbinary_type_array16) {
1894
if (igsd->buffer_offset + 2 > igsd->buffer_size) {
1895
zend_error(E_WARNING, "igbinary_unserialize_array: end-of-data");
1898
n = igbinary_unserialize16(igsd TSRMLS_CC);
1899
} else if (t == igbinary_type_array32) {
1900
if (igsd->buffer_offset + 4 > igsd->buffer_size) {
1901
zend_error(E_WARNING, "igbinary_unserialize_array: end-of-data");
1904
n = igbinary_unserialize32(igsd TSRMLS_CC);
1906
zend_error(E_WARNING, "igbinary_unserialize_array: unknown type '%02x', position %zu", t, igsd->buffer_offset);
1910
// n cannot be larger than the number of minimum "objects" in the array
1911
if (n > igsd->buffer_size - igsd->buffer_offset) {
1912
zend_error(E_WARNING, "%s: data size %zu smaller that requested array length %zu.", "igbinary_unserialize_array", igsd->buffer_size - igsd->buffer_offset, n);
1917
Z_TYPE_PP(z) = IS_ARRAY;
1918
ALLOC_HASHTABLE(Z_ARRVAL_PP(z));
1919
zend_hash_init(Z_ARRVAL_PP(z), n + 1, NULL, ZVAL_PTR_DTOR, 0);
1922
if (igsd->references_count + 1 >= igsd->references_capacity) {
1923
while (igsd->references_count + 1 >= igsd->references_capacity) {
1924
igsd->references_capacity *= 2;
1927
igsd->references = (void **) erealloc(igsd->references, sizeof(void *) * igsd->references_capacity);
1928
if (igsd->references == NULL)
1932
igsd->references[igsd->references_count++] = (void *) *z;
1942
for (i = 0; i < n; i++) {
1945
if (igsd->buffer_offset + 1 > igsd->buffer_size) {
1946
zend_error(E_WARNING, "igbinary_unserialize_array: end-of-data");
1952
key_type = (enum igbinary_type) igbinary_unserialize8(igsd TSRMLS_CC);
1955
case igbinary_type_long8p:
1956
case igbinary_type_long8n:
1957
case igbinary_type_long16p:
1958
case igbinary_type_long16n:
1959
case igbinary_type_long32p:
1960
case igbinary_type_long32n:
1961
case igbinary_type_long64p:
1962
case igbinary_type_long64n:
1963
if (igbinary_unserialize_long(igsd, key_type, &key_index TSRMLS_CC)) {
1969
case igbinary_type_string_id8:
1970
case igbinary_type_string_id16:
1971
case igbinary_type_string_id32:
1972
if (igbinary_unserialize_string(igsd, key_type, &key, &key_len TSRMLS_CC)) {
1978
case igbinary_type_string8:
1979
case igbinary_type_string16:
1980
case igbinary_type_string32:
1981
if (igbinary_unserialize_chararray(igsd, key_type, &key, &key_len TSRMLS_CC)) {
1987
case igbinary_type_string_empty:
1991
case igbinary_type_null:
1994
zend_error(E_WARNING, "igbinary_unserialize_array: unknown key type '%02x', position %zu", key_type, igsd->buffer_offset);
2002
if (igbinary_unserialize_zval(igsd, &v TSRMLS_CC)) {
2010
/* Keys must include a terminating null. */
2011
/* Ensure buffer starts at the beginning. */
2012
igsd->string0_buf.len = 0;
2013
smart_str_appendl(&igsd->string0_buf, key, key_len);
2014
smart_str_0(&igsd->string0_buf);
2016
if (zend_symtable_find(h, key, key_len + 1, (void **)&old_v) == SUCCESS) {
2017
var_push_dtor(var_hash, old_v);
2020
zend_symtable_update(h, igsd->string0_buf.c, igsd->string0_buf.len + 1, &v, sizeof(v), NULL);
2023
if (zend_hash_index_find(h, key_index, (void **)&old_v) == SUCCESS) {
2024
var_push_dtor(var_hash, old_v);
2027
zend_hash_index_update(h, key_index, &v, sizeof(v), NULL);
2034
/* {{{ igbinary_unserialize_object_ser */
2035
/** Unserializes object's property array of objects implementing Serializable -interface. */
2036
inline static int igbinary_unserialize_object_ser(struct igbinary_unserialize_data *igsd, enum igbinary_type t, zval **z, zend_class_entry *ce TSRMLS_DC) {
2039
php_unserialize_data_t var_hash;
2041
if (ce->unserialize == NULL) {
2042
zend_error(E_WARNING, "Class %s has no unserializer", ce->name);
2046
if (t == igbinary_type_object_ser8) {
2047
if (igsd->buffer_offset + 1 > igsd->buffer_size) {
2048
zend_error(E_WARNING, "igbinary_unserialize_object_ser: end-of-data");
2051
n = igbinary_unserialize8(igsd TSRMLS_CC);
2052
} else if (t == igbinary_type_object_ser16) {
2053
if (igsd->buffer_offset + 2 > igsd->buffer_size) {
2054
zend_error(E_WARNING, "igbinary_unserialize_object_ser: end-of-data");
2057
n = igbinary_unserialize16(igsd TSRMLS_CC);
2058
} else if (t == igbinary_type_object_ser32) {
2059
if (igsd->buffer_offset + 4 > igsd->buffer_size) {
2060
zend_error(E_WARNING, "igbinary_unserialize_object_ser: end-of-data");
2063
n = igbinary_unserialize32(igsd TSRMLS_CC);
2065
zend_error(E_WARNING, "igbinary_unserialize_object_ser: unknown type '%02x', position %zu", t, igsd->buffer_offset);
2069
if (igsd->buffer_offset + n > igsd->buffer_size) {
2070
zend_error(E_WARNING, "igbinary_unserialize_object_ser: end-of-data");
2074
PHP_VAR_UNSERIALIZE_INIT(var_hash);
2075
ret = ce->unserialize(z, ce,
2076
(const unsigned char*)(igsd->buffer + igsd->buffer_offset), n,
2077
(zend_unserialize_data *)&var_hash TSRMLS_CC);
2078
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
2080
if (ret != SUCCESS || EG(exception)) {
2084
igsd->buffer_offset += n;
2089
/* {{{ igbinary_unserialize_object */
2090
/** Unserialize object.
2091
* @see ext/standard/var_unserializer.c
2093
inline static int igbinary_unserialize_object(struct igbinary_unserialize_data *igsd, enum igbinary_type t, zval **z TSRMLS_DC) {
2094
zend_class_entry *ce;
2095
zend_class_entry **pce;
2101
size_t name_len = 0;
2105
bool incomplete_class = false;
2110
zval *arg_func_name;
2112
if (t == igbinary_type_object8 || t == igbinary_type_object16 || t == igbinary_type_object32) {
2113
if (igbinary_unserialize_chararray(igsd, t, &name, &name_len TSRMLS_CC)) {
2116
} else if (t == igbinary_type_object_id8 || t == igbinary_type_object_id16 || t == igbinary_type_object_id32) {
2117
if (igbinary_unserialize_string(igsd, t, &name, &name_len TSRMLS_CC)) {
2121
zend_error(E_WARNING, "igbinary_unserialize_object: unknown object type '%02x', position %zu", t, igsd->buffer_offset);
2126
/* Try to find class directly */
2127
if (zend_lookup_class(name, name_len, &pce TSRMLS_CC) == SUCCESS) {
2132
/* Check for unserialize callback */
2133
if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
2134
incomplete_class = 1;
2139
/* Call unserialize callback */
2140
MAKE_STD_ZVAL(user_func);
2141
ZVAL_STRING(user_func, PG(unserialize_callback_func), 1);
2142
args[0] = &arg_func_name;
2143
MAKE_STD_ZVAL(arg_func_name);
2144
ZVAL_STRING(arg_func_name, name, 1);
2145
if (call_user_function_ex(CG(function_table), NULL, user_func, &retval_ptr, 1, args, 0, NULL TSRMLS_CC) != SUCCESS) {
2146
php_error_docref(NULL TSRMLS_CC, E_WARNING, "defined (%s) but not found", name);
2147
incomplete_class = 1;
2149
zval_ptr_dtor(&user_func);
2150
zval_ptr_dtor(&arg_func_name);
2154
zval_ptr_dtor(&retval_ptr);
2157
/* The callback function may have defined the class */
2158
if (zend_lookup_class(name, name_len, &pce TSRMLS_CC) == SUCCESS) {
2161
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function %s() hasn't defined the class it was called for", name);
2162
incomplete_class = true;
2166
zval_ptr_dtor(&user_func);
2167
zval_ptr_dtor(&arg_func_name);
2170
/* previous user function call may have raised an exception */
2171
if (EG(exception)) {
2175
object_init_ex(*z, ce);
2178
if (igsd->references_count + 1 >= igsd->references_capacity) {
2179
while (igsd->references_count + 1 >= igsd->references_capacity) {
2180
igsd->references_capacity *= 2;
2183
igsd->references = (void **) erealloc(igsd->references, sizeof(void *) * igsd->references_capacity);
2184
if (igsd->references == NULL)
2188
igsd->references[igsd->references_count++] = (void *) *z;
2190
/* store incomplete class name */
2191
if (incomplete_class) {
2192
php_store_class_name(*z, name, name_len);
2195
t = (enum igbinary_type) igbinary_unserialize8(igsd TSRMLS_CC);
2197
case igbinary_type_array8:
2198
case igbinary_type_array16:
2199
case igbinary_type_array32:
2200
r = igbinary_unserialize_array(igsd, t, z, 1 TSRMLS_CC);
2202
case igbinary_type_object_ser8:
2203
case igbinary_type_object_ser16:
2204
case igbinary_type_object_ser32:
2205
r = igbinary_unserialize_object_ser(igsd, t, z, ce TSRMLS_CC);
2208
zend_error(E_WARNING, "igbinary_unserialize_object: unknown object inner type '%02x', position %zu", t, igsd->buffer_offset);
2216
if (Z_OBJCE_PP(z) != PHP_IC_ENTRY && zend_hash_exists(&Z_OBJCE_PP(z)->function_table, "__wakeup", sizeof("__wakeup"))) {
2218
ZVAL_STRINGL(&f, "__wakeup", sizeof("__wakeup") - 1, 0);
2219
call_user_function_ex(CG(function_table), z, &f, &h, 0, 0, 1, NULL TSRMLS_CC);
2225
if (EG(exception)) {
2233
/* {{{ igbinary_unserialize_ref */
2234
/** Unserializes array or object by reference. */
2235
inline static int igbinary_unserialize_ref(struct igbinary_unserialize_data *igsd, enum igbinary_type t, zval **z TSRMLS_DC) {
2238
if (t == igbinary_type_ref8 || t == igbinary_type_objref8) {
2239
if (igsd->buffer_offset + 1 > igsd->buffer_size) {
2240
zend_error(E_WARNING, "igbinary_unserialize_ref: end-of-data");
2243
n = igbinary_unserialize8(igsd TSRMLS_CC);
2244
} else if (t == igbinary_type_ref16 || t == igbinary_type_objref16) {
2245
if (igsd->buffer_offset + 2 > igsd->buffer_size) {
2246
zend_error(E_WARNING, "igbinary_unserialize_ref: end-of-data");
2249
n = igbinary_unserialize16(igsd TSRMLS_CC);
2250
} else if (t == igbinary_type_ref32 || t == igbinary_type_objref32) {
2251
if (igsd->buffer_offset + 4 > igsd->buffer_size) {
2252
zend_error(E_WARNING, "igbinary_unserialize_ref: end-of-data");
2255
n = igbinary_unserialize32(igsd TSRMLS_CC);
2257
zend_error(E_WARNING, "igbinary_unserialize_ref: unknown type '%02x', position %zu", t, igsd->buffer_offset);
2261
if (n >= igsd->references_count) {
2262
zend_error(E_WARNING, "igbinary_unserialize_ref: invalid reference");
2270
*z = igsd->references[n];
2273
if (t == igbinary_type_objref8 || t == igbinary_type_objref16 || t == igbinary_type_objref32) {
2274
Z_SET_ISREF_TO_PP(z, false);
2280
/* {{{ igbinary_unserialize_zval */
2281
/** Unserialize zval. */
2282
static int igbinary_unserialize_zval(struct igbinary_unserialize_data *igsd, zval **z TSRMLS_DC) {
2283
enum igbinary_type t;
2287
char *tmp_chararray;
2290
if (igsd->buffer_offset + 1 > igsd->buffer_size) {
2291
zend_error(E_WARNING, "igbinary_unserialize_zval: end-of-data");
2295
t = (enum igbinary_type) igbinary_unserialize8(igsd TSRMLS_CC);
2298
case igbinary_type_ref:
2299
if (igbinary_unserialize_zval(igsd, z TSRMLS_CC)) {
2302
/* Scalar types should be added to the references hash */
2303
/* unless they're already added */
2304
/* in references list: marked as ref */
2305
if (!Z_ISREF_PP(z)) switch (Z_TYPE_PP(z)) {
2312
if (igsd->references_count + 1 >= igsd->references_capacity) {
2313
while (igsd->references_count + 1 >= igsd->references_capacity) {
2314
igsd->references_capacity *= 2;
2317
igsd->references = (void **) erealloc(igsd->references, sizeof(void *) * igsd->references_capacity);
2318
if (igsd->references == NULL)
2322
igsd->references[igsd->references_count++] = (void *) *z;
2324
Z_SET_ISREF_TO_PP(z, true);
2326
case igbinary_type_objref8:
2327
case igbinary_type_objref16:
2328
case igbinary_type_objref32:
2329
case igbinary_type_ref8:
2330
case igbinary_type_ref16:
2331
case igbinary_type_ref32:
2332
if (igbinary_unserialize_ref(igsd, t, z TSRMLS_CC)) {
2336
case igbinary_type_object8:
2337
case igbinary_type_object16:
2338
case igbinary_type_object32:
2339
case igbinary_type_object_id8:
2340
case igbinary_type_object_id16:
2341
case igbinary_type_object_id32:
2342
if (igbinary_unserialize_object(igsd, t, z TSRMLS_CC)) {
2346
case igbinary_type_array8:
2347
case igbinary_type_array16:
2348
case igbinary_type_array32:
2349
if (igbinary_unserialize_array(igsd, t, z, 0 TSRMLS_CC)) {
2353
case igbinary_type_string_empty:
2354
ZVAL_EMPTY_STRING(*z);
2356
case igbinary_type_string_id8:
2357
case igbinary_type_string_id16:
2358
case igbinary_type_string_id32:
2359
if (igbinary_unserialize_string(igsd, t, &tmp_chararray, &tmp_size_t TSRMLS_CC)) {
2362
ZVAL_STRINGL(*z, tmp_chararray, tmp_size_t, 1);
2364
case igbinary_type_string8:
2365
case igbinary_type_string16:
2366
case igbinary_type_string32:
2367
if (igbinary_unserialize_chararray(igsd, t, &tmp_chararray, &tmp_size_t TSRMLS_CC)) {
2370
ZVAL_STRINGL(*z, tmp_chararray, tmp_size_t, 1);
2372
case igbinary_type_long8p:
2373
case igbinary_type_long8n:
2374
case igbinary_type_long16p:
2375
case igbinary_type_long16n:
2376
case igbinary_type_long32p:
2377
case igbinary_type_long32n:
2378
case igbinary_type_long64p:
2379
case igbinary_type_long64n:
2380
if (igbinary_unserialize_long(igsd, t, &tmp_long TSRMLS_CC)) {
2383
ZVAL_LONG(*z, tmp_long);
2385
case igbinary_type_null:
2388
case igbinary_type_bool_false:
2391
case igbinary_type_bool_true:
2394
case igbinary_type_double:
2395
if (igbinary_unserialize_double(igsd, t, &tmp_double TSRMLS_CC)) {
2398
ZVAL_DOUBLE(*z, tmp_double);
2401
zend_error(E_WARNING, "igbinary_unserialize_zval: unknown type '%02x', position %zu", t, igsd->buffer_offset);
2414
* vim600: noet sw=4 ts=4 fdm=marker
2415
* vim<600: noet sw=4 ts=4