xref: /PHP-7.3/ext/json/json_parser.y (revision 918a9f09)
1 %code top {
2 /*
3   +----------------------------------------------------------------------+
4   | PHP Version 7                                                        |
5   +----------------------------------------------------------------------+
6   | Copyright (c) 1997-2018 The PHP Group                                |
7   +----------------------------------------------------------------------+
8   | This source file is subject to version 3.01 of the PHP license,      |
9   | that is bundled with this package in the file LICENSE, and is        |
10   | available through the world-wide-web at the following url:           |
11   | http://www.php.net/license/3_01.txt                                  |
12   | If you did not receive a copy of the PHP license and are unable to   |
13   | obtain it through the world-wide-web, please send a note to          |
14   | license@php.net so we can mail you a copy immediately.               |
15   +----------------------------------------------------------------------+
16   | Author: Jakub Zelenka <bukka@php.net>                                |
17   +----------------------------------------------------------------------+
18 */
19 
20 #include "php.h"
21 #include "php_json.h"
22 #include "php_json_parser.h"
23 
24 #define YYDEBUG 0
25 
26 #if YYDEBUG
27 int json_yydebug = 1;
28 #endif
29 
30 #ifdef _MSC_VER
31 #define YYMALLOC malloc
32 #define YYFREE free
33 #endif
34 
35 #define PHP_JSON_USE(uv) ((void) (uv))
36 #define PHP_JSON_USE_1(uvr, uv1) PHP_JSON_USE(uvr); PHP_JSON_USE(uv1)
37 #define PHP_JSON_USE_2(uvr, uv1, uv2) PHP_JSON_USE(uvr); PHP_JSON_USE(uv1); PHP_JSON_USE(uv2)
38 
39 #define PHP_JSON_DEPTH_DEC --parser->depth
40 #define PHP_JSON_DEPTH_INC \
41 	if (parser->max_depth && parser->depth >= parser->max_depth) { \
42 		parser->scanner.errcode = PHP_JSON_ERROR_DEPTH; \
43 		YYERROR; \
44 	} \
45 	++parser->depth
46 
47 }
48 
49 %pure-parser
50 %name-prefix "php_json_yy"
51 %lex-param  { php_json_parser *parser  }
52 %parse-param { php_json_parser *parser }
53 
54 %union {
55 	zval value;
56 	struct {
57 		zend_string *key;
58 		zval val;
59 	} pair;
60 }
61 
62 
63 %token <value> PHP_JSON_T_NUL
64 %token <value> PHP_JSON_T_TRUE
65 %token <value> PHP_JSON_T_FALSE
66 %token <value> PHP_JSON_T_INT
67 %token <value> PHP_JSON_T_DOUBLE
68 %token <value> PHP_JSON_T_STRING
69 %token <value> PHP_JSON_T_ESTRING
70 %token <value> PHP_JSON_T_EOI
71 %token <value> PHP_JSON_T_ERROR
72 
73 %type <value> start object key value array errlex
74 %type <value> members member elements element
75 %type <pair> pair
76 
77 %destructor { zval_ptr_dtor_nogc(&$$); } <value>
78 %destructor { zend_string_release_ex($$.key, 0); zval_ptr_dtor_nogc(&$$.val); } <pair>
79 
80 %code {
81 static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser);
82 static void php_json_yyerror(php_json_parser *parser, char const *msg);
83 
84 }
85 
86 %% /* Rules */
87 
88 start:
89 		value PHP_JSON_T_EOI
90 			{
91 				ZVAL_COPY_VALUE(&$$, &$1);
92 				ZVAL_COPY_VALUE(parser->return_value, &$1);
93 				PHP_JSON_USE($2); YYACCEPT;
94 			}
95 	|	value errlex
96 			{
97 				PHP_JSON_USE_2($$, $1, $2);
98 			}
99 ;
100 
101 object:
102 		'{'
103 			{
104 				PHP_JSON_DEPTH_INC;
105 				if (parser->methods.object_start && FAILURE == parser->methods.object_start(parser)) {
106 					YYERROR;
107 				}
108 			}
109 		members object_end
110 			{
111 				ZVAL_COPY_VALUE(&$$, &$3);
112 				PHP_JSON_DEPTH_DEC;
113 				if (parser->methods.object_end && FAILURE == parser->methods.object_end(parser, &$$)) {
114 					YYERROR;
115 				}
116 			}
117 ;
118 
119 object_end:
120 		'}'
121 	|	']'
122 			{
123 				parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH;
124 				YYERROR;
125 			}
126 ;
127 
128 members:
129 		/* empty */
130 			{
131 				parser->methods.object_create(parser, &$$);
132 			}
133 	|	member
134 ;
135 
136 member:
137 		pair
138 			{
139 				parser->methods.object_create(parser, &$$);
140 				if (parser->methods.object_update(parser, &$$, $1.key, &$1.val) == FAILURE) {
141 					YYERROR;
142 				}
143 			}
144 	|	member ',' pair
145 			{
146 				if (parser->methods.object_update(parser, &$1, $3.key, &$3.val) == FAILURE) {
147 					YYERROR;
148 				}
149 				ZVAL_COPY_VALUE(&$$, &$1);
150 			}
151 	|	member errlex
152 			{
153 				PHP_JSON_USE_2($$, $1, $2);
154 			}
155 ;
156 
157 pair:
158 		key ':' value
159 			{
160 				$$.key = Z_STR($1);
161 				ZVAL_COPY_VALUE(&$$.val, &$3);
162 			}
163 	|	key errlex
164 			{
165 				PHP_JSON_USE_2($$, $1, $2);
166 			}
167 ;
168 
169 array:
170 		'['
171 			{
172 				PHP_JSON_DEPTH_INC;
173 				if (parser->methods.array_start && FAILURE == parser->methods.array_start(parser)) {
174 					YYERROR;
175 				}
176 			}
177 		elements array_end
178 			{
179 				ZVAL_COPY_VALUE(&$$, &$3);
180 				PHP_JSON_DEPTH_DEC;
181 				if (parser->methods.array_end && FAILURE == parser->methods.array_end(parser, &$$)) {
182 					YYERROR;
183 				}
184 			}
185 ;
186 
187 array_end:
188 		']'
189 	|	'}'
190 			{
191 				parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH;
192 				YYERROR;
193 			}
194 ;
195 
196 elements:
197 		/* empty */
198 			{
199 				parser->methods.array_create(parser, &$$);
200 			}
201 	|	element
202 ;
203 
204 element:
205 		value
206 			{
207 				parser->methods.array_create(parser, &$$);
208 				parser->methods.array_append(parser, &$$, &$1);
209 			}
210 	|	element ',' value
211 			{
212 				parser->methods.array_append(parser, &$1, &$3);
213 				ZVAL_COPY_VALUE(&$$, &$1);
214 			}
215 	|	element errlex
216 			{
217 				PHP_JSON_USE_2($$, $1, $2);
218 			}
219 ;
220 
221 key:
222 		PHP_JSON_T_STRING
223 	|	PHP_JSON_T_ESTRING
224 ;
225 
226 value:
227 		object
228 	|	array
229 	|	PHP_JSON_T_STRING
230 	|	PHP_JSON_T_ESTRING
231 	|	PHP_JSON_T_INT
232 	|	PHP_JSON_T_DOUBLE
233 	|	PHP_JSON_T_NUL
234 	|	PHP_JSON_T_TRUE
235 	|	PHP_JSON_T_FALSE
236 	|	errlex
237 ;
238 
239 errlex:
240 		PHP_JSON_T_ERROR
241 			{
242 				PHP_JSON_USE_1($$, $1);
243 				YYERROR;
244 			}
245 ;
246 
247 %% /* Functions */
248 
249 static int php_json_parser_array_create(php_json_parser *parser, zval *array)
250 {
251 	array_init(array);
252 	return SUCCESS;
253 }
254 
php_json_parser_array_append(php_json_parser * parser,zval * array,zval * zvalue)255 static int php_json_parser_array_append(php_json_parser *parser, zval *array, zval *zvalue)
256 {
257 	zend_hash_next_index_insert(Z_ARRVAL_P(array), zvalue);
258 	return SUCCESS;
259 }
260 
php_json_parser_object_create(php_json_parser * parser,zval * object)261 static int php_json_parser_object_create(php_json_parser *parser, zval *object)
262 {
263 	if (parser->scanner.options & PHP_JSON_OBJECT_AS_ARRAY) {
264 		array_init(object);
265 		return SUCCESS;
266 	} else {
267 		return object_init(object);
268 	}
269 }
270 
php_json_parser_object_update(php_json_parser * parser,zval * object,zend_string * key,zval * zvalue)271 static int php_json_parser_object_update(php_json_parser *parser, zval *object, zend_string *key, zval *zvalue)
272 {
273 	/* if JSON_OBJECT_AS_ARRAY is set */
274 	if (Z_TYPE_P(object) == IS_ARRAY) {
275 		zend_symtable_update(Z_ARRVAL_P(object), key, zvalue);
276 	} else {
277 		zval zkey;
278 		if (ZSTR_LEN(key) > 0 && ZSTR_VAL(key)[0] == '\0') {
279 			parser->scanner.errcode = PHP_JSON_ERROR_INVALID_PROPERTY_NAME;
280 			zend_string_release_ex(key, 0);
281 			zval_ptr_dtor_nogc(zvalue);
282 			zval_ptr_dtor_nogc(object);
283 			return FAILURE;
284 		}
285 		ZVAL_NEW_STR(&zkey, key);
286 		zend_std_write_property(object, &zkey, zvalue, NULL);
287 		Z_TRY_DELREF_P(zvalue);
288 	}
289 	zend_string_release_ex(key, 0);
290 
291 	return SUCCESS;
292 }
293 
php_json_yylex(union YYSTYPE * value,php_json_parser * parser)294 static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser)
295 {
296 	int token = php_json_scan(&parser->scanner);
297 	value->value = parser->scanner.value;
298 	return token;
299 }
300 
php_json_yyerror(php_json_parser * parser,char const * msg)301 static void php_json_yyerror(php_json_parser *parser, char const *msg)
302 {
303 	if (!parser->scanner.errcode) {
304 		parser->scanner.errcode = PHP_JSON_ERROR_SYNTAX;
305 	}
306 }
307 
php_json_parser_error_code(const php_json_parser * parser)308 PHP_JSON_API php_json_error_code php_json_parser_error_code(const php_json_parser *parser)
309 {
310 	return parser->scanner.errcode;
311 }
312 
313 static const php_json_parser_methods default_parser_methods =
314 {
315 	php_json_parser_array_create,
316 	php_json_parser_array_append,
317 	NULL,
318 	NULL,
319 	php_json_parser_object_create,
320 	php_json_parser_object_update,
321 	NULL,
322 	NULL,
323 };
324 
php_json_parser_init_ex(php_json_parser * parser,zval * return_value,char * str,size_t str_len,int options,int max_depth,const php_json_parser_methods * parser_methods)325 PHP_JSON_API void php_json_parser_init_ex(php_json_parser *parser,
326 		zval *return_value,
327 		char *str,
328 		size_t str_len,
329 		int options,
330 		int max_depth,
331 		const php_json_parser_methods *parser_methods)
332 {
333 	memset(parser, 0, sizeof(php_json_parser));
334 	php_json_scanner_init(&parser->scanner, str, str_len, options);
335 	parser->depth = 1;
336 	parser->max_depth = max_depth;
337 	parser->return_value = return_value;
338 	memcpy(&parser->methods, parser_methods, sizeof(php_json_parser_methods));
339 }
340 
php_json_parser_init(php_json_parser * parser,zval * return_value,char * str,size_t str_len,int options,int max_depth)341 PHP_JSON_API void php_json_parser_init(php_json_parser *parser,
342 		zval *return_value,
343 		char *str,
344 		size_t str_len,
345 		int options,
346 		int max_depth)
347 {
348 	php_json_parser_init_ex(
349 			parser,
350 			return_value,
351 			str,
352 			str_len,
353 			options,
354 			max_depth,
355 			&default_parser_methods);
356 }
357 
php_json_parse(php_json_parser * parser)358 PHP_JSON_API int php_json_parse(php_json_parser *parser)
359 {
360 	return php_json_yyparse(parser);
361 }
362