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