This source file includes following definitions.
- php_array_element_dump
- php_object_property_dump
- php_var_dump
- PHP_FUNCTION
- zval_array_element_dump
- zval_object_property_dump
- php_debug_zval_dump
- PHP_FUNCTION
- php_array_element_export
- php_object_element_export
- php_var_export_ex
- php_var_export
- PHP_FUNCTION
- php_add_var_hash
- php_var_serialize_long
- php_var_serialize_string
- php_var_serialize_class_name
- php_var_serialize_class
- php_var_serialize_intern
- php_var_serialize
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #include "php.h"
29 #include "php_string.h"
30 #include "php_var.h"
31 #include "zend_smart_str.h"
32 #include "basic_functions.h"
33 #include "php_incomplete_class.h"
34
35 #define COMMON (is_ref ? "&" : "")
36
37
38 static void php_array_element_dump(zval *zv, zend_ulong index, zend_string *key, int level)
39 {
40 if (key == NULL) {
41 php_printf("%*c[" ZEND_LONG_FMT "]=>\n", level + 1, ' ', index);
42 } else {
43 php_printf("%*c[\"", level + 1, ' ');
44 PHPWRITE(ZSTR_VAL(key), ZSTR_LEN(key));
45 php_printf("\"]=>\n");
46 }
47 php_var_dump(zv, level + 2);
48 }
49
50
51 static void php_object_property_dump(zval *zv, zend_ulong index, zend_string *key, int level)
52 {
53 const char *prop_name, *class_name;
54
55 if (key == NULL) {
56 php_printf("%*c[" ZEND_LONG_FMT "]=>\n", level + 1, ' ', index);
57 } else {
58 int unmangle = zend_unmangle_property_name(key, &class_name, &prop_name);
59 php_printf("%*c[", level + 1, ' ');
60
61 if (class_name && unmangle == SUCCESS) {
62 if (class_name[0] == '*') {
63 php_printf("\"%s\":protected", prop_name);
64 } else {
65 php_printf("\"%s\":\"%s\":private", prop_name, class_name);
66 }
67 } else {
68 php_printf("\"");
69 PHPWRITE(ZSTR_VAL(key), ZSTR_LEN(key));
70 php_printf("\"");
71 }
72 ZEND_PUTS("]=>\n");
73 }
74 php_var_dump(zv, level + 2);
75 }
76
77
78 PHPAPI void php_var_dump(zval *struc, int level)
79 {
80 HashTable *myht;
81 zend_string *class_name;
82 int is_temp;
83 int is_ref = 0;
84 zend_ulong num;
85 zend_string *key;
86 zval *val;
87 uint32_t count;
88
89 if (level > 1) {
90 php_printf("%*c", level - 1, ' ');
91 }
92
93 again:
94 switch (Z_TYPE_P(struc)) {
95 case IS_FALSE:
96 php_printf("%sbool(false)\n", COMMON);
97 break;
98 case IS_TRUE:
99 php_printf("%sbool(true)\n", COMMON);
100 break;
101 case IS_NULL:
102 php_printf("%sNULL\n", COMMON);
103 break;
104 case IS_LONG:
105 php_printf("%sint(" ZEND_LONG_FMT ")\n", COMMON, Z_LVAL_P(struc));
106 break;
107 case IS_DOUBLE:
108 php_printf("%sfloat(%.*G)\n", COMMON, (int) EG(precision), Z_DVAL_P(struc));
109 break;
110 case IS_STRING:
111 php_printf("%sstring(%zd) \"", COMMON, Z_STRLEN_P(struc));
112 PHPWRITE(Z_STRVAL_P(struc), Z_STRLEN_P(struc));
113 PUTS("\"\n");
114 break;
115 case IS_ARRAY:
116 myht = Z_ARRVAL_P(struc);
117 if (level > 1 && ZEND_HASH_APPLY_PROTECTION(myht) && ++myht->u.v.nApplyCount > 1) {
118 PUTS("*RECURSION*\n");
119 --myht->u.v.nApplyCount;
120 return;
121 }
122 count = zend_array_count(myht);
123 php_printf("%sarray(%d) {\n", COMMON, count);
124 is_temp = 0;
125
126 ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) {
127 php_array_element_dump(val, num, key, level);
128 } ZEND_HASH_FOREACH_END();
129 if (level > 1 && ZEND_HASH_APPLY_PROTECTION(myht)) {
130 --myht->u.v.nApplyCount;
131 }
132 if (is_temp) {
133 zend_hash_destroy(myht);
134 efree(myht);
135 }
136 if (level > 1) {
137 php_printf("%*c", level-1, ' ');
138 }
139 PUTS("}\n");
140 break;
141 case IS_OBJECT:
142 if (Z_OBJ_APPLY_COUNT_P(struc) > 0) {
143 PUTS("*RECURSION*\n");
144 return;
145 }
146 Z_OBJ_INC_APPLY_COUNT_P(struc);
147
148 myht = Z_OBJDEBUG_P(struc, is_temp);
149 class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc));
150 php_printf("%sobject(%s)#%d (%d) {\n", COMMON, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? zend_array_count(myht) : 0);
151 zend_string_release(class_name);
152
153 if (myht) {
154 zend_ulong num;
155 zend_string *key;
156 zval *val;
157
158 ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) {
159 php_object_property_dump(val, num, key, level);
160 } ZEND_HASH_FOREACH_END();
161 if (is_temp) {
162 zend_hash_destroy(myht);
163 efree(myht);
164 }
165 }
166 if (level > 1) {
167 php_printf("%*c", level-1, ' ');
168 }
169 PUTS("}\n");
170 Z_OBJ_DEC_APPLY_COUNT_P(struc);
171 break;
172 case IS_RESOURCE: {
173 const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(struc));
174 php_printf("%sresource(%pd) of type (%s)\n", COMMON, Z_RES_P(struc)->handle, type_name ? type_name : "Unknown");
175 break;
176 }
177 case IS_REFERENCE:
178
179 if (Z_REFCOUNT_P(struc) > 1) {
180 is_ref = 1;
181 }
182 struc = Z_REFVAL_P(struc);
183 goto again;
184 break;
185 default:
186 php_printf("%sUNKNOWN:0\n", COMMON);
187 break;
188 }
189 }
190
191
192
193
194 PHP_FUNCTION(var_dump)
195 {
196 zval *args;
197 int argc;
198 int i;
199
200 if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
201 return;
202 }
203
204 for (i = 0; i < argc; i++) {
205 php_var_dump(&args[i], 1);
206 }
207 }
208
209
210 static void zval_array_element_dump(zval *zv, zend_ulong index, zend_string *key, int level)
211 {
212 if (key == NULL) {
213 php_printf("%*c[" ZEND_LONG_FMT "]=>\n", level + 1, ' ', index);
214 } else {
215 php_printf("%*c[\"", level + 1, ' ');
216 PHPWRITE(ZSTR_VAL(key), ZSTR_LEN(key));
217 php_printf("\"]=>\n");
218 }
219 php_debug_zval_dump(zv, level + 2);
220 }
221
222
223 static void zval_object_property_dump(zval *zv, zend_ulong index, zend_string *key, int level)
224 {
225 const char *prop_name, *class_name;
226
227 if (key == NULL) {
228 php_printf("%*c[" ZEND_LONG_FMT "]=>\n", level + 1, ' ', index);
229 } else {
230 zend_unmangle_property_name(key, &class_name, &prop_name);
231 php_printf("%*c[", level + 1, ' ');
232
233 if (class_name) {
234 if (class_name[0] == '*') {
235 php_printf("\"%s\":protected", prop_name);
236 } else {
237 php_printf("\"%s\":\"%s\":private", prop_name, class_name);
238 }
239 } else {
240 php_printf("\"%s\"", prop_name);
241 }
242 ZEND_PUTS("]=>\n");
243 }
244 php_debug_zval_dump(zv, level + 2);
245 }
246
247
248 PHPAPI void php_debug_zval_dump(zval *struc, int level)
249 {
250 HashTable *myht = NULL;
251 zend_string *class_name;
252 int is_temp = 0;
253 int is_ref = 0;
254 zend_ulong index;
255 zend_string *key;
256 zval *val;
257 uint32_t count;
258
259 if (level > 1) {
260 php_printf("%*c", level - 1, ' ');
261 }
262
263 again:
264 switch (Z_TYPE_P(struc)) {
265 case IS_FALSE:
266 php_printf("%sbool(false)\n", COMMON);
267 break;
268 case IS_TRUE:
269 php_printf("%sbool(true)\n", COMMON);
270 break;
271 case IS_NULL:
272 php_printf("%sNULL\n", COMMON);
273 break;
274 case IS_LONG:
275 php_printf("%sint(" ZEND_LONG_FMT ")\n", COMMON, Z_LVAL_P(struc));
276 break;
277 case IS_DOUBLE:
278 php_printf("%sfloat(%.*G)\n", COMMON, (int) EG(precision), Z_DVAL_P(struc));
279 break;
280 case IS_STRING:
281 php_printf("%sstring(%zd) \"", COMMON, Z_STRLEN_P(struc));
282 PHPWRITE(Z_STRVAL_P(struc), Z_STRLEN_P(struc));
283 php_printf("\" refcount(%u)\n", Z_REFCOUNTED_P(struc) ? Z_REFCOUNT_P(struc) : 1);
284 break;
285 case IS_ARRAY:
286 myht = Z_ARRVAL_P(struc);
287 if (level > 1 && ZEND_HASH_APPLY_PROTECTION(myht) && myht->u.v.nApplyCount++ > 1) {
288 myht->u.v.nApplyCount--;
289 PUTS("*RECURSION*\n");
290 return;
291 }
292 count = zend_array_count(myht);
293 php_printf("%sarray(%d) refcount(%u){\n", COMMON, count, Z_REFCOUNTED_P(struc) ? Z_REFCOUNT_P(struc) : 1);
294 ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, val) {
295 zval_array_element_dump(val, index, key, level);
296 } ZEND_HASH_FOREACH_END();
297 if (level > 1 && ZEND_HASH_APPLY_PROTECTION(myht)) {
298 myht->u.v.nApplyCount--;
299 }
300 if (is_temp) {
301 zend_hash_destroy(myht);
302 efree(myht);
303 }
304 if (level > 1) {
305 php_printf("%*c", level - 1, ' ');
306 }
307 PUTS("}\n");
308 break;
309 case IS_OBJECT:
310 myht = Z_OBJDEBUG_P(struc, is_temp);
311 if (myht) {
312 if (myht->u.v.nApplyCount > 1) {
313 PUTS("*RECURSION*\n");
314 return;
315 } else {
316 myht->u.v.nApplyCount++;
317 }
318 }
319 class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc));
320 php_printf("%sobject(%s)#%d (%d) refcount(%u){\n", COMMON, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? zend_array_count(myht) : 0, Z_REFCOUNT_P(struc));
321 zend_string_release(class_name);
322 if (myht) {
323 ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, val) {
324 zval_object_property_dump(val, index, key, level);
325 } ZEND_HASH_FOREACH_END();
326 myht->u.v.nApplyCount--;
327 if (is_temp) {
328 zend_hash_destroy(myht);
329 efree(myht);
330 }
331 }
332 if (level > 1) {
333 php_printf("%*c", level - 1, ' ');
334 }
335 PUTS("}\n");
336 break;
337 case IS_RESOURCE: {
338 const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(struc));
339 php_printf("%sresource(%d) of type (%s) refcount(%u)\n", COMMON, Z_RES_P(struc)->handle, type_name ? type_name : "Unknown", Z_REFCOUNT_P(struc));
340 break;
341 }
342 case IS_REFERENCE:
343
344 if (Z_REFCOUNT_P(struc) > 1) {
345 is_ref = 1;
346 }
347 struc = Z_REFVAL_P(struc);
348 goto again;
349 default:
350 php_printf("%sUNKNOWN:0\n", COMMON);
351 break;
352 }
353 }
354
355
356
357
358 PHP_FUNCTION(debug_zval_dump)
359 {
360 zval *args;
361 int argc;
362 int i;
363
364 if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
365 return;
366 }
367
368 for (i = 0; i < argc; i++) {
369 php_debug_zval_dump(&args[i], 1);
370 }
371 }
372
373
374 #define buffer_append_spaces(buf, num_spaces) \
375 do { \
376 char *tmp_spaces; \
377 size_t tmp_spaces_len; \
378 tmp_spaces_len = spprintf(&tmp_spaces, 0,"%*c", num_spaces, ' '); \
379 smart_str_appendl(buf, tmp_spaces, tmp_spaces_len); \
380 efree(tmp_spaces); \
381 } while(0);
382
383 static void php_array_element_export(zval *zv, zend_ulong index, zend_string *key, int level, smart_str *buf)
384 {
385 if (key == NULL) {
386 buffer_append_spaces(buf, level+1);
387 smart_str_append_long(buf, (zend_long) index);
388 smart_str_appendl(buf, " => ", 4);
389
390 } else {
391 zend_string *tmp_str;
392 zend_string *ckey = php_addcslashes(key, 0, "'\\", 2);
393 tmp_str = php_str_to_str(ZSTR_VAL(ckey), ZSTR_LEN(ckey), "\0", 1, "' . \"\\0\" . '", 12);
394
395 buffer_append_spaces(buf, level + 1);
396
397 smart_str_appendc(buf, '\'');
398 smart_str_append(buf, tmp_str);
399 smart_str_appendl(buf, "' => ", 5);
400
401 zend_string_free(ckey);
402 zend_string_free(tmp_str);
403 }
404 php_var_export_ex(zv, level + 2, buf);
405
406 smart_str_appendc(buf, ',');
407 smart_str_appendc(buf, '\n');
408 }
409
410
411 static void php_object_element_export(zval *zv, zend_ulong index, zend_string *key, int level, smart_str *buf)
412 {
413 buffer_append_spaces(buf, level + 2);
414 if (key != NULL) {
415 const char *class_name, *prop_name;
416 size_t prop_name_len;
417 zend_string *pname_esc;
418
419 zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_name_len);
420 pname_esc = php_addcslashes(zend_string_init(prop_name, prop_name_len, 0), 1, "'\\", 2);
421
422 smart_str_appendc(buf, '\'');
423 smart_str_append(buf, pname_esc);
424 smart_str_appendc(buf, '\'');
425 zend_string_release(pname_esc);
426 } else {
427 smart_str_append_long(buf, (zend_long) index);
428 }
429 smart_str_appendl(buf, " => ", 4);
430 php_var_export_ex(zv, level + 2, buf);
431 smart_str_appendc(buf, ',');
432 smart_str_appendc(buf, '\n');
433 }
434
435
436 PHPAPI void php_var_export_ex(zval *struc, int level, smart_str *buf)
437 {
438 HashTable *myht;
439 char *tmp_str;
440 size_t tmp_len;
441 zend_string *ztmp, *ztmp2;
442 zend_ulong index;
443 zend_string *key;
444 zval *val;
445
446 again:
447 switch (Z_TYPE_P(struc)) {
448 case IS_FALSE:
449 smart_str_appendl(buf, "false", 5);
450 break;
451 case IS_TRUE:
452 smart_str_appendl(buf, "true", 4);
453 break;
454 case IS_NULL:
455 smart_str_appendl(buf, "NULL", 4);
456 break;
457 case IS_LONG:
458 smart_str_append_long(buf, Z_LVAL_P(struc));
459 break;
460 case IS_DOUBLE:
461 tmp_len = spprintf(&tmp_str, 0,"%.*H", PG(serialize_precision), Z_DVAL_P(struc));
462 smart_str_appendl(buf, tmp_str, tmp_len);
463
464
465
466
467
468
469 if (zend_finite(Z_DVAL_P(struc)) && NULL == strchr(tmp_str, '.')) {
470 smart_str_appendl(buf, ".0", 2);
471 }
472 efree(tmp_str);
473 break;
474 case IS_STRING:
475 ztmp = php_addcslashes(Z_STR_P(struc), 0, "'\\", 2);
476 ztmp2 = php_str_to_str(ZSTR_VAL(ztmp), ZSTR_LEN(ztmp), "\0", 1, "' . \"\\0\" . '", 12);
477
478 smart_str_appendc(buf, '\'');
479 smart_str_append(buf, ztmp2);
480 smart_str_appendc(buf, '\'');
481
482 zend_string_free(ztmp);
483 zend_string_free(ztmp2);
484 break;
485 case IS_ARRAY:
486 myht = Z_ARRVAL_P(struc);
487 if (ZEND_HASH_APPLY_PROTECTION(myht) && myht->u.v.nApplyCount++ > 0) {
488 myht->u.v.nApplyCount--;
489 smart_str_appendl(buf, "NULL", 4);
490 zend_error(E_WARNING, "var_export does not handle circular references");
491 return;
492 }
493 if (level > 1) {
494 smart_str_appendc(buf, '\n');
495 buffer_append_spaces(buf, level - 1);
496 }
497 smart_str_appendl(buf, "array (\n", 8);
498 ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, val) {
499 php_array_element_export(val, index, key, level, buf);
500 } ZEND_HASH_FOREACH_END();
501 if (ZEND_HASH_APPLY_PROTECTION(myht)) {
502 myht->u.v.nApplyCount--;
503 }
504 if (level > 1) {
505 buffer_append_spaces(buf, level - 1);
506 }
507 smart_str_appendc(buf, ')');
508
509 break;
510
511 case IS_OBJECT:
512 myht = Z_OBJPROP_P(struc);
513 if (myht) {
514 if (myht->u.v.nApplyCount > 0) {
515 smart_str_appendl(buf, "NULL", 4);
516 zend_error(E_WARNING, "var_export does not handle circular references");
517 return;
518 } else {
519 myht->u.v.nApplyCount++;
520 }
521 }
522 if (level > 1) {
523 smart_str_appendc(buf, '\n');
524 buffer_append_spaces(buf, level - 1);
525 }
526
527 smart_str_append(buf, Z_OBJCE_P(struc)->name);
528 smart_str_appendl(buf, "::__set_state(array(\n", 21);
529
530 if (myht) {
531 ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, val) {
532 php_object_element_export(val, index, key, level, buf);
533 } ZEND_HASH_FOREACH_END();
534 myht->u.v.nApplyCount--;
535 }
536 if (level > 1) {
537 buffer_append_spaces(buf, level - 1);
538 }
539 smart_str_appendl(buf, "))", 2);
540
541 break;
542 case IS_REFERENCE:
543 struc = Z_REFVAL_P(struc);
544 goto again;
545 break;
546 default:
547 smart_str_appendl(buf, "NULL", 4);
548 break;
549 }
550 }
551
552
553
554 PHPAPI void php_var_export(zval *struc, int level)
555 {
556 smart_str buf = {0};
557 php_var_export_ex(struc, level, &buf);
558 smart_str_0(&buf);
559 PHPWRITE(ZSTR_VAL(buf.s), ZSTR_LEN(buf.s));
560 smart_str_free(&buf);
561 }
562
563
564
565
566 PHP_FUNCTION(var_export)
567 {
568 zval *var;
569 zend_bool return_output = 0;
570 smart_str buf = {0};
571
572 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|b", &var, &return_output) == FAILURE) {
573 return;
574 }
575
576 php_var_export_ex(var, 1, &buf);
577 smart_str_0 (&buf);
578
579 if (return_output) {
580 RETURN_NEW_STR(buf.s);
581 } else {
582 PHPWRITE(ZSTR_VAL(buf.s), ZSTR_LEN(buf.s));
583 smart_str_free(&buf);
584 }
585 }
586
587
588 static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_data_t var_hash);
589
590 static inline zend_long php_add_var_hash(php_serialize_data_t data, zval *var)
591 {
592 zval *zv;
593 zend_ulong key;
594 zend_bool is_ref = Z_ISREF_P(var);
595
596 data->n += 1;
597
598 if (!is_ref && Z_TYPE_P(var) != IS_OBJECT) {
599 return 0;
600 }
601
602
603 if (is_ref && Z_TYPE_P(Z_REFVAL_P(var)) == IS_OBJECT) {
604 var = Z_REFVAL_P(var);
605 }
606
607
608
609 key = (zend_ulong) (zend_uintptr_t) Z_COUNTED_P(var);
610 zv = zend_hash_index_find(&data->ht, key);
611
612 if (zv) {
613
614 if (is_ref) {
615 data->n -= 1;
616 }
617
618 return Z_LVAL_P(zv);
619 } else {
620 zval zv_n;
621 ZVAL_LONG(&zv_n, data->n);
622 zend_hash_index_add_new(&data->ht, key, &zv_n);
623
624
625
626
627
628 zend_hash_index_add_new(&data->ht, key + 1, var);
629 Z_ADDREF_P(var);
630
631 return 0;
632 }
633 }
634
635
636 static inline void php_var_serialize_long(smart_str *buf, zend_long val)
637 {
638 smart_str_appendl(buf, "i:", 2);
639 smart_str_append_long(buf, val);
640 smart_str_appendc(buf, ';');
641 }
642
643
644 static inline void php_var_serialize_string(smart_str *buf, char *str, size_t len)
645 {
646 smart_str_appendl(buf, "s:", 2);
647 smart_str_append_unsigned(buf, len);
648 smart_str_appendl(buf, ":\"", 2);
649 smart_str_appendl(buf, str, len);
650 smart_str_appendl(buf, "\";", 2);
651 }
652
653
654 static inline zend_bool php_var_serialize_class_name(smart_str *buf, zval *struc)
655 {
656 PHP_CLASS_ATTRIBUTES;
657
658 PHP_SET_CLASS_ATTRIBUTES(struc);
659 smart_str_appendl(buf, "O:", 2);
660 smart_str_append_unsigned(buf, ZSTR_LEN(class_name));
661 smart_str_appendl(buf, ":\"", 2);
662 smart_str_append(buf, class_name);
663 smart_str_appendl(buf, "\":", 2);
664 PHP_CLEANUP_CLASS_ATTRIBUTES();
665 return incomplete_class;
666 }
667
668
669 static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_ptr, php_serialize_data_t var_hash)
670 {
671 uint32_t count;
672 zend_bool incomplete_class;
673 HashTable *ht;
674
675 incomplete_class = php_var_serialize_class_name(buf, struc);
676
677
678 if (Z_TYPE_P(retval_ptr) == IS_ARRAY) {
679 ht = Z_ARRVAL_P(retval_ptr);
680 count = zend_array_count(ht);
681 } else if (Z_TYPE_P(retval_ptr) == IS_OBJECT) {
682 ht = Z_OBJPROP_P(retval_ptr);
683 count = zend_array_count(ht);
684 if (incomplete_class) {
685 --count;
686 }
687 } else {
688 count = 0;
689 }
690
691 smart_str_append_unsigned(buf, count);
692 smart_str_appendl(buf, ":{", 2);
693
694 if (count > 0) {
695 zend_string *key;
696 zval *d, *val;
697 zval nval, *nvalp;
698 zend_string *name;
699 HashTable *propers;
700
701 ZVAL_NULL(&nval);
702 nvalp = &nval;
703
704 ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
705 if (incomplete_class && strcmp(ZSTR_VAL(key), MAGIC_MEMBER) == 0) {
706 continue;
707 }
708
709 if (Z_TYPE_P(val) != IS_STRING) {
710 php_error_docref(NULL, E_NOTICE,
711 "__sleep should return an array only containing the names of instance-variables to serialize.");
712 }
713 name = zval_get_string(val);
714 propers = Z_OBJPROP_P(struc);
715 if ((d = zend_hash_find(propers, name)) != NULL) {
716 if (Z_TYPE_P(d) == IS_INDIRECT) {
717 d = Z_INDIRECT_P(d);
718 if (Z_TYPE_P(d) == IS_UNDEF) {
719 zend_string_release(name);
720 continue;
721 }
722 }
723 php_var_serialize_string(buf, ZSTR_VAL(name), ZSTR_LEN(name));
724 php_var_serialize_intern(buf, d, var_hash);
725 } else {
726 zend_class_entry *ce = Z_OBJ_P(struc)->ce;
727 if (ce) {
728 zend_string *prot_name, *priv_name;
729
730 do {
731 priv_name = zend_mangle_property_name(
732 ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), ZSTR_VAL(name), ZSTR_LEN(name), ce->type & ZEND_INTERNAL_CLASS);
733 if ((d = zend_hash_find(propers, priv_name)) != NULL) {
734 if (Z_TYPE_P(d) == IS_INDIRECT) {
735 d = Z_INDIRECT_P(d);
736 if (Z_ISUNDEF_P(d)) {
737 break;
738 }
739 }
740 php_var_serialize_string(buf, ZSTR_VAL(priv_name), ZSTR_LEN(priv_name));
741 zend_string_free(priv_name);
742 php_var_serialize_intern(buf, d, var_hash);
743 break;
744 }
745 zend_string_free(priv_name);
746 prot_name = zend_mangle_property_name(
747 "*", 1, ZSTR_VAL(name), ZSTR_LEN(name), ce->type & ZEND_INTERNAL_CLASS);
748 if ((d = zend_hash_find(propers, prot_name)) != NULL) {
749 if (Z_TYPE_P(d) == IS_INDIRECT) {
750 d = Z_INDIRECT_P(d);
751 if (Z_TYPE_P(d) == IS_UNDEF) {
752 zend_string_free(prot_name);
753 break;
754 }
755 }
756 php_var_serialize_string(buf, ZSTR_VAL(prot_name), ZSTR_LEN(prot_name));
757 zend_string_free(prot_name);
758 php_var_serialize_intern(buf, d, var_hash);
759 break;
760 }
761 zend_string_free(prot_name);
762 php_var_serialize_string(buf, ZSTR_VAL(name), ZSTR_LEN(name));
763 php_var_serialize_intern(buf, nvalp, var_hash);
764 php_error_docref(NULL, E_NOTICE,
765 "\"%s\" returned as member variable from __sleep() but does not exist", ZSTR_VAL(name));
766 } while (0);
767 } else {
768 php_var_serialize_string(buf, ZSTR_VAL(name), ZSTR_LEN(name));
769 php_var_serialize_intern(buf, nvalp, var_hash);
770 }
771 }
772 zend_string_release(name);
773 } ZEND_HASH_FOREACH_END();
774 }
775 smart_str_appendc(buf, '}');
776 }
777
778
779 static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_data_t var_hash)
780 {
781 zend_long var_already;
782 HashTable *myht;
783
784 if (EG(exception)) {
785 return;
786 }
787
788 if (var_hash && (var_already = php_add_var_hash(var_hash, struc))) {
789 if (Z_ISREF_P(struc)) {
790 smart_str_appendl(buf, "R:", 2);
791 smart_str_append_long(buf, var_already);
792 smart_str_appendc(buf, ';');
793 return;
794 } else if (Z_TYPE_P(struc) == IS_OBJECT) {
795 smart_str_appendl(buf, "r:", 2);
796 smart_str_append_long(buf, var_already);
797 smart_str_appendc(buf, ';');
798 return;
799 }
800 }
801
802 again:
803 switch (Z_TYPE_P(struc)) {
804 case IS_FALSE:
805 smart_str_appendl(buf, "b:0;", 4);
806 return;
807
808 case IS_TRUE:
809 smart_str_appendl(buf, "b:1;", 4);
810 return;
811
812 case IS_NULL:
813 smart_str_appendl(buf, "N;", 2);
814 return;
815
816 case IS_LONG:
817 php_var_serialize_long(buf, Z_LVAL_P(struc));
818 return;
819
820 case IS_DOUBLE: {
821 char *s;
822
823 smart_str_appendl(buf, "d:", 2);
824 s = (char *) safe_emalloc(PG(serialize_precision), 1, MAX_LENGTH_OF_DOUBLE + 1);
825 php_gcvt(Z_DVAL_P(struc), (int)PG(serialize_precision), '.', 'E', s);
826 smart_str_appends(buf, s);
827 smart_str_appendc(buf, ';');
828 efree(s);
829 return;
830 }
831
832 case IS_STRING:
833 php_var_serialize_string(buf, Z_STRVAL_P(struc), Z_STRLEN_P(struc));
834 return;
835
836 case IS_OBJECT: {
837 zval retval;
838 zval fname;
839 int res;
840 zend_class_entry *ce = Z_OBJCE_P(struc);
841
842 if (ce->serialize != NULL) {
843
844 unsigned char *serialized_data = NULL;
845 size_t serialized_length;
846
847 if (ce->serialize(struc, &serialized_data, &serialized_length, (zend_serialize_data *)var_hash) == SUCCESS) {
848 smart_str_appendl(buf, "C:", 2);
849 smart_str_append_unsigned(buf, ZSTR_LEN(Z_OBJCE_P(struc)->name));
850 smart_str_appendl(buf, ":\"", 2);
851 smart_str_append(buf, Z_OBJCE_P(struc)->name);
852 smart_str_appendl(buf, "\":", 2);
853
854 smart_str_append_unsigned(buf, serialized_length);
855 smart_str_appendl(buf, ":{", 2);
856 smart_str_appendl(buf, (char *) serialized_data, serialized_length);
857 smart_str_appendc(buf, '}');
858 } else {
859 smart_str_appendl(buf, "N;", 2);
860 }
861 if (serialized_data) {
862 efree(serialized_data);
863 }
864 return;
865 }
866
867 if (ce != PHP_IC_ENTRY && zend_hash_str_exists(&ce->function_table, "__sleep", sizeof("__sleep")-1)) {
868 ZVAL_STRINGL(&fname, "__sleep", sizeof("__sleep") - 1);
869 BG(serialize_lock)++;
870 res = call_user_function_ex(CG(function_table), struc, &fname, &retval, 0, 0, 1, NULL);
871 BG(serialize_lock)--;
872 zval_dtor(&fname);
873
874 if (EG(exception)) {
875 zval_ptr_dtor(&retval);
876 return;
877 }
878
879 if (res == SUCCESS) {
880 if (Z_TYPE(retval) != IS_UNDEF) {
881 if (HASH_OF(&retval)) {
882 php_var_serialize_class(buf, struc, &retval, var_hash);
883 } else {
884 php_error_docref(NULL, E_NOTICE, "__sleep should return an array only containing the names of instance-variables to serialize");
885
886
887 smart_str_appendl(buf,"N;", 2);
888 }
889 zval_ptr_dtor(&retval);
890 }
891 return;
892 }
893 zval_ptr_dtor(&retval);
894 }
895
896
897 }
898 case IS_ARRAY: {
899 uint32_t i;
900 zend_bool incomplete_class = 0;
901 if (Z_TYPE_P(struc) == IS_ARRAY) {
902 smart_str_appendl(buf, "a:", 2);
903 myht = Z_ARRVAL_P(struc);
904 i = zend_array_count(myht);
905 } else {
906 incomplete_class = php_var_serialize_class_name(buf, struc);
907 myht = Z_OBJPROP_P(struc);
908
909
910 i = zend_array_count(myht);
911 if (i > 0 && incomplete_class) {
912 --i;
913 }
914 }
915 smart_str_append_unsigned(buf, i);
916 smart_str_appendl(buf, ":{", 2);
917 if (i > 0) {
918 zend_string *key;
919 zval *data;
920 zend_ulong index;
921
922 ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, data) {
923
924 if (incomplete_class && strcmp(ZSTR_VAL(key), MAGIC_MEMBER) == 0) {
925 continue;
926 }
927
928 if (!key) {
929 php_var_serialize_long(buf, index);
930 } else {
931 php_var_serialize_string(buf, ZSTR_VAL(key), ZSTR_LEN(key));
932 }
933
934
935
936 if ((Z_TYPE_P(data) == IS_ARRAY && Z_TYPE_P(struc) == IS_ARRAY && Z_ARR_P(data) == Z_ARR_P(struc))
937 || (Z_TYPE_P(data) == IS_ARRAY && Z_ARRVAL_P(data)->u.v.nApplyCount > 1)
938 ) {
939 smart_str_appendl(buf, "N;", 2);
940 } else {
941 if (Z_TYPE_P(data) == IS_ARRAY && ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data))) {
942 Z_ARRVAL_P(data)->u.v.nApplyCount++;
943 }
944 php_var_serialize_intern(buf, data, var_hash);
945 if (Z_TYPE_P(data) == IS_ARRAY && ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data))) {
946 Z_ARRVAL_P(data)->u.v.nApplyCount--;
947 }
948 }
949 } ZEND_HASH_FOREACH_END();
950 }
951 smart_str_appendc(buf, '}');
952 return;
953 }
954 case IS_REFERENCE:
955 struc = Z_REFVAL_P(struc);
956 goto again;
957 default:
958 smart_str_appendl(buf, "i:0;", 4);
959 return;
960 }
961 }
962
963
964 PHPAPI void php_var_serialize(smart_str *buf, zval *struc, php_serialize_data_t *data)
965 {
966 php_var_serialize_intern(buf, struc, *data);
967 smart_str_0(buf);
968 }
969
970
971
972
973 PHP_FUNCTION(serialize)
974 {
975 zval *struc;
976 php_serialize_data_t var_hash;
977 smart_str buf = {0};
978
979 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &struc) == FAILURE) {
980 return;
981 }
982
983 PHP_VAR_SERIALIZE_INIT(var_hash);
984 php_var_serialize(&buf, struc, &var_hash);
985 PHP_VAR_SERIALIZE_DESTROY(var_hash);
986
987 if (EG(exception)) {
988 smart_str_free(&buf);
989 RETURN_FALSE;
990 }
991
992 if (buf.s) {
993 RETURN_NEW_STR(buf.s);
994 } else {
995 RETURN_NULL();
996 }
997 }
998
999
1000
1001
1002 PHP_FUNCTION(unserialize)
1003 {
1004 char *buf = NULL;
1005 size_t buf_len;
1006 const unsigned char *p;
1007 php_unserialize_data_t var_hash;
1008 zval *options = NULL, *classes = NULL;
1009 HashTable *class_hash = NULL;
1010
1011 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|a", &buf, &buf_len, &options) == FAILURE) {
1012 RETURN_FALSE;
1013 }
1014
1015 if (buf_len == 0) {
1016 RETURN_FALSE;
1017 }
1018
1019 p = (const unsigned char*) buf;
1020 PHP_VAR_UNSERIALIZE_INIT(var_hash);
1021 if(options != NULL) {
1022 classes = zend_hash_str_find(Z_ARRVAL_P(options), "allowed_classes", sizeof("allowed_classes")-1);
1023 if(classes && (Z_TYPE_P(classes) == IS_ARRAY || !zend_is_true(classes))) {
1024 ALLOC_HASHTABLE(class_hash);
1025 zend_hash_init(class_hash, (Z_TYPE_P(classes) == IS_ARRAY)?zend_hash_num_elements(Z_ARRVAL_P(classes)):0, NULL, NULL, 0);
1026 }
1027 if(class_hash && Z_TYPE_P(classes) == IS_ARRAY) {
1028 zval *entry;
1029 zend_string *lcname;
1030
1031 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(classes), entry) {
1032 convert_to_string_ex(entry);
1033 lcname = zend_string_tolower(Z_STR_P(entry));
1034 zend_hash_add_empty_element(class_hash, lcname);
1035 zend_string_release(lcname);
1036 } ZEND_HASH_FOREACH_END();
1037 }
1038 }
1039
1040 if (!php_var_unserialize_ex(return_value, &p, p + buf_len, &var_hash, class_hash)) {
1041 PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
1042 if(class_hash) {
1043 zend_hash_destroy(class_hash);
1044 FREE_HASHTABLE(class_hash);
1045 }
1046 zval_ptr_dtor(return_value);
1047 if (!EG(exception)) {
1048 php_error_docref(NULL, E_NOTICE, "Error at offset " ZEND_LONG_FMT " of %zd bytes",
1049 (zend_long)((char*)p - buf), buf_len);
1050 }
1051 RETURN_FALSE;
1052 }
1053 PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
1054 if(class_hash) {
1055 zend_hash_destroy(class_hash);
1056 FREE_HASHTABLE(class_hash);
1057 }
1058 }
1059
1060
1061
1062
1063 PHP_FUNCTION(memory_get_usage) {
1064 zend_bool real_usage = 0;
1065
1066 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &real_usage) == FAILURE) {
1067 RETURN_FALSE;
1068 }
1069
1070 RETURN_LONG(zend_memory_usage(real_usage));
1071 }
1072
1073
1074
1075
1076 PHP_FUNCTION(memory_get_peak_usage) {
1077 zend_bool real_usage = 0;
1078
1079 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &real_usage) == FAILURE) {
1080 RETURN_FALSE;
1081 }
1082
1083 RETURN_LONG(zend_memory_peak_usage(real_usage));
1084 }
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094