/src/h2o/deps/yaml/src/loader.c
Line | Count | Source (jump to first uncovered line) |
1 | | |
2 | | #include "yaml_private.h" |
3 | | |
4 | | /* |
5 | | * API functions. |
6 | | */ |
7 | | |
8 | | YAML_DECLARE(int) |
9 | | yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document); |
10 | | |
11 | | /* |
12 | | * Error handling. |
13 | | */ |
14 | | |
15 | | static int |
16 | | yaml_parser_set_composer_error(yaml_parser_t *parser, |
17 | | const char *problem, yaml_mark_t problem_mark); |
18 | | |
19 | | static int |
20 | | yaml_parser_set_composer_error_context(yaml_parser_t *parser, |
21 | | const char *context, yaml_mark_t context_mark, |
22 | | const char *problem, yaml_mark_t problem_mark); |
23 | | |
24 | | |
25 | | /* |
26 | | * Alias handling. |
27 | | */ |
28 | | |
29 | | static int |
30 | | yaml_parser_register_anchor(yaml_parser_t *parser, |
31 | | int index, yaml_char_t *anchor); |
32 | | |
33 | | /* |
34 | | * Clean up functions. |
35 | | */ |
36 | | |
37 | | static void |
38 | | yaml_parser_delete_aliases(yaml_parser_t *parser); |
39 | | |
40 | | /* |
41 | | * Document loading context. |
42 | | */ |
43 | | struct loader_ctx { |
44 | | int *start; |
45 | | int *end; |
46 | | int *top; |
47 | | }; |
48 | | |
49 | | /* |
50 | | * Composer functions. |
51 | | */ |
52 | | static int |
53 | | yaml_parser_load_nodes(yaml_parser_t *parser, struct loader_ctx *ctx); |
54 | | |
55 | | static int |
56 | | yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *event); |
57 | | |
58 | | static int |
59 | | yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *event, |
60 | | struct loader_ctx *ctx); |
61 | | |
62 | | static int |
63 | | yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *event, |
64 | | struct loader_ctx *ctx); |
65 | | |
66 | | static int |
67 | | yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *event, |
68 | | struct loader_ctx *ctx); |
69 | | |
70 | | static int |
71 | | yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *event, |
72 | | struct loader_ctx *ctx); |
73 | | |
74 | | static int |
75 | | yaml_parser_load_sequence_end(yaml_parser_t *parser, yaml_event_t *event, |
76 | | struct loader_ctx *ctx); |
77 | | |
78 | | static int |
79 | | yaml_parser_load_mapping_end(yaml_parser_t *parser, yaml_event_t *event, |
80 | | struct loader_ctx *ctx); |
81 | | |
82 | | /* |
83 | | * Load the next document of the stream. |
84 | | */ |
85 | | |
86 | | YAML_DECLARE(int) |
87 | | yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document) |
88 | 0 | { |
89 | 0 | yaml_event_t event; |
90 | |
|
91 | 0 | assert(parser); /* Non-NULL parser object is expected. */ |
92 | 0 | assert(document); /* Non-NULL document object is expected. */ |
93 | | |
94 | 0 | memset(document, 0, sizeof(yaml_document_t)); |
95 | 0 | if (!STACK_INIT(parser, document->nodes, yaml_node_t*)) |
96 | 0 | goto error; |
97 | | |
98 | 0 | if (!parser->stream_start_produced) { |
99 | 0 | if (!yaml_parser_parse(parser, &event)) goto error; |
100 | 0 | assert(event.type == YAML_STREAM_START_EVENT); |
101 | | /* STREAM-START is expected. */ |
102 | 0 | } |
103 | | |
104 | 0 | if (parser->stream_end_produced) { |
105 | 0 | return 1; |
106 | 0 | } |
107 | | |
108 | 0 | if (!yaml_parser_parse(parser, &event)) goto error; |
109 | 0 | if (event.type == YAML_STREAM_END_EVENT) { |
110 | 0 | return 1; |
111 | 0 | } |
112 | | |
113 | 0 | if (!STACK_INIT(parser, parser->aliases, yaml_alias_data_t*)) |
114 | 0 | goto error; |
115 | | |
116 | 0 | parser->document = document; |
117 | |
|
118 | 0 | if (!yaml_parser_load_document(parser, &event)) goto error; |
119 | | |
120 | 0 | yaml_parser_delete_aliases(parser); |
121 | 0 | parser->document = NULL; |
122 | |
|
123 | 0 | return 1; |
124 | | |
125 | 0 | error: |
126 | |
|
127 | 0 | yaml_parser_delete_aliases(parser); |
128 | 0 | yaml_document_delete(document); |
129 | 0 | parser->document = NULL; |
130 | |
|
131 | 0 | return 0; |
132 | 0 | } |
133 | | |
134 | | /* |
135 | | * Set composer error. |
136 | | */ |
137 | | |
138 | | static int |
139 | | yaml_parser_set_composer_error(yaml_parser_t *parser, |
140 | | const char *problem, yaml_mark_t problem_mark) |
141 | 0 | { |
142 | 0 | parser->error = YAML_COMPOSER_ERROR; |
143 | 0 | parser->problem = problem; |
144 | 0 | parser->problem_mark = problem_mark; |
145 | |
|
146 | 0 | return 0; |
147 | 0 | } |
148 | | |
149 | | /* |
150 | | * Set composer error with context. |
151 | | */ |
152 | | |
153 | | static int |
154 | | yaml_parser_set_composer_error_context(yaml_parser_t *parser, |
155 | | const char *context, yaml_mark_t context_mark, |
156 | | const char *problem, yaml_mark_t problem_mark) |
157 | 0 | { |
158 | 0 | parser->error = YAML_COMPOSER_ERROR; |
159 | 0 | parser->context = context; |
160 | 0 | parser->context_mark = context_mark; |
161 | 0 | parser->problem = problem; |
162 | 0 | parser->problem_mark = problem_mark; |
163 | |
|
164 | 0 | return 0; |
165 | 0 | } |
166 | | |
167 | | /* |
168 | | * Delete the stack of aliases. |
169 | | */ |
170 | | |
171 | | static void |
172 | | yaml_parser_delete_aliases(yaml_parser_t *parser) |
173 | 0 | { |
174 | 0 | while (!STACK_EMPTY(parser, parser->aliases)) { |
175 | 0 | yaml_free(POP(parser, parser->aliases).anchor); |
176 | 0 | } |
177 | 0 | STACK_DEL(parser, parser->aliases); |
178 | 0 | } |
179 | | |
180 | | /* |
181 | | * Compose a document object. |
182 | | */ |
183 | | |
184 | | static int |
185 | | yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *event) |
186 | 0 | { |
187 | 0 | struct loader_ctx ctx = { NULL, NULL, NULL }; |
188 | |
|
189 | 0 | assert(event->type == YAML_DOCUMENT_START_EVENT); |
190 | | /* DOCUMENT-START is expected. */ |
191 | | |
192 | 0 | parser->document->version_directive |
193 | 0 | = event->data.document_start.version_directive; |
194 | 0 | parser->document->tag_directives.start |
195 | 0 | = event->data.document_start.tag_directives.start; |
196 | 0 | parser->document->tag_directives.end |
197 | 0 | = event->data.document_start.tag_directives.end; |
198 | 0 | parser->document->start_implicit |
199 | 0 | = event->data.document_start.implicit; |
200 | 0 | parser->document->start_mark = event->start_mark; |
201 | |
|
202 | 0 | if (!STACK_INIT(parser, ctx, int*)) return 0; |
203 | 0 | if (!yaml_parser_load_nodes(parser, &ctx)) { |
204 | 0 | STACK_DEL(parser, ctx); |
205 | 0 | return 0; |
206 | 0 | } |
207 | 0 | STACK_DEL(parser, ctx); |
208 | |
|
209 | 0 | return 1; |
210 | 0 | } |
211 | | |
212 | | /* |
213 | | * Compose a node tree. |
214 | | */ |
215 | | |
216 | | static int |
217 | | yaml_parser_load_nodes(yaml_parser_t *parser, struct loader_ctx *ctx) |
218 | 0 | { |
219 | 0 | yaml_event_t event; |
220 | |
|
221 | 0 | do { |
222 | 0 | if (!yaml_parser_parse(parser, &event)) return 0; |
223 | | |
224 | 0 | switch (event.type) { |
225 | 0 | case YAML_ALIAS_EVENT: |
226 | 0 | if (!yaml_parser_load_alias(parser, &event, ctx)) return 0; |
227 | 0 | break; |
228 | 0 | case YAML_SCALAR_EVENT: |
229 | 0 | if (!yaml_parser_load_scalar(parser, &event, ctx)) return 0; |
230 | 0 | break; |
231 | 0 | case YAML_SEQUENCE_START_EVENT: |
232 | 0 | if (!yaml_parser_load_sequence(parser, &event, ctx)) return 0; |
233 | 0 | break; |
234 | 0 | case YAML_SEQUENCE_END_EVENT: |
235 | 0 | if (!yaml_parser_load_sequence_end(parser, &event, ctx)) |
236 | 0 | return 0; |
237 | 0 | break; |
238 | 0 | case YAML_MAPPING_START_EVENT: |
239 | 0 | if (!yaml_parser_load_mapping(parser, &event, ctx)) return 0; |
240 | 0 | break; |
241 | 0 | case YAML_MAPPING_END_EVENT: |
242 | 0 | if (!yaml_parser_load_mapping_end(parser, &event, ctx)) |
243 | 0 | return 0; |
244 | 0 | break; |
245 | 0 | default: |
246 | 0 | assert(0); /* Could not happen. */ |
247 | 0 | return 0; |
248 | 0 | case YAML_DOCUMENT_END_EVENT: |
249 | 0 | break; |
250 | 0 | } |
251 | 0 | } while (event.type != YAML_DOCUMENT_END_EVENT); |
252 | | |
253 | 0 | parser->document->end_implicit = event.data.document_end.implicit; |
254 | 0 | parser->document->end_mark = event.end_mark; |
255 | |
|
256 | 0 | return 1; |
257 | 0 | } |
258 | | |
259 | | /* |
260 | | * Add an anchor. |
261 | | */ |
262 | | |
263 | | static int |
264 | | yaml_parser_register_anchor(yaml_parser_t *parser, |
265 | | int index, yaml_char_t *anchor) |
266 | 0 | { |
267 | 0 | yaml_alias_data_t data; |
268 | 0 | yaml_alias_data_t *alias_data; |
269 | |
|
270 | 0 | if (!anchor) return 1; |
271 | | |
272 | 0 | data.anchor = anchor; |
273 | 0 | data.index = index; |
274 | 0 | data.mark = parser->document->nodes.start[index-1].start_mark; |
275 | |
|
276 | 0 | for (alias_data = parser->aliases.start; |
277 | 0 | alias_data != parser->aliases.top; alias_data ++) { |
278 | 0 | if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) { |
279 | 0 | yaml_free(anchor); |
280 | 0 | return yaml_parser_set_composer_error_context(parser, |
281 | 0 | "found duplicate anchor; first occurrence", |
282 | 0 | alias_data->mark, "second occurrence", data.mark); |
283 | 0 | } |
284 | 0 | } |
285 | | |
286 | 0 | if (!PUSH(parser, parser->aliases, data)) { |
287 | 0 | yaml_free(anchor); |
288 | 0 | return 0; |
289 | 0 | } |
290 | | |
291 | 0 | return 1; |
292 | 0 | } |
293 | | |
294 | | /* |
295 | | * Compose node into its parent in the stree. |
296 | | */ |
297 | | |
298 | | static int |
299 | | yaml_parser_load_node_add(yaml_parser_t *parser, struct loader_ctx *ctx, |
300 | | int index) |
301 | 0 | { |
302 | 0 | struct yaml_node_s *parent; |
303 | 0 | int parent_index; |
304 | |
|
305 | 0 | if (STACK_EMPTY(parser, *ctx)) { |
306 | | /* This is the root node, there's no tree to add it to. */ |
307 | 0 | return 1; |
308 | 0 | } |
309 | | |
310 | 0 | parent_index = *((*ctx).top - 1); |
311 | 0 | parent = &parser->document->nodes.start[parent_index-1]; |
312 | |
|
313 | 0 | switch (parent->type) { |
314 | 0 | case YAML_SEQUENCE_NODE: |
315 | 0 | if (!STACK_LIMIT(parser, parent->data.sequence.items, INT_MAX-1)) |
316 | 0 | return 0; |
317 | 0 | if (!PUSH(parser, parent->data.sequence.items, index)) |
318 | 0 | return 0; |
319 | 0 | break; |
320 | 0 | case YAML_MAPPING_NODE: { |
321 | 0 | yaml_node_pair_t pair; |
322 | 0 | if (!STACK_EMPTY(parser, parent->data.mapping.pairs)) { |
323 | 0 | yaml_node_pair_t *p = parent->data.mapping.pairs.top - 1; |
324 | 0 | if (p->key != 0 && p->value == 0) { |
325 | 0 | p->value = index; |
326 | 0 | break; |
327 | 0 | } |
328 | 0 | } |
329 | | |
330 | 0 | pair.key = index; |
331 | 0 | pair.value = 0; |
332 | 0 | if (!STACK_LIMIT(parser, parent->data.mapping.pairs, INT_MAX-1)) |
333 | 0 | return 0; |
334 | 0 | if (!PUSH(parser, parent->data.mapping.pairs, pair)) |
335 | 0 | return 0; |
336 | | |
337 | 0 | break; |
338 | 0 | } |
339 | 0 | default: |
340 | 0 | assert(0); /* Could not happen. */ |
341 | 0 | return 0; |
342 | 0 | } |
343 | 0 | return 1; |
344 | 0 | } |
345 | | |
346 | | /* |
347 | | * Compose a node corresponding to an alias. |
348 | | */ |
349 | | |
350 | | static int |
351 | | yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *event, |
352 | | struct loader_ctx *ctx) |
353 | 0 | { |
354 | 0 | yaml_char_t *anchor = event->data.alias.anchor; |
355 | 0 | yaml_alias_data_t *alias_data; |
356 | |
|
357 | 0 | for (alias_data = parser->aliases.start; |
358 | 0 | alias_data != parser->aliases.top; alias_data ++) { |
359 | 0 | if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) { |
360 | 0 | yaml_free(anchor); |
361 | 0 | return yaml_parser_load_node_add(parser, ctx, alias_data->index); |
362 | 0 | } |
363 | 0 | } |
364 | | |
365 | 0 | yaml_free(anchor); |
366 | 0 | return yaml_parser_set_composer_error(parser, "found undefined alias", |
367 | 0 | event->start_mark); |
368 | 0 | } |
369 | | |
370 | | /* |
371 | | * Compose a scalar node. |
372 | | */ |
373 | | |
374 | | static int |
375 | | yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *event, |
376 | | struct loader_ctx *ctx) |
377 | 0 | { |
378 | 0 | yaml_node_t node; |
379 | 0 | int index; |
380 | 0 | yaml_char_t *tag = event->data.scalar.tag; |
381 | |
|
382 | 0 | if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error; |
383 | | |
384 | 0 | if (!tag || strcmp((char *)tag, "!") == 0) { |
385 | 0 | yaml_free(tag); |
386 | 0 | tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG); |
387 | 0 | if (!tag) goto error; |
388 | 0 | } |
389 | | |
390 | 0 | SCALAR_NODE_INIT(node, tag, event->data.scalar.value, |
391 | 0 | event->data.scalar.length, event->data.scalar.style, |
392 | 0 | event->start_mark, event->end_mark); |
393 | |
|
394 | 0 | if (!PUSH(parser, parser->document->nodes, node)) goto error; |
395 | | |
396 | 0 | index = parser->document->nodes.top - parser->document->nodes.start; |
397 | |
|
398 | 0 | if (!yaml_parser_register_anchor(parser, index, |
399 | 0 | event->data.scalar.anchor)) return 0; |
400 | | |
401 | 0 | return yaml_parser_load_node_add(parser, ctx, index); |
402 | | |
403 | 0 | error: |
404 | 0 | yaml_free(tag); |
405 | 0 | yaml_free(event->data.scalar.anchor); |
406 | 0 | yaml_free(event->data.scalar.value); |
407 | 0 | return 0; |
408 | 0 | } |
409 | | |
410 | | /* |
411 | | * Compose a sequence node. |
412 | | */ |
413 | | |
414 | | static int |
415 | | yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *event, |
416 | | struct loader_ctx *ctx) |
417 | 0 | { |
418 | 0 | yaml_node_t node; |
419 | 0 | struct { |
420 | 0 | yaml_node_item_t *start; |
421 | 0 | yaml_node_item_t *end; |
422 | 0 | yaml_node_item_t *top; |
423 | 0 | } items = { NULL, NULL, NULL }; |
424 | 0 | int index; |
425 | 0 | yaml_char_t *tag = event->data.sequence_start.tag; |
426 | |
|
427 | 0 | if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error; |
428 | | |
429 | 0 | if (!tag || strcmp((char *)tag, "!") == 0) { |
430 | 0 | yaml_free(tag); |
431 | 0 | tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG); |
432 | 0 | if (!tag) goto error; |
433 | 0 | } |
434 | | |
435 | 0 | if (!STACK_INIT(parser, items, yaml_node_item_t*)) goto error; |
436 | | |
437 | 0 | SEQUENCE_NODE_INIT(node, tag, items.start, items.end, |
438 | 0 | event->data.sequence_start.style, |
439 | 0 | event->start_mark, event->end_mark); |
440 | |
|
441 | 0 | if (!PUSH(parser, parser->document->nodes, node)) goto error; |
442 | | |
443 | 0 | index = parser->document->nodes.top - parser->document->nodes.start; |
444 | |
|
445 | 0 | if (!yaml_parser_register_anchor(parser, index, |
446 | 0 | event->data.sequence_start.anchor)) return 0; |
447 | | |
448 | 0 | if (!yaml_parser_load_node_add(parser, ctx, index)) return 0; |
449 | | |
450 | 0 | if (!STACK_LIMIT(parser, *ctx, INT_MAX-1)) return 0; |
451 | 0 | if (!PUSH(parser, *ctx, index)) return 0; |
452 | | |
453 | 0 | return 1; |
454 | | |
455 | 0 | error: |
456 | 0 | yaml_free(tag); |
457 | 0 | yaml_free(event->data.sequence_start.anchor); |
458 | 0 | return 0; |
459 | 0 | } |
460 | | |
461 | | static int |
462 | | yaml_parser_load_sequence_end(yaml_parser_t *parser, yaml_event_t *event, |
463 | | struct loader_ctx *ctx) |
464 | 0 | { |
465 | 0 | int index; |
466 | |
|
467 | 0 | assert(((*ctx).top - (*ctx).start) > 0); |
468 | | |
469 | 0 | index = *((*ctx).top - 1); |
470 | 0 | assert(parser->document->nodes.start[index-1].type == YAML_SEQUENCE_NODE); |
471 | 0 | parser->document->nodes.start[index-1].end_mark = event->end_mark; |
472 | |
|
473 | 0 | (void)POP(parser, *ctx); |
474 | |
|
475 | 0 | return 1; |
476 | 0 | } |
477 | | |
478 | | /* |
479 | | * Compose a mapping node. |
480 | | */ |
481 | | |
482 | | static int |
483 | | yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *event, |
484 | | struct loader_ctx *ctx) |
485 | 0 | { |
486 | 0 | yaml_node_t node; |
487 | 0 | struct { |
488 | 0 | yaml_node_pair_t *start; |
489 | 0 | yaml_node_pair_t *end; |
490 | 0 | yaml_node_pair_t *top; |
491 | 0 | } pairs = { NULL, NULL, NULL }; |
492 | 0 | int index; |
493 | 0 | yaml_char_t *tag = event->data.mapping_start.tag; |
494 | |
|
495 | 0 | if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error; |
496 | | |
497 | 0 | if (!tag || strcmp((char *)tag, "!") == 0) { |
498 | 0 | yaml_free(tag); |
499 | 0 | tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG); |
500 | 0 | if (!tag) goto error; |
501 | 0 | } |
502 | | |
503 | 0 | if (!STACK_INIT(parser, pairs, yaml_node_pair_t*)) goto error; |
504 | | |
505 | 0 | MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end, |
506 | 0 | event->data.mapping_start.style, |
507 | 0 | event->start_mark, event->end_mark); |
508 | |
|
509 | 0 | if (!PUSH(parser, parser->document->nodes, node)) goto error; |
510 | | |
511 | 0 | index = parser->document->nodes.top - parser->document->nodes.start; |
512 | |
|
513 | 0 | if (!yaml_parser_register_anchor(parser, index, |
514 | 0 | event->data.mapping_start.anchor)) return 0; |
515 | | |
516 | 0 | if (!yaml_parser_load_node_add(parser, ctx, index)) return 0; |
517 | | |
518 | 0 | if (!STACK_LIMIT(parser, *ctx, INT_MAX-1)) return 0; |
519 | 0 | if (!PUSH(parser, *ctx, index)) return 0; |
520 | | |
521 | 0 | return 1; |
522 | | |
523 | 0 | error: |
524 | 0 | yaml_free(tag); |
525 | 0 | yaml_free(event->data.mapping_start.anchor); |
526 | 0 | return 0; |
527 | 0 | } |
528 | | |
529 | | static int |
530 | | yaml_parser_load_mapping_end(yaml_parser_t *parser, yaml_event_t *event, |
531 | | struct loader_ctx *ctx) |
532 | 0 | { |
533 | 0 | int index; |
534 | |
|
535 | 0 | assert(((*ctx).top - (*ctx).start) > 0); |
536 | | |
537 | 0 | index = *((*ctx).top - 1); |
538 | 0 | assert(parser->document->nodes.start[index-1].type == YAML_MAPPING_NODE); |
539 | 0 | parser->document->nodes.start[index-1].end_mark = event->end_mark; |
540 | |
|
541 | 0 | (void)POP(parser, *ctx); |
542 | |
|
543 | 0 | return 1; |
544 | 0 | } |