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