xref: /PHP-7.4/ext/json/json_parser.y (revision 447f07cd)
1 %code top {
2 /*
3   +----------------------------------------------------------------------+
4   | PHP Version 7                                                        |
5   +----------------------------------------------------------------------+
6   | Copyright (c) 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_DEPTH_DEC --parser->depth
36 #define PHP_JSON_DEPTH_INC \
37 	if (parser->max_depth && parser->depth >= parser->max_depth) { \
38 		parser->scanner.errcode = PHP_JSON_ERROR_DEPTH; \
39 		YYERROR; \
40 	} \
41 	++parser->depth
42 
43 }
44 
45 %define api.pure full
46 %define api.prefix {php_json_yy}
47 %lex-param  { php_json_parser *parser  }
48 %parse-param { php_json_parser *parser }
49 
50 %union {
51 	zval value;
52 	struct {
53 		zend_string *key;
54 		zval val;
55 	} pair;
56 }
57 
58 
59 %token <value> PHP_JSON_T_NUL
60 %token <value> PHP_JSON_T_TRUE
61 %token <value> PHP_JSON_T_FALSE
62 %token <value> PHP_JSON_T_INT
63 %token <value> PHP_JSON_T_DOUBLE
64 %token <value> PHP_JSON_T_STRING
65 %token <value> PHP_JSON_T_ESTRING
66 %token PHP_JSON_T_EOI
67 %token PHP_JSON_T_ERROR
68 
69 %type <value> start object key value array
70 %type <value> members member elements element
71 %type <pair> pair
72 
73 %destructor { zval_ptr_dtor_nogc(&$$); } <value>
74 %destructor { zend_string_release_ex($$.key, 0); zval_ptr_dtor_nogc(&$$.val); } <pair>
75 
76 %code {
77 static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser);
78 static void php_json_yyerror(php_json_parser *parser, char const *msg);
79 static int php_json_parser_array_create(php_json_parser *parser, zval *array);
80 static int php_json_parser_object_create(php_json_parser *parser, zval *array);
81 
82 }
83 
84 %% /* Rules */
85 
86 start:
87 		value PHP_JSON_T_EOI
88 			{
89 				ZVAL_COPY_VALUE(&$$, &$1);
90 				ZVAL_COPY_VALUE(parser->return_value, &$1);
91 				YYACCEPT;
92 			}
93 ;
94 
95 object:
96 		'{'
97 			{
98 				PHP_JSON_DEPTH_INC;
99 				if (parser->methods.object_start && FAILURE == parser->methods.object_start(parser)) {
100 					YYERROR;
101 				}
102 			}
103 		members object_end
104 			{
105 				ZVAL_COPY_VALUE(&$$, &$3);
106 				PHP_JSON_DEPTH_DEC;
107 				if (parser->methods.object_end && FAILURE == parser->methods.object_end(parser, &$$)) {
108 					YYERROR;
109 				}
110 			}
111 ;
112 
113 object_end:
114 		'}'
115 	|	']'
116 			{
117 				parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH;
118 				YYERROR;
119 			}
120 ;
121 
122 members:
123 		/* empty */
124 			{
125 				if ((parser->scanner.options & PHP_JSON_OBJECT_AS_ARRAY) && parser->methods.object_create == php_json_parser_object_create) {
126 					ZVAL_EMPTY_ARRAY(&$$);
127 				} else {
128 					parser->methods.object_create(parser, &$$);
129 				}
130 			}
131 	|	member
132 ;
133 
134 member:
135 		pair
136 			{
137 				parser->methods.object_create(parser, &$$);
138 				if (parser->methods.object_update(parser, &$$, $1.key, &$1.val) == FAILURE) {
139 					YYERROR;
140 				}
141 			}
142 	|	member ',' pair
143 			{
144 				if (parser->methods.object_update(parser, &$1, $3.key, &$3.val) == FAILURE) {
145 					YYERROR;
146 				}
147 				ZVAL_COPY_VALUE(&$$, &$1);
148 			}
149 ;
150 
151 pair:
152 		key ':' value
153 			{
154 				$$.key = Z_STR($1);
155 				ZVAL_COPY_VALUE(&$$.val, &$3);
156 			}
157 ;
158 
159 array:
160 		'['
161 			{
162 				PHP_JSON_DEPTH_INC;
163 				if (parser->methods.array_start && FAILURE == parser->methods.array_start(parser)) {
164 					YYERROR;
165 				}
166 			}
167 		elements array_end
168 			{
169 				ZVAL_COPY_VALUE(&$$, &$3);
170 				PHP_JSON_DEPTH_DEC;
171 				if (parser->methods.array_end && FAILURE == parser->methods.array_end(parser, &$$)) {
172 					YYERROR;
173 				}
174 			}
175 ;
176 
177 array_end:
178 		']'
179 	|	'}'
180 			{
181 				parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH;
182 				YYERROR;
183 			}
184 ;
185 
186 elements:
187 		/* empty */
188 			{
189 				if (parser->methods.array_create == php_json_parser_array_create) {
190 					ZVAL_EMPTY_ARRAY(&$$);
191 				} else {
192 					parser->methods.array_create(parser, &$$);
193 				}
194 			}
195 	|	element
196 ;
197 
198 element:
199 		value
200 			{
201 				parser->methods.array_create(parser, &$$);
202 				parser->methods.array_append(parser, &$$, &$1);
203 			}
204 	|	element ',' value
205 			{
206 				parser->methods.array_append(parser, &$1, &$3);
207 				ZVAL_COPY_VALUE(&$$, &$1);
208 			}
209 ;
210 
211 key:
212 		PHP_JSON_T_STRING
213 	|	PHP_JSON_T_ESTRING
214 ;
215 
216 value:
217 		object
218 	|	array
219 	|	PHP_JSON_T_STRING
220 	|	PHP_JSON_T_ESTRING
221 	|	PHP_JSON_T_INT
222 	|	PHP_JSON_T_DOUBLE
223 	|	PHP_JSON_T_NUL
224 	|	PHP_JSON_T_TRUE
225 	|	PHP_JSON_T_FALSE
226 ;
227 
228 %% /* Functions */
229 
230 static int php_json_parser_array_create(php_json_parser *parser, zval *array)
231 {
232 	array_init(array);
233 	return SUCCESS;
234 }
235 
php_json_parser_array_append(php_json_parser * parser,zval * array,zval * zvalue)236 static int php_json_parser_array_append(php_json_parser *parser, zval *array, zval *zvalue)
237 {
238 	zend_hash_next_index_insert(Z_ARRVAL_P(array), zvalue);
239 	return SUCCESS;
240 }
241 
php_json_parser_object_create(php_json_parser * parser,zval * object)242 static int php_json_parser_object_create(php_json_parser *parser, zval *object)
243 {
244 	if (parser->scanner.options & PHP_JSON_OBJECT_AS_ARRAY) {
245 		array_init(object);
246 		return SUCCESS;
247 	} else {
248 		return object_init(object);
249 	}
250 }
251 
php_json_parser_object_update(php_json_parser * parser,zval * object,zend_string * key,zval * zvalue)252 static int php_json_parser_object_update(php_json_parser *parser, zval *object, zend_string *key, zval *zvalue)
253 {
254 	/* if JSON_OBJECT_AS_ARRAY is set */
255 	if (Z_TYPE_P(object) == IS_ARRAY) {
256 		zend_symtable_update(Z_ARRVAL_P(object), key, zvalue);
257 	} else {
258 		zval zkey;
259 		if (ZSTR_LEN(key) > 0 && ZSTR_VAL(key)[0] == '\0') {
260 			parser->scanner.errcode = PHP_JSON_ERROR_INVALID_PROPERTY_NAME;
261 			zend_string_release_ex(key, 0);
262 			zval_ptr_dtor_nogc(zvalue);
263 			zval_ptr_dtor_nogc(object);
264 			return FAILURE;
265 		}
266 		ZVAL_NEW_STR(&zkey, key);
267 		zend_std_write_property(object, &zkey, zvalue, NULL);
268 		Z_TRY_DELREF_P(zvalue);
269 	}
270 	zend_string_release_ex(key, 0);
271 
272 	return SUCCESS;
273 }
274 
php_json_yylex(union YYSTYPE * value,php_json_parser * parser)275 static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser)
276 {
277 	int token = php_json_scan(&parser->scanner);
278 	value->value = parser->scanner.value;
279 	return token;
280 }
281 
php_json_yyerror(php_json_parser * parser,char const * msg)282 static void php_json_yyerror(php_json_parser *parser, char const *msg)
283 {
284 	if (!parser->scanner.errcode) {
285 		parser->scanner.errcode = PHP_JSON_ERROR_SYNTAX;
286 	}
287 }
288 
php_json_parser_error_code(const php_json_parser * parser)289 PHP_JSON_API php_json_error_code php_json_parser_error_code(const php_json_parser *parser)
290 {
291 	return parser->scanner.errcode;
292 }
293 
294 static const php_json_parser_methods default_parser_methods =
295 {
296 	php_json_parser_array_create,
297 	php_json_parser_array_append,
298 	NULL,
299 	NULL,
300 	php_json_parser_object_create,
301 	php_json_parser_object_update,
302 	NULL,
303 	NULL,
304 };
305 
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)306 PHP_JSON_API void php_json_parser_init_ex(php_json_parser *parser,
307 		zval *return_value,
308 		char *str,
309 		size_t str_len,
310 		int options,
311 		int max_depth,
312 		const php_json_parser_methods *parser_methods)
313 {
314 	memset(parser, 0, sizeof(php_json_parser));
315 	php_json_scanner_init(&parser->scanner, str, str_len, options);
316 	parser->depth = 1;
317 	parser->max_depth = max_depth;
318 	parser->return_value = return_value;
319 	memcpy(&parser->methods, parser_methods, sizeof(php_json_parser_methods));
320 }
321 
php_json_parser_init(php_json_parser * parser,zval * return_value,char * str,size_t str_len,int options,int max_depth)322 PHP_JSON_API void php_json_parser_init(php_json_parser *parser,
323 		zval *return_value,
324 		char *str,
325 		size_t str_len,
326 		int options,
327 		int max_depth)
328 {
329 	php_json_parser_init_ex(
330 			parser,
331 			return_value,
332 			str,
333 			str_len,
334 			options,
335 			max_depth,
336 			&default_parser_methods);
337 }
338 
php_json_parse(php_json_parser * parser)339 PHP_JSON_API int php_json_parse(php_json_parser *parser)
340 {
341 	return php_json_yyparse(parser);
342 }
343