xref: /PHP-7.2/ext/json/json_parser.y (revision 7a7ec01a)
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_dtor(&$$); } <value>
78 %destructor { zend_string_release($$.key); zval_dtor(&$$.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 	return array_init(array);
252 }
253 
php_json_parser_array_append(php_json_parser * parser,zval * array,zval * zvalue)254 static int php_json_parser_array_append(php_json_parser *parser, zval *array, zval *zvalue)
255 {
256 	zend_hash_next_index_insert(Z_ARRVAL_P(array), zvalue);
257 	return SUCCESS;
258 }
259 
php_json_parser_object_create(php_json_parser * parser,zval * object)260 static int php_json_parser_object_create(php_json_parser *parser, zval *object)
261 {
262 	if (parser->scanner.options & PHP_JSON_OBJECT_AS_ARRAY) {
263 		return array_init(object);
264 	} else {
265 		return object_init(object);
266 	}
267 }
268 
php_json_parser_object_update(php_json_parser * parser,zval * object,zend_string * key,zval * zvalue)269 static int php_json_parser_object_update(php_json_parser *parser, zval *object, zend_string *key, zval *zvalue)
270 {
271 	/* if JSON_OBJECT_AS_ARRAY is set */
272 	if (Z_TYPE_P(object) == IS_ARRAY) {
273 		zend_symtable_update(Z_ARRVAL_P(object), key, zvalue);
274 	} else {
275 		zval zkey;
276 		if (ZSTR_LEN(key) > 0 && ZSTR_VAL(key)[0] == '\0') {
277 			parser->scanner.errcode = PHP_JSON_ERROR_INVALID_PROPERTY_NAME;
278 			zend_string_release(key);
279 			zval_dtor(zvalue);
280 			zval_dtor(object);
281 			return FAILURE;
282 		}
283 		ZVAL_NEW_STR(&zkey, key);
284 		zend_std_write_property(object, &zkey, zvalue, NULL);
285 
286 		if (Z_REFCOUNTED_P(zvalue)) {
287 			Z_DELREF_P(zvalue);
288 		}
289 	}
290 	zend_string_release(key);
291 
292 	return SUCCESS;
293 }
294 
php_json_yylex(union YYSTYPE * value,php_json_parser * parser)295 static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser)
296 {
297 	int token = php_json_scan(&parser->scanner);
298 	value->value = parser->scanner.value;
299 	return token;
300 }
301 
php_json_yyerror(php_json_parser * parser,char const * msg)302 static void php_json_yyerror(php_json_parser *parser, char const *msg)
303 {
304 	if (!parser->scanner.errcode) {
305 		parser->scanner.errcode = PHP_JSON_ERROR_SYNTAX;
306 	}
307 }
308 
php_json_parser_error_code(const php_json_parser * parser)309 PHP_JSON_API php_json_error_code php_json_parser_error_code(const php_json_parser *parser)
310 {
311 	return parser->scanner.errcode;
312 }
313 
314 static const php_json_parser_methods default_parser_methods =
315 {
316 	php_json_parser_array_create,
317 	php_json_parser_array_append,
318 	NULL,
319 	NULL,
320 	php_json_parser_object_create,
321 	php_json_parser_object_update,
322 	NULL,
323 	NULL,
324 };
325 
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)326 PHP_JSON_API void php_json_parser_init_ex(php_json_parser *parser,
327 		zval *return_value,
328 		char *str,
329 		size_t str_len,
330 		int options,
331 		int max_depth,
332 		const php_json_parser_methods *parser_methods)
333 {
334 	memset(parser, 0, sizeof(php_json_parser));
335 	php_json_scanner_init(&parser->scanner, str, str_len, options);
336 	parser->depth = 1;
337 	parser->max_depth = max_depth;
338 	parser->return_value = return_value;
339 	memcpy(&parser->methods, parser_methods, sizeof(php_json_parser_methods));
340 }
341 
php_json_parser_init(php_json_parser * parser,zval * return_value,char * str,size_t str_len,int options,int max_depth)342 PHP_JSON_API void php_json_parser_init(php_json_parser *parser,
343 		zval *return_value,
344 		char *str,
345 		size_t str_len,
346 		int options,
347 		int max_depth)
348 {
349 	php_json_parser_init_ex(
350 			parser,
351 			return_value,
352 			str,
353 			str_len,
354 			options,
355 			max_depth,
356 			&default_parser_methods);
357 }
358 
php_json_parse(php_json_parser * parser)359 PHP_JSON_API int php_json_parse(php_json_parser *parser)
360 {
361 	return php_json_yyparse(parser);
362 }
363