PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/json - json_encoder.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 257 263 97.7 %
Date: 2019-05-06 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Mon, 06 May 2019 17:58:16 +0000 (998 days ago)

Copyright © 2005-2022 The PHP Group
All rights reserved.