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