Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infinite loop in parse() after YAML_MEMORY_ERROR #440

Closed
khanderson opened this issue Mar 7, 2020 · 0 comments
Closed

Infinite loop in parse() after YAML_MEMORY_ERROR #440

khanderson opened this issue Mar 7, 2020 · 0 comments

Comments

@khanderson
Copy link
Contributor

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;
...
	}
}
khanderson added a commit to khanderson/ruby that referenced this issue Oct 28, 2021
Fix for the psych parser entering an infinite loop after a mem allocation failure.

PR in ruby/psych project: ruby/psych#526
hsbt pushed a commit to khanderson/psych that referenced this issue May 13, 2022
tenderlove added a commit that referenced this issue Jul 14, 2022
Fix infinite loop bug after YAML_MEMORY_ERROR (psych issue #440)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

1 participant