Open pnck opened 5 years ago
i also found that if grammar contains ambiguity, the generated parser will not break out of current parsing loop after handled the error, and will try accessing invalid objects which may had been released in a former exception handler.
is it by design?
this probably relates to the change in PR #2398 and also to my comments there: https://github.com/antlr/antlr4/commit/95fecce8edfeedf4444e107eaa4f173054a436b9#commitcomment-31893994
But I were not sure how to fix.
I was able to get your code sample working. I commented on your diff; if I remove the contents of the destructor, then your sample works. Just let the shared_ptr
handle everything itself.
A shared_ptr won't solve the issue, because the stored dead end configuration can be one of states that are managed in the DFA (also via a shared_ptr), while others might just be created in this handler code. That's what makes this such a tricky problem. Maybe defining a move constructor, which resets the _deleteConfigs
in the source exception object would help?
@mike-lischke Thanks for taking a look at this. A move constructor may be the answer.
By the way, I just tried adding a move constructor:
NoViableAltException(NoViableAltException&&) = default;
The ANTLR runtime failed to compile because std::make_exception_ptr()
is specified to always make a copy. (See 17.9.6 of the WD standard).
The move constructor was a good idea, but it looks like it isn't allowed.
yes, i closed that PR also for another reason that i found crash may happen even let shared_ptr to handle the pointer. if the grammar definition includes some ambiguities and the parsing token is leading to multi errors, some objects would be use after freed because of the parse loop not breaking out. but i failed to simplify that example and it's related to my personal job so i didn't post it. i may try again to see if i can make another example.
here is the example, please check it
parse: stmt_list* EOF
;
stmt_list: ';'* stmt ( ';'+ stmt )* ';'*
;
stmt: 'A' 'B' | 'A' ('B')?;
WS: [\n ]+ -> skip
;
ANY: .
;
with input
A;
A _B;
run with valgrind and it will warn Invalid Write
please take a review at #2562
i think the real reason is deleting a raw ATNConfigSet
pointer which was originally managed by an unique_ptr in DFAState
CrashGrammar.g4:
main.cpp:
Crashes on parser doing
parse()
. Backtrace shows theNoViableAltException
destructing onreportNoViableAlternative
return, which is attempting to delete_deadEndConfigs
that has been deleted