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