1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Omar Kilani <omar@php.net> |
14 | Jakub Zelenka <bukka@php.net> |
15 +----------------------------------------------------------------------+
16 */
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include "php.h"
23 #include "php_ini.h"
24 #include "ext/standard/info.h"
25 #include "ext/standard/html.h"
26 #include "zend_smart_str.h"
27 #include "php_json.h"
28 #include "php_json_encoder.h"
29 #include <zend_exceptions.h>
30 #include "zend_enum.h"
31
32 static const char digits[] = "0123456789abcdef";
33
php_json_determine_array_type(zval * val)34 static int php_json_determine_array_type(zval *val) /* {{{ */
35 {
36 zend_array *myht = Z_ARRVAL_P(val);
37
38 if (myht) {
39 return zend_array_is_list(myht) ? PHP_JSON_OUTPUT_ARRAY : PHP_JSON_OUTPUT_OBJECT;
40 }
41
42 return PHP_JSON_OUTPUT_ARRAY;
43 }
44 /* }}} */
45
46 /* {{{ Pretty printing support functions */
47
php_json_pretty_print_char(smart_str * buf,int options,char c)48 static inline void php_json_pretty_print_char(smart_str *buf, int options, char c) /* {{{ */
49 {
50 if (options & PHP_JSON_PRETTY_PRINT) {
51 smart_str_appendc(buf, c);
52 }
53 }
54 /* }}} */
55
php_json_pretty_print_indent(smart_str * buf,int options,php_json_encoder * encoder)56 static inline void php_json_pretty_print_indent(smart_str *buf, int options, php_json_encoder *encoder) /* {{{ */
57 {
58 int i;
59
60 if (options & PHP_JSON_PRETTY_PRINT) {
61 for (i = 0; i < encoder->depth; ++i) {
62 smart_str_appendl(buf, " ", 4);
63 }
64 }
65 }
66 /* }}} */
67
68 /* }}} */
69
70 static
71 #if defined(_MSC_VER) && defined(_M_ARM64)
72 // MSVC bug: https://developercommunity.visualstudio.com/t/corrupt-optimization-on-arm64-with-Ox-/10102551
73 zend_never_inline
74 #else
75 inline
76 #endif
php_json_is_valid_double(double d)77 bool php_json_is_valid_double(double d) /* {{{ */
78 {
79 return !zend_isinf(d) && !zend_isnan(d);
80 }
81 /* }}} */
82
php_json_encode_double(smart_str * buf,double d,int options)83 static inline void php_json_encode_double(smart_str *buf, double d, int options) /* {{{ */
84 {
85 size_t len;
86 char num[ZEND_DOUBLE_MAX_LENGTH];
87
88 zend_gcvt(d, (int)PG(serialize_precision), '.', 'e', num);
89 len = strlen(num);
90 if (options & PHP_JSON_PRESERVE_ZERO_FRACTION && strchr(num, '.') == NULL && len < ZEND_DOUBLE_MAX_LENGTH - 2) {
91 num[len++] = '.';
92 num[len++] = '0';
93 num[len] = '\0';
94 }
95 smart_str_appendl(buf, num, len);
96 }
97 /* }}} */
98
99 #define PHP_JSON_HASH_PROTECT_RECURSION(_tmp_ht) \
100 do { \
101 if (_tmp_ht) { \
102 GC_TRY_PROTECT_RECURSION(_tmp_ht); \
103 } \
104 } while (0)
105
106 #define PHP_JSON_HASH_UNPROTECT_RECURSION(_tmp_ht) \
107 do { \
108 if (_tmp_ht) { \
109 GC_TRY_UNPROTECT_RECURSION(_tmp_ht); \
110 } \
111 } while (0)
112
php_json_encode_array(smart_str * buf,zval * val,int options,php_json_encoder * encoder)113 static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, php_json_encoder *encoder) /* {{{ */
114 {
115 int i, r, need_comma = 0;
116 HashTable *myht, *prop_ht;
117
118 if (Z_TYPE_P(val) == IS_ARRAY) {
119 myht = Z_ARRVAL_P(val);
120 prop_ht = NULL;
121 r = (options & PHP_JSON_FORCE_OBJECT) ? PHP_JSON_OUTPUT_OBJECT : php_json_determine_array_type(val);
122 } else if (Z_OBJ_P(val)->properties == NULL
123 && Z_OBJ_HT_P(val)->get_properties_for == NULL
124 && Z_OBJ_HT_P(val)->get_properties == zend_std_get_properties) {
125 /* Optimized version without rebuilding properties HashTable */
126 zend_object *obj = Z_OBJ_P(val);
127 zend_class_entry *ce = obj->ce;
128 zend_property_info *prop_info;
129 zval *prop;
130 int i;
131
132 if (GC_IS_RECURSIVE(obj)) {
133 encoder->error_code = PHP_JSON_ERROR_RECURSION;
134 smart_str_appendl(buf, "null", 4);
135 return FAILURE;
136 }
137
138 PHP_JSON_HASH_PROTECT_RECURSION(obj);
139
140 smart_str_appendc(buf, '{');
141
142 ++encoder->depth;
143
144 for (i = 0; i < ce->default_properties_count; i++) {
145 prop_info = ce->properties_info_table[i];
146 if (!prop_info) {
147 continue;
148 }
149 if (ZSTR_VAL(prop_info->name)[0] == '\0' && ZSTR_LEN(prop_info->name) > 0) {
150 /* Skip protected and private members. */
151 continue;
152 }
153 prop = OBJ_PROP(obj, prop_info->offset);
154 if (Z_TYPE_P(prop) == IS_UNDEF) {
155 continue;
156 }
157
158 if (need_comma) {
159 smart_str_appendc(buf, ',');
160 } else {
161 need_comma = 1;
162 }
163
164 php_json_pretty_print_char(buf, options, '\n');
165 php_json_pretty_print_indent(buf, options, encoder);
166
167 if (php_json_escape_string(buf, ZSTR_VAL(prop_info->name), ZSTR_LEN(prop_info->name),
168 options & ~PHP_JSON_NUMERIC_CHECK, encoder) == FAILURE &&
169 (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) &&
170 buf->s) {
171 ZSTR_LEN(buf->s) -= 4;
172 smart_str_appendl(buf, "\"\"", 2);
173 }
174
175 smart_str_appendc(buf, ':');
176 php_json_pretty_print_char(buf, options, ' ');
177
178 if (php_json_encode_zval(buf, prop, options, encoder) == FAILURE &&
179 !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
180 PHP_JSON_HASH_UNPROTECT_RECURSION(obj);
181 return FAILURE;
182 }
183 }
184
185 PHP_JSON_HASH_UNPROTECT_RECURSION(obj);
186 if (encoder->depth > encoder->max_depth) {
187 encoder->error_code = PHP_JSON_ERROR_DEPTH;
188 if (!(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
189 return FAILURE;
190 }
191 }
192 --encoder->depth;
193
194 if (need_comma) {
195 php_json_pretty_print_char(buf, options, '\n');
196 php_json_pretty_print_indent(buf, options, encoder);
197 }
198 smart_str_appendc(buf, '}');
199 return SUCCESS;
200 } else {
201 prop_ht = myht = zend_get_properties_for(val, ZEND_PROP_PURPOSE_JSON);
202 r = PHP_JSON_OUTPUT_OBJECT;
203 }
204
205 if (myht && GC_IS_RECURSIVE(myht)) {
206 encoder->error_code = PHP_JSON_ERROR_RECURSION;
207 smart_str_appendl(buf, "null", 4);
208 zend_release_properties(prop_ht);
209 return FAILURE;
210 }
211
212 PHP_JSON_HASH_PROTECT_RECURSION(myht);
213
214 if (r == PHP_JSON_OUTPUT_ARRAY) {
215 smart_str_appendc(buf, '[');
216 } else {
217 smart_str_appendc(buf, '{');
218 }
219
220 ++encoder->depth;
221
222 i = myht ? zend_hash_num_elements(myht) : 0;
223
224 if (i > 0) {
225 zend_string *key;
226 zval *data;
227 zend_ulong index;
228
229 ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, data) {
230 if (r == PHP_JSON_OUTPUT_ARRAY) {
231 if (need_comma) {
232 smart_str_appendc(buf, ',');
233 } else {
234 need_comma = 1;
235 }
236
237 php_json_pretty_print_char(buf, options, '\n');
238 php_json_pretty_print_indent(buf, options, encoder);
239 } else if (r == PHP_JSON_OUTPUT_OBJECT) {
240 if (key) {
241 if (ZSTR_VAL(key)[0] == '\0' && ZSTR_LEN(key) > 0 && Z_TYPE_P(val) == IS_OBJECT) {
242 /* Skip protected and private members. */
243 continue;
244 }
245
246 if (need_comma) {
247 smart_str_appendc(buf, ',');
248 } else {
249 need_comma = 1;
250 }
251
252 php_json_pretty_print_char(buf, options, '\n');
253 php_json_pretty_print_indent(buf, options, encoder);
254
255 if (php_json_escape_string(buf, ZSTR_VAL(key), ZSTR_LEN(key),
256 options & ~PHP_JSON_NUMERIC_CHECK, encoder) == FAILURE &&
257 (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) &&
258 buf->s) {
259 ZSTR_LEN(buf->s) -= 4;
260 smart_str_appendl(buf, "\"\"", 2);
261 }
262 } else {
263 if (need_comma) {
264 smart_str_appendc(buf, ',');
265 } else {
266 need_comma = 1;
267 }
268
269 php_json_pretty_print_char(buf, options, '\n');
270 php_json_pretty_print_indent(buf, options, encoder);
271
272 smart_str_appendc(buf, '"');
273 smart_str_append_long(buf, (zend_long) index);
274 smart_str_appendc(buf, '"');
275 }
276
277 smart_str_appendc(buf, ':');
278 php_json_pretty_print_char(buf, options, ' ');
279 }
280
281 if (php_json_encode_zval(buf, data, options, encoder) == FAILURE &&
282 !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
283 PHP_JSON_HASH_UNPROTECT_RECURSION(myht);
284 zend_release_properties(prop_ht);
285 return FAILURE;
286 }
287 } ZEND_HASH_FOREACH_END();
288 }
289
290 PHP_JSON_HASH_UNPROTECT_RECURSION(myht);
291
292 if (encoder->depth > encoder->max_depth) {
293 encoder->error_code = PHP_JSON_ERROR_DEPTH;
294 if (!(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
295 zend_release_properties(prop_ht);
296 return FAILURE;
297 }
298 }
299 --encoder->depth;
300
301 /* Only keep closing bracket on same line for empty arrays/objects */
302 if (need_comma) {
303 php_json_pretty_print_char(buf, options, '\n');
304 php_json_pretty_print_indent(buf, options, encoder);
305 }
306
307 if (r == PHP_JSON_OUTPUT_ARRAY) {
308 smart_str_appendc(buf, ']');
309 } else {
310 smart_str_appendc(buf, '}');
311 }
312
313 zend_release_properties(prop_ht);
314 return SUCCESS;
315 }
316 /* }}} */
317
php_json_escape_string(smart_str * buf,const char * s,size_t len,int options,php_json_encoder * encoder)318 zend_result php_json_escape_string(
319 smart_str *buf, const char *s, size_t len,
320 int options, php_json_encoder *encoder) /* {{{ */
321 {
322 unsigned int us;
323 size_t pos, checkpoint;
324 char *dst;
325
326 if (len == 0) {
327 smart_str_appendl(buf, "\"\"", 2);
328 return SUCCESS;
329 }
330
331 if (options & PHP_JSON_NUMERIC_CHECK) {
332 double d;
333 int type;
334 zend_long p;
335
336 if ((type = is_numeric_string(s, len, &p, &d, 0)) != 0) {
337 if (type == IS_LONG) {
338 smart_str_append_long(buf, p);
339 return SUCCESS;
340 } else if (type == IS_DOUBLE && php_json_is_valid_double(d)) {
341 php_json_encode_double(buf, d, options);
342 return SUCCESS;
343 }
344 }
345
346 }
347 checkpoint = buf->s ? ZSTR_LEN(buf->s) : 0;
348
349 /* pre-allocate for string length plus 2 quotes */
350 smart_str_alloc(buf, len+2, 0);
351 smart_str_appendc(buf, '"');
352
353 pos = 0;
354
355 do {
356 static const uint32_t charmap[8] = {
357 0xffffffff, 0x500080c4, 0x10000000, 0x00000000,
358 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff};
359
360 us = (unsigned char)s[pos];
361 if (EXPECTED(!ZEND_BIT_TEST(charmap, us))) {
362 pos++;
363 len--;
364 if (len == 0) {
365 smart_str_appendl(buf, s, pos);
366 break;
367 }
368 } else {
369 if (pos) {
370 smart_str_appendl(buf, s, pos);
371 s += pos;
372 pos = 0;
373 }
374 us = (unsigned char)s[0];
375 if (UNEXPECTED(us >= 0x80)) {
376 zend_result status;
377 us = php_next_utf8_char((unsigned char *)s, len, &pos, &status);
378
379 /* check whether UTF8 character is correct */
380 if (UNEXPECTED(status != SUCCESS)) {
381 if (options & PHP_JSON_INVALID_UTF8_IGNORE) {
382 /* ignore invalid UTF8 character */
383 } else if (options & PHP_JSON_INVALID_UTF8_SUBSTITUTE) {
384 /* Use Unicode character 'REPLACEMENT CHARACTER' (U+FFFD) */
385 if (options & PHP_JSON_UNESCAPED_UNICODE) {
386 smart_str_appendl(buf, "\xef\xbf\xbd", 3);
387 } else {
388 smart_str_appendl(buf, "\\ufffd", 6);
389 }
390 } else {
391 ZSTR_LEN(buf->s) = checkpoint;
392 encoder->error_code = PHP_JSON_ERROR_UTF8;
393 if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
394 smart_str_appendl(buf, "null", 4);
395 }
396 return FAILURE;
397 }
398
399 /* Escape U+2028/U+2029 line terminators, UNLESS both
400 JSON_UNESCAPED_UNICODE and
401 JSON_UNESCAPED_LINE_TERMINATORS were provided */
402 } else if ((options & PHP_JSON_UNESCAPED_UNICODE)
403 && ((options & PHP_JSON_UNESCAPED_LINE_TERMINATORS)
404 || us < 0x2028 || us > 0x2029)) {
405 smart_str_appendl(buf, s, pos);
406 } else {
407 /* From http://en.wikipedia.org/wiki/UTF16 */
408 if (us >= 0x10000) {
409 unsigned int next_us;
410
411 us -= 0x10000;
412 next_us = (unsigned short)((us & 0x3ff) | 0xdc00);
413 us = (unsigned short)((us >> 10) | 0xd800);
414 dst = smart_str_extend(buf, 6);
415 dst[0] = '\\';
416 dst[1] = 'u';
417 dst[2] = digits[(us >> 12) & 0xf];
418 dst[3] = digits[(us >> 8) & 0xf];
419 dst[4] = digits[(us >> 4) & 0xf];
420 dst[5] = digits[us & 0xf];
421 us = next_us;
422 }
423 dst = smart_str_extend(buf, 6);
424 dst[0] = '\\';
425 dst[1] = 'u';
426 dst[2] = digits[(us >> 12) & 0xf];
427 dst[3] = digits[(us >> 8) & 0xf];
428 dst[4] = digits[(us >> 4) & 0xf];
429 dst[5] = digits[us & 0xf];
430 }
431 s += pos;
432 len -= pos;
433 pos = 0;
434 } else {
435 s++;
436 switch (us) {
437 case '"':
438 if (options & PHP_JSON_HEX_QUOT) {
439 smart_str_appendl(buf, "\\u0022", 6);
440 } else {
441 smart_str_appendl(buf, "\\\"", 2);
442 }
443 break;
444
445 case '\\':
446 smart_str_appendl(buf, "\\\\", 2);
447 break;
448
449 case '/':
450 if (options & PHP_JSON_UNESCAPED_SLASHES) {
451 smart_str_appendc(buf, '/');
452 } else {
453 smart_str_appendl(buf, "\\/", 2);
454 }
455 break;
456
457 case '\b':
458 smart_str_appendl(buf, "\\b", 2);
459 break;
460
461 case '\f':
462 smart_str_appendl(buf, "\\f", 2);
463 break;
464
465 case '\n':
466 smart_str_appendl(buf, "\\n", 2);
467 break;
468
469 case '\r':
470 smart_str_appendl(buf, "\\r", 2);
471 break;
472
473 case '\t':
474 smart_str_appendl(buf, "\\t", 2);
475 break;
476
477 case '<':
478 if (options & PHP_JSON_HEX_TAG) {
479 smart_str_appendl(buf, "\\u003C", 6);
480 } else {
481 smart_str_appendc(buf, '<');
482 }
483 break;
484
485 case '>':
486 if (options & PHP_JSON_HEX_TAG) {
487 smart_str_appendl(buf, "\\u003E", 6);
488 } else {
489 smart_str_appendc(buf, '>');
490 }
491 break;
492
493 case '&':
494 if (options & PHP_JSON_HEX_AMP) {
495 smart_str_appendl(buf, "\\u0026", 6);
496 } else {
497 smart_str_appendc(buf, '&');
498 }
499 break;
500
501 case '\'':
502 if (options & PHP_JSON_HEX_APOS) {
503 smart_str_appendl(buf, "\\u0027", 6);
504 } else {
505 smart_str_appendc(buf, '\'');
506 }
507 break;
508
509 default:
510 ZEND_ASSERT(us < ' ');
511 dst = smart_str_extend(buf, 6);
512 dst[0] = '\\';
513 dst[1] = 'u';
514 dst[2] = '0';
515 dst[3] = '0';
516 dst[4] = digits[(us >> 4) & 0xf];
517 dst[5] = digits[us & 0xf];
518 break;
519 }
520 len--;
521 }
522 }
523 } while (len);
524
525 smart_str_appendc(buf, '"');
526
527 return SUCCESS;
528 }
529 /* }}} */
530
php_json_encode_serializable_object(smart_str * buf,zval * val,int options,php_json_encoder * encoder)531 static zend_result php_json_encode_serializable_object(smart_str *buf, zval *val, int options, php_json_encoder *encoder) /* {{{ */
532 {
533 zend_class_entry *ce = Z_OBJCE_P(val);
534 HashTable* myht = Z_OBJPROP_P(val);
535 zval retval, fname;
536 zend_result return_code;
537
538 if (myht && GC_IS_RECURSIVE(myht)) {
539 encoder->error_code = PHP_JSON_ERROR_RECURSION;
540 if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
541 smart_str_appendl(buf, "null", 4);
542 }
543 return FAILURE;
544 }
545
546 PHP_JSON_HASH_PROTECT_RECURSION(myht);
547
548 ZVAL_STRING(&fname, "jsonSerialize");
549
550 if (FAILURE == call_user_function(NULL, val, &fname, &retval, 0, NULL) || Z_TYPE(retval) == IS_UNDEF) {
551 if (!EG(exception)) {
552 zend_throw_exception_ex(NULL, 0, "Failed calling %s::jsonSerialize()", ZSTR_VAL(ce->name));
553 }
554 zval_ptr_dtor(&fname);
555
556 if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
557 smart_str_appendl(buf, "null", 4);
558 }
559 PHP_JSON_HASH_UNPROTECT_RECURSION(myht);
560 return FAILURE;
561 }
562
563 if (EG(exception)) {
564 /* Error already raised */
565 zval_ptr_dtor(&retval);
566 zval_ptr_dtor(&fname);
567
568 if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
569 smart_str_appendl(buf, "null", 4);
570 }
571 PHP_JSON_HASH_UNPROTECT_RECURSION(myht);
572 return FAILURE;
573 }
574
575 if ((Z_TYPE(retval) == IS_OBJECT) &&
576 (Z_OBJ(retval) == Z_OBJ_P(val))) {
577 /* Handle the case where jsonSerialize does: return $this; by going straight to encode array */
578 PHP_JSON_HASH_UNPROTECT_RECURSION(myht);
579 return_code = php_json_encode_array(buf, &retval, options, encoder);
580 } else {
581 /* All other types, encode as normal */
582 return_code = php_json_encode_zval(buf, &retval, options, encoder);
583 PHP_JSON_HASH_UNPROTECT_RECURSION(myht);
584 }
585
586 zval_ptr_dtor(&retval);
587 zval_ptr_dtor(&fname);
588
589 return return_code;
590 }
591 /* }}} */
592
php_json_encode_serializable_enum(smart_str * buf,zval * val,int options,php_json_encoder * encoder)593 static zend_result php_json_encode_serializable_enum(smart_str *buf, zval *val, int options, php_json_encoder *encoder)
594 {
595 zend_class_entry *ce = Z_OBJCE_P(val);
596 if (ce->enum_backing_type == IS_UNDEF) {
597 encoder->error_code = PHP_JSON_ERROR_NON_BACKED_ENUM;
598 smart_str_appendc(buf, '0');
599 return FAILURE;
600 }
601
602 zval *value_zv = zend_enum_fetch_case_value(Z_OBJ_P(val));
603 return php_json_encode_zval(buf, value_zv, options, encoder);
604 }
605
php_json_encode_zval(smart_str * buf,zval * val,int options,php_json_encoder * encoder)606 zend_result php_json_encode_zval(smart_str *buf, zval *val, int options, php_json_encoder *encoder) /* {{{ */
607 {
608 again:
609 switch (Z_TYPE_P(val))
610 {
611 case IS_NULL:
612 smart_str_appendl(buf, "null", 4);
613 break;
614
615 case IS_TRUE:
616 smart_str_appendl(buf, "true", 4);
617 break;
618 case IS_FALSE:
619 smart_str_appendl(buf, "false", 5);
620 break;
621
622 case IS_LONG:
623 smart_str_append_long(buf, Z_LVAL_P(val));
624 break;
625
626 case IS_DOUBLE:
627 if (php_json_is_valid_double(Z_DVAL_P(val))) {
628 php_json_encode_double(buf, Z_DVAL_P(val), options);
629 } else {
630 encoder->error_code = PHP_JSON_ERROR_INF_OR_NAN;
631 smart_str_appendc(buf, '0');
632 }
633 break;
634
635 case IS_STRING:
636 return php_json_escape_string(buf, Z_STRVAL_P(val), Z_STRLEN_P(val), options, encoder);
637
638 case IS_OBJECT:
639 if (instanceof_function(Z_OBJCE_P(val), php_json_serializable_ce)) {
640 return php_json_encode_serializable_object(buf, val, options, encoder);
641 }
642 if (Z_OBJCE_P(val)->ce_flags & ZEND_ACC_ENUM) {
643 return php_json_encode_serializable_enum(buf, val, options, encoder);
644 }
645 /* fallthrough -- Non-serializable object */
646 ZEND_FALLTHROUGH;
647 case IS_ARRAY: {
648 /* Avoid modifications (and potential freeing) of the array through a reference when a
649 * jsonSerialize() method is invoked. */
650 zval zv;
651 int res;
652 ZVAL_COPY(&zv, val);
653 res = php_json_encode_array(buf, &zv, options, encoder);
654 zval_ptr_dtor_nogc(&zv);
655 return res;
656 }
657
658 case IS_REFERENCE:
659 val = Z_REFVAL_P(val);
660 goto again;
661
662 default:
663 encoder->error_code = PHP_JSON_ERROR_UNSUPPORTED_TYPE;
664 if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
665 smart_str_appendl(buf, "null", 4);
666 }
667 return FAILURE;
668 }
669
670 return SUCCESS;
671 }
672 /* }}} */
673