Skip to main content

unsafe_libyaml/
loader.rs

1use core::{
2    mem::{MaybeUninit, size_of},
3    ptr::{self, addr_of_mut},
4};
5
6use crate::{
7    PointerExt, YAML_ALIAS_EVENT, YAML_COMPOSER_ERROR, YAML_DOCUMENT_END_EVENT, YAML_DOCUMENT_START_EVENT,
8    YAML_MAPPING_END_EVENT, YAML_MAPPING_NODE, YAML_MAPPING_START_EVENT, YAML_MEMORY_ERROR, YAML_SCALAR_EVENT,
9    YAML_SCALAR_NODE, YAML_SEQUENCE_END_EVENT, YAML_SEQUENCE_NODE, YAML_SEQUENCE_START_EVENT, YAML_STREAM_END_EVENT,
10    YAML_STREAM_START_EVENT,
11    api::{yaml_free, yaml_malloc, yaml_stack_extend, yaml_strdup},
12    externs::{memset, strcmp},
13    libc,
14    success::{FAIL, OK, Success},
15    yaml::yaml_char_t,
16    yaml_alias_data_t, yaml_document_delete, yaml_document_t, yaml_event_t, yaml_mark_t, yaml_node_item_t,
17    yaml_node_pair_t, yaml_node_t, yaml_parser_parse, yaml_parser_t,
18};
19
20#[repr(C)]
21struct loader_ctx {
22    start: *mut libc::c_int,
23    end: *mut libc::c_int,
24    top: *mut libc::c_int,
25}
26
27/// Parse the input stream and produce the next YAML document.
28///
29/// Call this function subsequently to produce a sequence of documents
30/// constituting the input stream.
31///
32/// If the produced document has no root node, it means that the document end
33/// has been reached.
34///
35/// An application is responsible for freeing any data associated with the
36/// produced document object using the yaml_document_delete() function.
37///
38/// An application must not alternate the calls of yaml_parser_load() with the
39/// calls of yaml_parser_scan() or yaml_parser_parse(). Doing this will break
40/// the parser.
41pub unsafe fn yaml_parser_load(parser: *mut yaml_parser_t, document: *mut yaml_document_t) -> Success {
42    let current_block: u64;
43    let mut event = MaybeUninit::<yaml_event_t>::uninit();
44    let event = event.as_mut_ptr();
45    __assert!(!parser.is_null());
46    __assert!(!document.is_null());
47    memset(document as *mut libc::c_void, 0, size_of::<yaml_document_t>() as libc::c_ulong);
48    STACK_INIT!((*document).nodes, yaml_node_t);
49    if !(*parser).stream_start_produced {
50        if yaml_parser_parse(parser, event).fail {
51            current_block = 6234624449317607669;
52        } else {
53            __assert!((*event).type_ == YAML_STREAM_START_EVENT);
54            current_block = 7815301370352969686;
55        }
56    } else {
57        current_block = 7815301370352969686;
58    }
59    if current_block != 6234624449317607669 {
60        if (*parser).stream_end_produced {
61            return OK;
62        }
63        if yaml_parser_parse(parser, event).ok {
64            if (*event).type_ == YAML_STREAM_END_EVENT {
65                return OK;
66            }
67            STACK_INIT!((*parser).aliases, yaml_alias_data_t);
68            let fresh6 = addr_of_mut!((*parser).document);
69            *fresh6 = document;
70            if yaml_parser_load_document(parser, event).ok {
71                yaml_parser_delete_aliases(parser);
72                let fresh7 = addr_of_mut!((*parser).document);
73                *fresh7 = ptr::null_mut::<yaml_document_t>();
74                return OK;
75            }
76        }
77    }
78    yaml_parser_delete_aliases(parser);
79    yaml_document_delete(document);
80    let fresh8 = addr_of_mut!((*parser).document);
81    *fresh8 = ptr::null_mut::<yaml_document_t>();
82    FAIL
83}
84
85unsafe fn yaml_parser_set_composer_error(
86    parser: *mut yaml_parser_t,
87    problem: *const libc::c_char,
88    problem_mark: yaml_mark_t,
89) -> Success {
90    (*parser).error = YAML_COMPOSER_ERROR;
91    let fresh9 = addr_of_mut!((*parser).problem);
92    *fresh9 = problem;
93    (*parser).problem_mark = problem_mark;
94    FAIL
95}
96
97unsafe fn yaml_parser_set_composer_error_context(
98    parser: *mut yaml_parser_t,
99    context: *const libc::c_char,
100    context_mark: yaml_mark_t,
101    problem: *const libc::c_char,
102    problem_mark: yaml_mark_t,
103) -> Success {
104    (*parser).error = YAML_COMPOSER_ERROR;
105    let fresh10 = addr_of_mut!((*parser).context);
106    *fresh10 = context;
107    (*parser).context_mark = context_mark;
108    let fresh11 = addr_of_mut!((*parser).problem);
109    *fresh11 = problem;
110    (*parser).problem_mark = problem_mark;
111    FAIL
112}
113
114unsafe fn yaml_parser_delete_aliases(parser: *mut yaml_parser_t) {
115    while !STACK_EMPTY!((*parser).aliases) {
116        yaml_free(POP!((*parser).aliases).anchor as *mut libc::c_void);
117    }
118    STACK_DEL!((*parser).aliases);
119}
120
121unsafe fn yaml_parser_load_document(parser: *mut yaml_parser_t, event: *mut yaml_event_t) -> Success {
122    let mut ctx = loader_ctx {
123        start: ptr::null_mut::<libc::c_int>(),
124        end: ptr::null_mut::<libc::c_int>(),
125        top: ptr::null_mut::<libc::c_int>(),
126    };
127    __assert!((*event).type_ == YAML_DOCUMENT_START_EVENT);
128    let fresh16 = addr_of_mut!((*(*parser).document).version_directive);
129    *fresh16 = (*event).data.document_start.version_directive;
130    let fresh17 = addr_of_mut!((*(*parser).document).tag_directives.start);
131    *fresh17 = (*event).data.document_start.tag_directives.start;
132    let fresh18 = addr_of_mut!((*(*parser).document).tag_directives.end);
133    *fresh18 = (*event).data.document_start.tag_directives.end;
134    (*(*parser).document).start_implicit = (*event).data.document_start.implicit;
135    (*(*parser).document).start_mark = (*event).start_mark;
136    STACK_INIT!(ctx, libc::c_int);
137    if yaml_parser_load_nodes(parser, addr_of_mut!(ctx)).fail {
138        STACK_DEL!(ctx);
139        return FAIL;
140    }
141    STACK_DEL!(ctx);
142    OK
143}
144
145unsafe fn yaml_parser_load_nodes(parser: *mut yaml_parser_t, ctx: *mut loader_ctx) -> Success {
146    let mut event = MaybeUninit::<yaml_event_t>::uninit();
147    let event = event.as_mut_ptr();
148    loop {
149        if yaml_parser_parse(parser, event).fail {
150            return FAIL;
151        }
152        match (*event).type_ {
153            YAML_ALIAS_EVENT => {
154                if yaml_parser_load_alias(parser, event, ctx).fail {
155                    return FAIL;
156                }
157            }
158            YAML_SCALAR_EVENT => {
159                if yaml_parser_load_scalar(parser, event, ctx).fail {
160                    return FAIL;
161                }
162            }
163            YAML_SEQUENCE_START_EVENT => {
164                if yaml_parser_load_sequence(parser, event, ctx).fail {
165                    return FAIL;
166                }
167            }
168            YAML_SEQUENCE_END_EVENT => {
169                if yaml_parser_load_sequence_end(parser, event, ctx).fail {
170                    return FAIL;
171                }
172            }
173            YAML_MAPPING_START_EVENT => {
174                if yaml_parser_load_mapping(parser, event, ctx).fail {
175                    return FAIL;
176                }
177            }
178            YAML_MAPPING_END_EVENT => {
179                if yaml_parser_load_mapping_end(parser, event, ctx).fail {
180                    return FAIL;
181                }
182            }
183            YAML_DOCUMENT_END_EVENT => {}
184            _ => {
185                __assert!(false);
186            }
187        }
188        if (*event).type_ == YAML_DOCUMENT_END_EVENT {
189            break;
190        }
191    }
192    (*(*parser).document).end_implicit = (*event).data.document_end.implicit;
193    (*(*parser).document).end_mark = (*event).end_mark;
194    OK
195}
196
197unsafe fn yaml_parser_register_anchor(
198    parser: *mut yaml_parser_t,
199    index: libc::c_int,
200    anchor: *mut yaml_char_t,
201) -> Success {
202    let mut data = MaybeUninit::<yaml_alias_data_t>::uninit();
203    let data = data.as_mut_ptr();
204    let mut alias_data: *mut yaml_alias_data_t;
205    if anchor.is_null() {
206        return OK;
207    }
208    (*data).anchor = anchor;
209    (*data).index = index;
210    (*data).mark = (*(*(*parser).document).nodes.start.wrapping_offset((index - 1) as isize)).start_mark;
211    alias_data = (*parser).aliases.start;
212    while alias_data != (*parser).aliases.top {
213        if strcmp((*alias_data).anchor as *mut libc::c_char, anchor as *mut libc::c_char) == 0 {
214            yaml_free(anchor as *mut libc::c_void);
215            return yaml_parser_set_composer_error_context(
216                parser,
217                b"found duplicate anchor; first occurrence\0" as *const u8 as *const libc::c_char,
218                (*alias_data).mark,
219                b"second occurrence\0" as *const u8 as *const libc::c_char,
220                (*data).mark,
221            );
222        }
223        alias_data = alias_data.wrapping_offset(1);
224    }
225    PUSH!((*parser).aliases, *data);
226    OK
227}
228
229unsafe fn yaml_parser_load_node_add(parser: *mut yaml_parser_t, ctx: *mut loader_ctx, index: libc::c_int) -> Success {
230    if STACK_EMPTY!(*ctx) {
231        return OK;
232    }
233    let parent_index: libc::c_int = *(*ctx).top.wrapping_offset(-1_isize);
234    let parent: *mut yaml_node_t =
235        addr_of_mut!(*((*(*parser).document).nodes.start).wrapping_offset((parent_index - 1) as isize));
236    let current_block_17: u64;
237    match (*parent).type_ {
238        YAML_SEQUENCE_NODE => {
239            if STACK_LIMIT!(parser, (*parent).data.sequence.items).fail {
240                return FAIL;
241            }
242            PUSH!((*parent).data.sequence.items, index);
243        }
244        YAML_MAPPING_NODE => {
245            let mut pair = MaybeUninit::<yaml_node_pair_t>::uninit();
246            let pair = pair.as_mut_ptr();
247            if !STACK_EMPTY!((*parent).data.mapping.pairs) {
248                let p: *mut yaml_node_pair_t = (*parent).data.mapping.pairs.top.wrapping_offset(-1_isize);
249                if (*p).key != 0 && (*p).value == 0 {
250                    (*p).value = index;
251                    current_block_17 = 11307063007268554308;
252                } else {
253                    current_block_17 = 17407779659766490442;
254                }
255            } else {
256                current_block_17 = 17407779659766490442;
257            }
258            match current_block_17 {
259                11307063007268554308 => {}
260                _ => {
261                    (*pair).key = index;
262                    (*pair).value = 0;
263                    if STACK_LIMIT!(parser, (*parent).data.mapping.pairs).fail {
264                        return FAIL;
265                    }
266                    PUSH!((*parent).data.mapping.pairs, *pair);
267                }
268            }
269        }
270        _ => {
271            __assert!(false);
272        }
273    }
274    OK
275}
276
277unsafe fn yaml_parser_load_alias(
278    parser: *mut yaml_parser_t,
279    event: *mut yaml_event_t,
280    ctx: *mut loader_ctx,
281) -> Success {
282    let anchor: *mut yaml_char_t = (*event).data.alias.anchor;
283    let mut alias_data: *mut yaml_alias_data_t;
284    alias_data = (*parser).aliases.start;
285    while alias_data != (*parser).aliases.top {
286        if strcmp((*alias_data).anchor as *mut libc::c_char, anchor as *mut libc::c_char) == 0 {
287            yaml_free(anchor as *mut libc::c_void);
288            return yaml_parser_load_node_add(parser, ctx, (*alias_data).index);
289        }
290        alias_data = alias_data.wrapping_offset(1);
291    }
292    yaml_free(anchor as *mut libc::c_void);
293    yaml_parser_set_composer_error(
294        parser,
295        b"found undefined alias\0" as *const u8 as *const libc::c_char,
296        (*event).start_mark,
297    )
298}
299
300unsafe fn yaml_parser_load_scalar(
301    parser: *mut yaml_parser_t,
302    event: *mut yaml_event_t,
303    ctx: *mut loader_ctx,
304) -> Success {
305    let current_block: u64;
306    let mut node = MaybeUninit::<yaml_node_t>::uninit();
307    let node = node.as_mut_ptr();
308    let index: libc::c_int;
309    let mut tag: *mut yaml_char_t = (*event).data.scalar.tag;
310    if STACK_LIMIT!(parser, (*(*parser).document).nodes).ok {
311        if tag.is_null() || strcmp(tag as *mut libc::c_char, b"!\0" as *const u8 as *const libc::c_char) == 0 {
312            yaml_free(tag as *mut libc::c_void);
313            tag = yaml_strdup(b"tag:yaml.org,2002:str\0" as *const u8 as *const libc::c_char as *mut yaml_char_t);
314            if tag.is_null() {
315                current_block = 10579931339944277179;
316            } else {
317                current_block = 11006700562992250127;
318            }
319        } else {
320            current_block = 11006700562992250127;
321        }
322        if current_block != 10579931339944277179 {
323            memset(node as *mut libc::c_void, 0, size_of::<yaml_node_t>() as libc::c_ulong);
324            (*node).type_ = YAML_SCALAR_NODE;
325            (*node).tag = tag;
326            (*node).start_mark = (*event).start_mark;
327            (*node).end_mark = (*event).end_mark;
328            (*node).data.scalar.value = (*event).data.scalar.value;
329            (*node).data.scalar.length = (*event).data.scalar.length;
330            (*node).data.scalar.style = (*event).data.scalar.style;
331            PUSH!((*(*parser).document).nodes, *node);
332            index = (*(*parser).document)
333                .nodes
334                .top
335                .c_offset_from((*(*parser).document).nodes.start) as libc::c_int;
336            if yaml_parser_register_anchor(parser, index, (*event).data.scalar.anchor).fail {
337                return FAIL;
338            }
339            return yaml_parser_load_node_add(parser, ctx, index);
340        }
341    }
342    yaml_free(tag as *mut libc::c_void);
343    yaml_free((*event).data.scalar.anchor as *mut libc::c_void);
344    yaml_free((*event).data.scalar.value as *mut libc::c_void);
345    FAIL
346}
347
348unsafe fn yaml_parser_load_sequence(
349    parser: *mut yaml_parser_t,
350    event: *mut yaml_event_t,
351    ctx: *mut loader_ctx,
352) -> Success {
353    let current_block: u64;
354    let mut node = MaybeUninit::<yaml_node_t>::uninit();
355    let node = node.as_mut_ptr();
356    struct Items {
357        start: *mut yaml_node_item_t,
358        end: *mut yaml_node_item_t,
359        top: *mut yaml_node_item_t,
360    }
361    let mut items = Items {
362        start: ptr::null_mut::<yaml_node_item_t>(),
363        end: ptr::null_mut::<yaml_node_item_t>(),
364        top: ptr::null_mut::<yaml_node_item_t>(),
365    };
366    let index: libc::c_int;
367    let mut tag: *mut yaml_char_t = (*event).data.sequence_start.tag;
368    if STACK_LIMIT!(parser, (*(*parser).document).nodes).ok {
369        if tag.is_null() || strcmp(tag as *mut libc::c_char, b"!\0" as *const u8 as *const libc::c_char) == 0 {
370            yaml_free(tag as *mut libc::c_void);
371            tag = yaml_strdup(b"tag:yaml.org,2002:seq\0" as *const u8 as *const libc::c_char as *mut yaml_char_t);
372            if tag.is_null() {
373                current_block = 13474536459355229096;
374            } else {
375                current_block = 6937071982253665452;
376            }
377        } else {
378            current_block = 6937071982253665452;
379        }
380        if current_block != 13474536459355229096 {
381            STACK_INIT!(items, yaml_node_item_t);
382            memset(node as *mut libc::c_void, 0, size_of::<yaml_node_t>() as libc::c_ulong);
383            (*node).type_ = YAML_SEQUENCE_NODE;
384            (*node).tag = tag;
385            (*node).start_mark = (*event).start_mark;
386            (*node).end_mark = (*event).end_mark;
387            (*node).data.sequence.items.start = items.start;
388            (*node).data.sequence.items.end = items.end;
389            (*node).data.sequence.items.top = items.start;
390            (*node).data.sequence.style = (*event).data.sequence_start.style;
391            PUSH!((*(*parser).document).nodes, *node);
392            index = (*(*parser).document)
393                .nodes
394                .top
395                .c_offset_from((*(*parser).document).nodes.start) as libc::c_int;
396            if yaml_parser_register_anchor(parser, index, (*event).data.sequence_start.anchor).fail {
397                return FAIL;
398            }
399            if yaml_parser_load_node_add(parser, ctx, index).fail {
400                return FAIL;
401            }
402            if STACK_LIMIT!(parser, *ctx).fail {
403                return FAIL;
404            }
405            PUSH!(*ctx, index);
406            return OK;
407        }
408    }
409    yaml_free(tag as *mut libc::c_void);
410    yaml_free((*event).data.sequence_start.anchor as *mut libc::c_void);
411    FAIL
412}
413
414unsafe fn yaml_parser_load_sequence_end(
415    parser: *mut yaml_parser_t,
416    event: *mut yaml_event_t,
417    ctx: *mut loader_ctx,
418) -> Success {
419    __assert!(((*ctx).top).c_offset_from((*ctx).start) as libc::c_long > 0_i64);
420    let index: libc::c_int = *(*ctx).top.wrapping_offset(-1_isize);
421    __assert!((*((*(*parser).document).nodes.start).wrapping_offset((index - 1) as isize)).type_ == YAML_SEQUENCE_NODE);
422    (*(*(*parser).document).nodes.start.wrapping_offset((index - 1) as isize)).end_mark = (*event).end_mark;
423    let _ = POP!(*ctx);
424    OK
425}
426
427unsafe fn yaml_parser_load_mapping(
428    parser: *mut yaml_parser_t,
429    event: *mut yaml_event_t,
430    ctx: *mut loader_ctx,
431) -> Success {
432    let current_block: u64;
433    let mut node = MaybeUninit::<yaml_node_t>::uninit();
434    let node = node.as_mut_ptr();
435    struct Pairs {
436        start: *mut yaml_node_pair_t,
437        end: *mut yaml_node_pair_t,
438        top: *mut yaml_node_pair_t,
439    }
440    let mut pairs = Pairs {
441        start: ptr::null_mut::<yaml_node_pair_t>(),
442        end: ptr::null_mut::<yaml_node_pair_t>(),
443        top: ptr::null_mut::<yaml_node_pair_t>(),
444    };
445    let index: libc::c_int;
446    let mut tag: *mut yaml_char_t = (*event).data.mapping_start.tag;
447    if STACK_LIMIT!(parser, (*(*parser).document).nodes).ok {
448        if tag.is_null() || strcmp(tag as *mut libc::c_char, b"!\0" as *const u8 as *const libc::c_char) == 0 {
449            yaml_free(tag as *mut libc::c_void);
450            tag = yaml_strdup(b"tag:yaml.org,2002:map\0" as *const u8 as *const libc::c_char as *mut yaml_char_t);
451            if tag.is_null() {
452                current_block = 13635467803606088781;
453            } else {
454                current_block = 6937071982253665452;
455            }
456        } else {
457            current_block = 6937071982253665452;
458        }
459        if current_block != 13635467803606088781 {
460            STACK_INIT!(pairs, yaml_node_pair_t);
461            memset(node as *mut libc::c_void, 0, size_of::<yaml_node_t>() as libc::c_ulong);
462            (*node).type_ = YAML_MAPPING_NODE;
463            (*node).tag = tag;
464            (*node).start_mark = (*event).start_mark;
465            (*node).end_mark = (*event).end_mark;
466            (*node).data.mapping.pairs.start = pairs.start;
467            (*node).data.mapping.pairs.end = pairs.end;
468            (*node).data.mapping.pairs.top = pairs.start;
469            (*node).data.mapping.style = (*event).data.mapping_start.style;
470            PUSH!((*(*parser).document).nodes, *node);
471            index = (*(*parser).document)
472                .nodes
473                .top
474                .c_offset_from((*(*parser).document).nodes.start) as libc::c_int;
475            if yaml_parser_register_anchor(parser, index, (*event).data.mapping_start.anchor).fail {
476                return FAIL;
477            }
478            if yaml_parser_load_node_add(parser, ctx, index).fail {
479                return FAIL;
480            }
481            if STACK_LIMIT!(parser, *ctx).fail {
482                return FAIL;
483            }
484            PUSH!(*ctx, index);
485            return OK;
486        }
487    }
488    yaml_free(tag as *mut libc::c_void);
489    yaml_free((*event).data.mapping_start.anchor as *mut libc::c_void);
490    FAIL
491}
492
493unsafe fn yaml_parser_load_mapping_end(
494    parser: *mut yaml_parser_t,
495    event: *mut yaml_event_t,
496    ctx: *mut loader_ctx,
497) -> Success {
498    __assert!(((*ctx).top).c_offset_from((*ctx).start) as libc::c_long > 0_i64);
499    let index: libc::c_int = *(*ctx).top.wrapping_offset(-1_isize);
500    __assert!((*((*(*parser).document).nodes.start).wrapping_offset((index - 1) as isize)).type_ == YAML_MAPPING_NODE);
501    (*(*(*parser).document).nodes.start.wrapping_offset((index - 1) as isize)).end_mark = (*event).end_mark;
502    let _ = POP!(*ctx);
503    OK
504}