Fix stack-use-after-return with unterminated heredocs#4155
Open
matz wants to merge 1 commit into
Open
Conversation
279dcd7 to
e9c2567
Compare
The heredoc handler in parse_expression_prefix stores the address of its stack-local common_whitespace into the heredoc lex mode. When the heredoc terminator is missing, expect1_heredoc_term reports an error without popping the lex mode, so the stored pointer outlives the stack frame and subsequent lexing reads dead stack memory. Clear the pointer before leaving the handler; the lexer already guards against NULL. Co-authored-by: Claude <noreply@anthropic.com>
e9c2567 to
9bd2370
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This fixes a stack-use-after-return found while fuzzing mruby, which vendors Prism as its compiler.
Reproduction (24 bytes, minimized from a clusterfuzz testcase):
`#{r{<<~0 #{{i}w<<0 0 }Parsing this source under valgrind, or ASan with
detect_stack_use_after_return=1, reports reads of a dead stack frame inparser_lex:Cause: the
PM_TOKEN_HEREDOC_STARThandler inparse_expression_prefixstores the address of its stack-localcommon_whitespaceinto the heredoc lex mode so that the lexer can report the common leading whitespace back to the parser. On well-formed input the lex mode is popped whenPM_TOKEN_HEREDOC_ENDis lexed, before the handler returns. When the terminator is missing, however,expect1_heredoc_termonly records an error and does not pop the lex mode, so the stored pointer outlives the handler's stack frame. Subsequent lexing, still in heredoc mode, then dereferences the dangling pointer at thecommon_whitespacechecks inparser_lex.Fix: before leaving the handler, walk the lex mode stack and clear any
common_whitespacepointer that still points at the handler's local. The lexer already guards the pointer against NULL, so this degrades gracefully; the dedent width is lost, but the source is a syntax error at that point anyway.I verified the fix with valgrind and ASan on the v1.9.0 sources vendored in mruby, and the same code is present on main.