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