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.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 140 150 93.3 %
Date: 2019-05-06 Functions: 9 11 81.8 %
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 "php_json_parser.h"
      32             : #include <zend_exceptions.h>
      33             : 
      34             : static PHP_MINFO_FUNCTION(json);
      35             : static PHP_FUNCTION(json_encode);
      36             : static PHP_FUNCTION(json_decode);
      37             : static PHP_FUNCTION(json_last_error);
      38             : static PHP_FUNCTION(json_last_error_msg);
      39             : 
      40             : PHP_JSON_API zend_class_entry *php_json_serializable_ce;
      41             : PHP_JSON_API zend_class_entry *php_json_exception_ce;
      42             : 
      43             : PHP_JSON_API ZEND_DECLARE_MODULE_GLOBALS(json)
      44             : 
      45             : /* {{{ arginfo */
      46             : ZEND_BEGIN_ARG_INFO_EX(arginfo_json_encode, 0, 0, 1)
      47             :         ZEND_ARG_INFO(0, value)
      48             :         ZEND_ARG_INFO(0, options)
      49             :         ZEND_ARG_INFO(0, depth)
      50             : ZEND_END_ARG_INFO()
      51             : 
      52             : ZEND_BEGIN_ARG_INFO_EX(arginfo_json_decode, 0, 0, 1)
      53             :         ZEND_ARG_INFO(0, json)
      54             :         ZEND_ARG_INFO(0, assoc)
      55             :         ZEND_ARG_INFO(0, depth)
      56             :         ZEND_ARG_INFO(0, options)
      57             : ZEND_END_ARG_INFO()
      58             : 
      59             : ZEND_BEGIN_ARG_INFO(arginfo_json_last_error, 0)
      60             : ZEND_END_ARG_INFO()
      61             : 
      62             : ZEND_BEGIN_ARG_INFO(arginfo_json_last_error_msg, 0)
      63             : ZEND_END_ARG_INFO()
      64             : /* }}} */
      65             : 
      66             : /* {{{ json_functions[] */
      67             : static const zend_function_entry json_functions[] = {
      68             :         PHP_FE(json_encode, arginfo_json_encode)
      69             :         PHP_FE(json_decode, arginfo_json_decode)
      70             :         PHP_FE(json_last_error, arginfo_json_last_error)
      71             :         PHP_FE(json_last_error_msg, arginfo_json_last_error_msg)
      72             :         PHP_FE_END
      73             : };
      74             : /* }}} */
      75             : 
      76             : /* {{{ JsonSerializable methods */
      77             : ZEND_BEGIN_ARG_INFO(json_serialize_arginfo, 0)
      78             :         /* No arguments */
      79             : ZEND_END_ARG_INFO();
      80             : 
      81             : static const zend_function_entry json_serializable_interface[] = {
      82             :         PHP_ABSTRACT_ME(JsonSerializable, jsonSerialize, json_serialize_arginfo)
      83             :         PHP_FE_END
      84             : };
      85             : /* }}} */
      86             : 
      87             : /* Register constant for options and errors */
      88             : #define PHP_JSON_REGISTER_CONSTANT(_name, _value) \
      89             :         REGISTER_LONG_CONSTANT(_name,  _value, CONST_CS | CONST_PERSISTENT);
      90             : 
      91             : /* {{{ MINIT */
      92       23043 : static PHP_MINIT_FUNCTION(json)
      93             : {
      94             :         zend_class_entry ce;
      95             : 
      96       23043 :         INIT_CLASS_ENTRY(ce, "JsonSerializable", json_serializable_interface);
      97       23043 :         php_json_serializable_ce = zend_register_internal_interface(&ce);
      98             : 
      99       23043 :         INIT_CLASS_ENTRY(ce, "JsonException", NULL);
     100       23043 :         php_json_exception_ce = zend_register_internal_class_ex(&ce, zend_ce_exception);
     101             : 
     102             :         /* options for json_encode */
     103       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_HEX_TAG",  PHP_JSON_HEX_TAG);
     104       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_HEX_AMP",  PHP_JSON_HEX_AMP);
     105       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_HEX_APOS", PHP_JSON_HEX_APOS);
     106       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_HEX_QUOT", PHP_JSON_HEX_QUOT);
     107       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_FORCE_OBJECT", PHP_JSON_FORCE_OBJECT);
     108       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_NUMERIC_CHECK", PHP_JSON_NUMERIC_CHECK);
     109       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_UNESCAPED_SLASHES", PHP_JSON_UNESCAPED_SLASHES);
     110       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_PRETTY_PRINT", PHP_JSON_PRETTY_PRINT);
     111       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_UNESCAPED_UNICODE", PHP_JSON_UNESCAPED_UNICODE);
     112       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_PARTIAL_OUTPUT_ON_ERROR", PHP_JSON_PARTIAL_OUTPUT_ON_ERROR);
     113       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_PRESERVE_ZERO_FRACTION", PHP_JSON_PRESERVE_ZERO_FRACTION);
     114       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_UNESCAPED_LINE_TERMINATORS", PHP_JSON_UNESCAPED_LINE_TERMINATORS);
     115             : 
     116             :         /* options for json_decode */
     117       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_OBJECT_AS_ARRAY", PHP_JSON_OBJECT_AS_ARRAY);
     118       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_BIGINT_AS_STRING", PHP_JSON_BIGINT_AS_STRING);
     119             : 
     120             :         /* common options for json_decode and json_encode */
     121       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_INVALID_UTF8_IGNORE", PHP_JSON_INVALID_UTF8_IGNORE);
     122       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_INVALID_UTF8_SUBSTITUTE", PHP_JSON_INVALID_UTF8_SUBSTITUTE);
     123       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_THROW_ON_ERROR", PHP_JSON_THROW_ON_ERROR);
     124             : 
     125             :         /* json error constants */
     126       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_NONE", PHP_JSON_ERROR_NONE);
     127       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_DEPTH", PHP_JSON_ERROR_DEPTH);
     128       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_STATE_MISMATCH", PHP_JSON_ERROR_STATE_MISMATCH);
     129       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_CTRL_CHAR", PHP_JSON_ERROR_CTRL_CHAR);
     130       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_SYNTAX", PHP_JSON_ERROR_SYNTAX);
     131       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_UTF8", PHP_JSON_ERROR_UTF8);
     132       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_RECURSION", PHP_JSON_ERROR_RECURSION);
     133       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_INF_OR_NAN", PHP_JSON_ERROR_INF_OR_NAN);
     134       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_UNSUPPORTED_TYPE", PHP_JSON_ERROR_UNSUPPORTED_TYPE);
     135       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_INVALID_PROPERTY_NAME", PHP_JSON_ERROR_INVALID_PROPERTY_NAME);
     136       23043 :         PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_UTF16", PHP_JSON_ERROR_UTF16);
     137             : 
     138       23043 :         return SUCCESS;
     139             : }
     140             : /* }}} */
     141             : 
     142             : /* {{{ PHP_GINIT_FUNCTION
     143             : */
     144       23043 : static PHP_GINIT_FUNCTION(json)
     145             : {
     146             : #if defined(COMPILE_DL_JSON) && defined(ZTS)
     147             :         ZEND_TSRMLS_CACHE_UPDATE();
     148             : #endif
     149       23043 :         json_globals->encoder_depth = 0;
     150       23043 :         json_globals->error_code = 0;
     151       23043 :         json_globals->encode_max_depth = PHP_JSON_PARSER_DEFAULT_DEPTH;
     152       23043 : }
     153             : /* }}} */
     154             : 
     155             : 
     156             : /* {{{ json_module_entry
     157             :  */
     158             : zend_module_entry json_module_entry = {
     159             :         STANDARD_MODULE_HEADER,
     160             :         "json",
     161             :         json_functions,
     162             :         PHP_MINIT(json),
     163             :         NULL,
     164             :         NULL,
     165             :         NULL,
     166             :         PHP_MINFO(json),
     167             :         PHP_JSON_VERSION,
     168             :         PHP_MODULE_GLOBALS(json),
     169             :         PHP_GINIT(json),
     170             :         NULL,
     171             :         NULL,
     172             :         STANDARD_MODULE_PROPERTIES_EX
     173             : };
     174             : /* }}} */
     175             : 
     176             : #ifdef COMPILE_DL_JSON
     177             : #ifdef ZTS
     178             : ZEND_TSRMLS_CACHE_DEFINE()
     179             : #endif
     180             : ZEND_GET_MODULE(json)
     181             : #endif
     182             : 
     183             : /* {{{ PHP_MINFO_FUNCTION
     184             :  */
     185         146 : static PHP_MINFO_FUNCTION(json)
     186             : {
     187         146 :         php_info_print_table_start();
     188         146 :         php_info_print_table_row(2, "json support", "enabled");
     189         146 :         php_info_print_table_row(2, "json version", PHP_JSON_VERSION);
     190         146 :         php_info_print_table_end();
     191         146 : }
     192             : /* }}} */
     193             : 
     194           0 : PHP_JSON_API int php_json_encode_ex(smart_str *buf, zval *val, int options, zend_long depth) /* {{{ */
     195             : {
     196             :         php_json_encoder encoder;
     197             :         int return_code;
     198             : 
     199           0 :         php_json_encode_init(&encoder);
     200           0 :         encoder.max_depth = depth;
     201             : 
     202           0 :         return_code = php_json_encode_zval(buf, val, options, &encoder);
     203           0 :         JSON_G(error_code) = encoder.error_code;
     204             : 
     205           0 :         return return_code;
     206             : }
     207             : /* }}} */
     208             : 
     209           0 : PHP_JSON_API int php_json_encode(smart_str *buf, zval *val, int options) /* {{{ */
     210             : {
     211           0 :         return php_json_encode_ex(buf, val, options, JSON_G(encode_max_depth));
     212             : }
     213             : /* }}} */
     214             : 
     215          32 : static const char *php_json_get_error_msg(php_json_error_code error_code) /* {{{ */
     216             : {
     217          32 :         switch(error_code) {
     218           2 :                 case PHP_JSON_ERROR_NONE:
     219           2 :                         return "No error";
     220           1 :                 case PHP_JSON_ERROR_DEPTH:
     221           1 :                         return "Maximum stack depth exceeded";
     222           1 :                 case PHP_JSON_ERROR_STATE_MISMATCH:
     223           1 :                         return "State mismatch (invalid or malformed JSON)";
     224           1 :                 case PHP_JSON_ERROR_CTRL_CHAR:
     225           1 :                         return "Control character error, possibly incorrectly encoded";
     226           4 :                 case PHP_JSON_ERROR_SYNTAX:
     227           4 :                         return "Syntax error";
     228          10 :                 case PHP_JSON_ERROR_UTF8:
     229          10 :                         return "Malformed UTF-8 characters, possibly incorrectly encoded";
     230           4 :                 case PHP_JSON_ERROR_RECURSION:
     231           4 :                         return "Recursion detected";
     232           5 :                 case PHP_JSON_ERROR_INF_OR_NAN:
     233           5 :                         return "Inf and NaN cannot be JSON encoded";
     234           2 :                 case PHP_JSON_ERROR_UNSUPPORTED_TYPE:
     235           2 :                         return "Type is not supported";
     236           1 :                 case PHP_JSON_ERROR_INVALID_PROPERTY_NAME:
     237           1 :                         return "The decoded property name is invalid";
     238           1 :                 case PHP_JSON_ERROR_UTF16:
     239           1 :                         return "Single unpaired UTF-16 surrogate in unicode escape";
     240           0 :                 default:
     241           0 :                         return "Unknown error";
     242             :         }
     243             : }
     244             : /* }}} */
     245             : 
     246         237 : PHP_JSON_API int php_json_decode_ex(zval *return_value, char *str, size_t str_len, zend_long options, zend_long depth) /* {{{ */
     247             : {
     248             :         php_json_parser parser;
     249             : 
     250         237 :         php_json_parser_init(&parser, return_value, str, str_len, (int)options, (int)depth);
     251             : 
     252         237 :         if (php_json_yyparse(&parser)) {
     253          83 :                 php_json_error_code error_code = php_json_parser_error_code(&parser);
     254          83 :                 if (!(options & PHP_JSON_THROW_ON_ERROR)) {
     255          81 :                         JSON_G(error_code) = error_code;
     256             :                 } else {
     257           2 :                         zend_throw_exception(php_json_exception_ce, php_json_get_error_msg(error_code), error_code);
     258             :                 }
     259          83 :                 RETVAL_NULL();
     260          83 :                 return FAILURE;
     261             :         }
     262             : 
     263         154 :         return SUCCESS;
     264             : }
     265             : /* }}} */
     266             : 
     267             : /* {{{ proto string json_encode(mixed data [, int options[, int depth]])
     268             :    Returns the JSON representation of a value */
     269         469 : static PHP_FUNCTION(json_encode)
     270             : {
     271             :         zval *parameter;
     272             :         php_json_encoder encoder;
     273         469 :         smart_str buf = {0};
     274         469 :         zend_long options = 0;
     275         469 :         zend_long depth = PHP_JSON_PARSER_DEFAULT_DEPTH;
     276             : 
     277         469 :         ZEND_PARSE_PARAMETERS_START(1, 3)
     278         469 :                 Z_PARAM_ZVAL(parameter)
     279         469 :                 Z_PARAM_OPTIONAL
     280         544 :                 Z_PARAM_LONG(options)
     281          77 :                 Z_PARAM_LONG(depth)
     282         469 :         ZEND_PARSE_PARAMETERS_END();
     283             : 
     284         469 :         php_json_encode_init(&encoder);
     285         469 :         encoder.max_depth = (int)depth;
     286         469 :         php_json_encode_zval(&buf, parameter, (int)options, &encoder);
     287             : 
     288         469 :         if (!(options & PHP_JSON_THROW_ON_ERROR) || (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
     289         467 :                 JSON_G(error_code) = encoder.error_code;
     290         913 :                 if (encoder.error_code != PHP_JSON_ERROR_NONE && !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
     291             :                         smart_str_free(&buf);
     292          21 :                         RETURN_FALSE;
     293             :                 }
     294             :         } else {
     295           2 :                 if (encoder.error_code != PHP_JSON_ERROR_NONE) {
     296             :                         smart_str_free(&buf);
     297           2 :                         zend_throw_exception(php_json_exception_ce, php_json_get_error_msg(encoder.error_code), encoder.error_code);
     298           2 :                         RETURN_FALSE;
     299             :                 }
     300             :         }
     301             : 
     302             :         smart_str_0(&buf); /* copy? */
     303         446 :         if (buf.s) {
     304         445 :                 RETURN_NEW_STR(buf.s);
     305             :         }
     306           1 :         RETURN_EMPTY_STRING();
     307             : }
     308             : /* }}} */
     309             : 
     310             : /* {{{ proto mixed json_decode(string json [, bool assoc [, int depth]])
     311             :    Decodes the JSON representation into a PHP value */
     312         253 : static PHP_FUNCTION(json_decode)
     313             : {
     314             :         char *str;
     315             :         size_t str_len;
     316         253 :         zend_bool assoc = 0; /* return JS objects as PHP objects by default */
     317         253 :         zend_bool assoc_null = 1;
     318         253 :         zend_long depth = PHP_JSON_PARSER_DEFAULT_DEPTH;
     319         253 :         zend_long options = 0;
     320             : 
     321         253 :         ZEND_PARSE_PARAMETERS_START(1, 4)
     322         506 :                 Z_PARAM_STRING(str, str_len)
     323         253 :                 Z_PARAM_OPTIONAL
     324         343 :                 Z_PARAM_BOOL_EX(assoc, assoc_null, 1, 0)
     325         111 :                 Z_PARAM_LONG(depth)
     326          39 :                 Z_PARAM_LONG(options)
     327         253 :         ZEND_PARSE_PARAMETERS_END();
     328             : 
     329         253 :         if (!(options & PHP_JSON_THROW_ON_ERROR)) {
     330         250 :                 JSON_G(error_code) = PHP_JSON_ERROR_NONE;
     331             :         }
     332             : 
     333         253 :         if (!str_len) {
     334          14 :                 if (!(options & PHP_JSON_THROW_ON_ERROR)) {
     335          13 :                         JSON_G(error_code) = PHP_JSON_ERROR_SYNTAX;
     336             :                 } else {
     337           1 :                         zend_throw_exception(php_json_exception_ce, php_json_get_error_msg(PHP_JSON_ERROR_SYNTAX), PHP_JSON_ERROR_SYNTAX);
     338             :                 }
     339          14 :                 RETURN_NULL();
     340             :         }
     341             : 
     342         239 :         if (depth <= 0) {
     343           1 :                 php_error_docref(NULL, E_WARNING, "Depth must be greater than zero");
     344           1 :                 RETURN_NULL();
     345             :         }
     346             : 
     347         238 :         if (depth > INT_MAX) {
     348           1 :                 php_error_docref(NULL, E_WARNING, "Depth must be lower than %d", INT_MAX);
     349           1 :                 RETURN_NULL();
     350             :         }
     351             : 
     352             :         /* For BC reasons, the bool $assoc overrides the long $options bit for PHP_JSON_OBJECT_AS_ARRAY */
     353         237 :         if (!assoc_null) {
     354          80 :                 if (assoc) {
     355          70 :                         options |=  PHP_JSON_OBJECT_AS_ARRAY;
     356             :                 } else {
     357          10 :                         options &= ~PHP_JSON_OBJECT_AS_ARRAY;
     358             :                 }
     359             :         }
     360             : 
     361         237 :         php_json_decode_ex(return_value, str, str_len, options, depth);
     362             : }
     363             : /* }}} */
     364             : 
     365             : /* {{{ proto int json_last_error()
     366             :    Returns the error code of the last json_encode() or json_decode() call. */
     367          88 : static PHP_FUNCTION(json_last_error)
     368             : {
     369          88 :         if (zend_parse_parameters_none() == FAILURE) {
     370           1 :                 return;
     371             :         }
     372             : 
     373          87 :         RETURN_LONG(JSON_G(error_code));
     374             : }
     375             : /* }}} */
     376             : 
     377             : /* {{{ proto string json_last_error_msg()
     378             :    Returns the error string of the last json_encode() or json_decode() call. */
     379          28 : static PHP_FUNCTION(json_last_error_msg)
     380             : {
     381          28 :         if (zend_parse_parameters_none() == FAILURE) {
     382           1 :                 return;
     383             :         }
     384             : 
     385          54 :         RETURN_STRING(php_json_get_error_msg(JSON_G(error_code)));
     386             : }
     387             : /* }}} */

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.