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