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