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