json.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  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. #ifdef HAVE_CONFIG_H
  18. #include "config.h"
  19. #endif
  20. #include "php.h"
  21. #include "php_ini.h"
  22. #include "ext/standard/info.h"
  23. #include "ext/standard/html.h"
  24. #include "zend_smart_str.h"
  25. #include "php_json.h"
  26. #include "php_json_encoder.h"
  27. #include "php_json_parser.h"
  28. #include "json_arginfo.h"
  29. #include <zend_exceptions.h>
  30. static PHP_MINFO_FUNCTION(json);
  31. PHP_JSON_API zend_class_entry *php_json_serializable_ce;
  32. PHP_JSON_API zend_class_entry *php_json_exception_ce;
  33. PHP_JSON_API ZEND_DECLARE_MODULE_GLOBALS(json)
  34. /* Register constant for options and errors */
  35. #define PHP_JSON_REGISTER_CONSTANT(_name, _value) \
  36. REGISTER_LONG_CONSTANT(_name, _value, CONST_CS | CONST_PERSISTENT);
  37. /* {{{ MINIT */
  38. static PHP_MINIT_FUNCTION(json)
  39. {
  40. php_json_serializable_ce = register_class_JsonSerializable();
  41. php_json_exception_ce = register_class_JsonException(zend_ce_exception);
  42. /* options for json_encode */
  43. PHP_JSON_REGISTER_CONSTANT("JSON_HEX_TAG", PHP_JSON_HEX_TAG);
  44. PHP_JSON_REGISTER_CONSTANT("JSON_HEX_AMP", PHP_JSON_HEX_AMP);
  45. PHP_JSON_REGISTER_CONSTANT("JSON_HEX_APOS", PHP_JSON_HEX_APOS);
  46. PHP_JSON_REGISTER_CONSTANT("JSON_HEX_QUOT", PHP_JSON_HEX_QUOT);
  47. PHP_JSON_REGISTER_CONSTANT("JSON_FORCE_OBJECT", PHP_JSON_FORCE_OBJECT);
  48. PHP_JSON_REGISTER_CONSTANT("JSON_NUMERIC_CHECK", PHP_JSON_NUMERIC_CHECK);
  49. PHP_JSON_REGISTER_CONSTANT("JSON_UNESCAPED_SLASHES", PHP_JSON_UNESCAPED_SLASHES);
  50. PHP_JSON_REGISTER_CONSTANT("JSON_PRETTY_PRINT", PHP_JSON_PRETTY_PRINT);
  51. PHP_JSON_REGISTER_CONSTANT("JSON_UNESCAPED_UNICODE", PHP_JSON_UNESCAPED_UNICODE);
  52. PHP_JSON_REGISTER_CONSTANT("JSON_PARTIAL_OUTPUT_ON_ERROR", PHP_JSON_PARTIAL_OUTPUT_ON_ERROR);
  53. PHP_JSON_REGISTER_CONSTANT("JSON_PRESERVE_ZERO_FRACTION", PHP_JSON_PRESERVE_ZERO_FRACTION);
  54. PHP_JSON_REGISTER_CONSTANT("JSON_UNESCAPED_LINE_TERMINATORS", PHP_JSON_UNESCAPED_LINE_TERMINATORS);
  55. /* options for json_decode */
  56. PHP_JSON_REGISTER_CONSTANT("JSON_OBJECT_AS_ARRAY", PHP_JSON_OBJECT_AS_ARRAY);
  57. PHP_JSON_REGISTER_CONSTANT("JSON_BIGINT_AS_STRING", PHP_JSON_BIGINT_AS_STRING);
  58. /* common options for json_decode and json_encode */
  59. PHP_JSON_REGISTER_CONSTANT("JSON_INVALID_UTF8_IGNORE", PHP_JSON_INVALID_UTF8_IGNORE);
  60. PHP_JSON_REGISTER_CONSTANT("JSON_INVALID_UTF8_SUBSTITUTE", PHP_JSON_INVALID_UTF8_SUBSTITUTE);
  61. PHP_JSON_REGISTER_CONSTANT("JSON_THROW_ON_ERROR", PHP_JSON_THROW_ON_ERROR);
  62. /* json error constants */
  63. PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_NONE", PHP_JSON_ERROR_NONE);
  64. PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_DEPTH", PHP_JSON_ERROR_DEPTH);
  65. PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_STATE_MISMATCH", PHP_JSON_ERROR_STATE_MISMATCH);
  66. PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_CTRL_CHAR", PHP_JSON_ERROR_CTRL_CHAR);
  67. PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_SYNTAX", PHP_JSON_ERROR_SYNTAX);
  68. PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_UTF8", PHP_JSON_ERROR_UTF8);
  69. PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_RECURSION", PHP_JSON_ERROR_RECURSION);
  70. PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_INF_OR_NAN", PHP_JSON_ERROR_INF_OR_NAN);
  71. PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_UNSUPPORTED_TYPE", PHP_JSON_ERROR_UNSUPPORTED_TYPE);
  72. PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_INVALID_PROPERTY_NAME", PHP_JSON_ERROR_INVALID_PROPERTY_NAME);
  73. PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_UTF16", PHP_JSON_ERROR_UTF16);
  74. PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_NON_BACKED_ENUM", PHP_JSON_ERROR_NON_BACKED_ENUM);
  75. return SUCCESS;
  76. }
  77. /* }}} */
  78. /* {{{ PHP_GINIT_FUNCTION */
  79. static PHP_GINIT_FUNCTION(json)
  80. {
  81. #if defined(COMPILE_DL_JSON) && defined(ZTS)
  82. ZEND_TSRMLS_CACHE_UPDATE();
  83. #endif
  84. json_globals->encoder_depth = 0;
  85. json_globals->error_code = 0;
  86. json_globals->encode_max_depth = PHP_JSON_PARSER_DEFAULT_DEPTH;
  87. }
  88. /* }}} */
  89. static PHP_RINIT_FUNCTION(json)
  90. {
  91. JSON_G(error_code) = 0;
  92. return SUCCESS;
  93. }
  94. /* {{{ json_module_entry */
  95. zend_module_entry json_module_entry = {
  96. STANDARD_MODULE_HEADER,
  97. "json",
  98. ext_functions,
  99. PHP_MINIT(json),
  100. NULL,
  101. PHP_RINIT(json),
  102. NULL,
  103. PHP_MINFO(json),
  104. PHP_JSON_VERSION,
  105. PHP_MODULE_GLOBALS(json),
  106. PHP_GINIT(json),
  107. NULL,
  108. NULL,
  109. STANDARD_MODULE_PROPERTIES_EX
  110. };
  111. /* }}} */
  112. #ifdef COMPILE_DL_JSON
  113. #ifdef ZTS
  114. ZEND_TSRMLS_CACHE_DEFINE()
  115. #endif
  116. ZEND_GET_MODULE(json)
  117. #endif
  118. /* {{{ PHP_MINFO_FUNCTION */
  119. static PHP_MINFO_FUNCTION(json)
  120. {
  121. php_info_print_table_start();
  122. php_info_print_table_row(2, "json support", "enabled");
  123. php_info_print_table_end();
  124. }
  125. /* }}} */
  126. PHP_JSON_API int php_json_encode_ex(smart_str *buf, zval *val, int options, zend_long depth) /* {{{ */
  127. {
  128. php_json_encoder encoder;
  129. int return_code;
  130. php_json_encode_init(&encoder);
  131. encoder.max_depth = depth;
  132. return_code = php_json_encode_zval(buf, val, options, &encoder);
  133. JSON_G(error_code) = encoder.error_code;
  134. return return_code;
  135. }
  136. /* }}} */
  137. PHP_JSON_API int php_json_encode(smart_str *buf, zval *val, int options) /* {{{ */
  138. {
  139. return php_json_encode_ex(buf, val, options, JSON_G(encode_max_depth));
  140. }
  141. /* }}} */
  142. static const char *php_json_get_error_msg(php_json_error_code error_code) /* {{{ */
  143. {
  144. switch(error_code) {
  145. case PHP_JSON_ERROR_NONE:
  146. return "No error";
  147. case PHP_JSON_ERROR_DEPTH:
  148. return "Maximum stack depth exceeded";
  149. case PHP_JSON_ERROR_STATE_MISMATCH:
  150. return "State mismatch (invalid or malformed JSON)";
  151. case PHP_JSON_ERROR_CTRL_CHAR:
  152. return "Control character error, possibly incorrectly encoded";
  153. case PHP_JSON_ERROR_SYNTAX:
  154. return "Syntax error";
  155. case PHP_JSON_ERROR_UTF8:
  156. return "Malformed UTF-8 characters, possibly incorrectly encoded";
  157. case PHP_JSON_ERROR_RECURSION:
  158. return "Recursion detected";
  159. case PHP_JSON_ERROR_INF_OR_NAN:
  160. return "Inf and NaN cannot be JSON encoded";
  161. case PHP_JSON_ERROR_UNSUPPORTED_TYPE:
  162. return "Type is not supported";
  163. case PHP_JSON_ERROR_INVALID_PROPERTY_NAME:
  164. return "The decoded property name is invalid";
  165. case PHP_JSON_ERROR_UTF16:
  166. return "Single unpaired UTF-16 surrogate in unicode escape";
  167. case PHP_JSON_ERROR_NON_BACKED_ENUM:
  168. return "Non-backed enums have no default serialization";
  169. default:
  170. return "Unknown error";
  171. }
  172. }
  173. /* }}} */
  174. PHP_JSON_API int php_json_decode_ex(zval *return_value, const char *str, size_t str_len, zend_long options, zend_long depth) /* {{{ */
  175. {
  176. php_json_parser parser;
  177. php_json_parser_init(&parser, return_value, str, str_len, (int)options, (int)depth);
  178. if (php_json_yyparse(&parser)) {
  179. php_json_error_code error_code = php_json_parser_error_code(&parser);
  180. if (!(options & PHP_JSON_THROW_ON_ERROR)) {
  181. JSON_G(error_code) = error_code;
  182. } else {
  183. zend_throw_exception(php_json_exception_ce, php_json_get_error_msg(error_code), error_code);
  184. }
  185. RETVAL_NULL();
  186. return FAILURE;
  187. }
  188. return SUCCESS;
  189. }
  190. /* }}} */
  191. /* {{{ Returns the JSON representation of a value */
  192. PHP_FUNCTION(json_encode)
  193. {
  194. zval *parameter;
  195. php_json_encoder encoder;
  196. smart_str buf = {0};
  197. zend_long options = 0;
  198. zend_long depth = PHP_JSON_PARSER_DEFAULT_DEPTH;
  199. ZEND_PARSE_PARAMETERS_START(1, 3)
  200. Z_PARAM_ZVAL(parameter)
  201. Z_PARAM_OPTIONAL
  202. Z_PARAM_LONG(options)
  203. Z_PARAM_LONG(depth)
  204. ZEND_PARSE_PARAMETERS_END();
  205. php_json_encode_init(&encoder);
  206. encoder.max_depth = (int)depth;
  207. php_json_encode_zval(&buf, parameter, (int)options, &encoder);
  208. if (!(options & PHP_JSON_THROW_ON_ERROR) || (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
  209. JSON_G(error_code) = encoder.error_code;
  210. if (encoder.error_code != PHP_JSON_ERROR_NONE && !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
  211. smart_str_free(&buf);
  212. RETURN_FALSE;
  213. }
  214. } else {
  215. if (encoder.error_code != PHP_JSON_ERROR_NONE) {
  216. smart_str_free(&buf);
  217. zend_throw_exception(php_json_exception_ce, php_json_get_error_msg(encoder.error_code), encoder.error_code);
  218. RETURN_THROWS();
  219. }
  220. }
  221. smart_str_0(&buf); /* copy? */
  222. if (buf.s) {
  223. RETURN_NEW_STR(buf.s);
  224. }
  225. RETURN_EMPTY_STRING();
  226. }
  227. /* }}} */
  228. /* {{{ Decodes the JSON representation into a PHP value */
  229. PHP_FUNCTION(json_decode)
  230. {
  231. char *str;
  232. size_t str_len;
  233. bool assoc = 0; /* return JS objects as PHP objects by default */
  234. bool assoc_null = 1;
  235. zend_long depth = PHP_JSON_PARSER_DEFAULT_DEPTH;
  236. zend_long options = 0;
  237. ZEND_PARSE_PARAMETERS_START(1, 4)
  238. Z_PARAM_STRING(str, str_len)
  239. Z_PARAM_OPTIONAL
  240. Z_PARAM_BOOL_OR_NULL(assoc, assoc_null)
  241. Z_PARAM_LONG(depth)
  242. Z_PARAM_LONG(options)
  243. ZEND_PARSE_PARAMETERS_END();
  244. if (!(options & PHP_JSON_THROW_ON_ERROR)) {
  245. JSON_G(error_code) = PHP_JSON_ERROR_NONE;
  246. }
  247. if (!str_len) {
  248. if (!(options & PHP_JSON_THROW_ON_ERROR)) {
  249. JSON_G(error_code) = PHP_JSON_ERROR_SYNTAX;
  250. } else {
  251. zend_throw_exception(php_json_exception_ce, php_json_get_error_msg(PHP_JSON_ERROR_SYNTAX), PHP_JSON_ERROR_SYNTAX);
  252. }
  253. RETURN_NULL();
  254. }
  255. if (depth <= 0) {
  256. zend_argument_value_error(3, "must be greater than 0");
  257. RETURN_THROWS();
  258. }
  259. if (depth > INT_MAX) {
  260. zend_argument_value_error(3, "must be less than %d", INT_MAX);
  261. RETURN_THROWS();
  262. }
  263. /* For BC reasons, the bool $assoc overrides the long $options bit for PHP_JSON_OBJECT_AS_ARRAY */
  264. if (!assoc_null) {
  265. if (assoc) {
  266. options |= PHP_JSON_OBJECT_AS_ARRAY;
  267. } else {
  268. options &= ~PHP_JSON_OBJECT_AS_ARRAY;
  269. }
  270. }
  271. php_json_decode_ex(return_value, str, str_len, options, depth);
  272. }
  273. /* }}} */
  274. /* {{{ Returns the error code of the last json_encode() or json_decode() call. */
  275. PHP_FUNCTION(json_last_error)
  276. {
  277. ZEND_PARSE_PARAMETERS_NONE();
  278. RETURN_LONG(JSON_G(error_code));
  279. }
  280. /* }}} */
  281. /* {{{ Returns the error string of the last json_encode() or json_decode() call. */
  282. PHP_FUNCTION(json_last_error_msg)
  283. {
  284. ZEND_PARSE_PARAMETERS_NONE();
  285. RETURN_STRING(php_json_get_error_msg(JSON_G(error_code)));
  286. }
  287. /* }}} */