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