Skip to content

Infinite loop in parse() after YAML_MEMORY_ERROR #440

@khanderson

Description

@khanderson

I've encountered an infinite loop in parse() in psych_parser.c, seemingly caused by incorrect handling of the YAML_MEMORY_ERROR error condition.

Here's what I see in gdb at psych_parser.c:307 (master atm, revision bb7585b), after yaml_parser_parse is called:

(gdb) p *((yaml_parser_t*)parser)
$3 = {error = YAML_MEMORY_ERROR, /* omitted fields */ }
(gdb) p event
$4 = {type = YAML_NO_EVENT, data = {stream_start = {encoding = YAML_ANY_ENCODING}, document_start = {version_directive = 0x0, tag_directives = {start = 0x0, end = 0x0}, implicit = 0},
    document_end = {implicit = 0}, alias = {anchor = 0x0}, scalar = {anchor = 0x0, tag = 0x0, value = 0x0, length = 0, plain_implicit = 0, quoted_implicit = 0, style = YAML_ANY_SCALAR_STYLE},
    sequence_start = {anchor = 0x0, tag = 0x0, implicit = 0, style = YAML_ANY_SEQUENCE_STYLE}, mapping_start = {anchor = 0x0, tag = 0x0, implicit = 0, style = YAML_ANY_MAPPING_STYLE}},
  start_mark = {index = 0, line = 0, column = 0}, end_mark = {index = 0, line = 0, column = 0}}

It looks like yaml_parser_parse() is returning 1/success in the error case...

    if (parser->stream_end_produced || parser->error ||
            parser->state == YAML_PARSE_END_STATE) {
        return 1;
    }

...but parse() is expecting it to return 0, so we get no exception, hit the YAML_NO_EVENT case and repeat.

while(!done) {
...
	if(!yaml_parser_parse(parser, &event)) {
	    VALUE exception;
	    exception = make_exception(parser, path);
	    yaml_parser_delete(parser);
	    yaml_parser_initialize(parser);
	    rb_exc_raise(exception);
	}
...
	switch(event.type) {
...
	  case YAML_NO_EVENT:
	    rb_protect(protected_empty, handler, &state);
	    break;
...
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions