Avoid double deletion when NoViableAltException is thrown

When ownership of the configurations set is passed to a NoViableAltException,
it get deleted more than once if the exception happens to get copied.
This commit is contained in:
Gerasimos Dimitriadis 2019-02-23 20:31:19 +02:00
parent 1c6c62afc7
commit d69e7c4d0f
3 changed files with 20 additions and 8 deletions

View File

@ -213,3 +213,4 @@ YYYY/MM/DD, github id, Full name, email
2018/12/20, WalterCouto, Walter Couto, WalterCouto@users.noreply.github.com 2018/12/20, WalterCouto, Walter Couto, WalterCouto@users.noreply.github.com
2018/12/23, youkaichao, Kaichao You, youkaichao@gmail.com 2018/12/23, youkaichao, Kaichao You, youkaichao@gmail.com
2019/02/06, ralucado, Cristina Raluca Vijulie, ralucris.v[at]gmail[dot]com 2019/02/06, ralucado, Cristina Raluca Vijulie, ralucris.v[at]gmail[dot]com
2019/02/23, gedimitr, Gerasimos Dimitriadis, gedimitr@gmail.com

View File

@ -9,6 +9,20 @@
using namespace antlr4; using namespace antlr4;
namespace {
// Create a normal shared pointer if the configurations are to be deleted. If not, then
// the shared pointer is created with a deleter that does nothing.
Ref<atn::ATNConfigSet> buildConfigsRef(atn::ATNConfigSet *configs, bool deleteConfigs) {
if (deleteConfigs) {
return Ref<atn::ATNConfigSet>(configs);
} else {
return Ref<atn::ATNConfigSet>(configs, [](atn::ATNConfigSet *){});
}
}
}
NoViableAltException::NoViableAltException(Parser *recognizer) NoViableAltException::NoViableAltException(Parser *recognizer)
: NoViableAltException(recognizer, recognizer->getTokenStream(), recognizer->getCurrentToken(), : NoViableAltException(recognizer, recognizer->getTokenStream(), recognizer->getCurrentToken(),
recognizer->getCurrentToken(), nullptr, recognizer->getContext(), false) { recognizer->getCurrentToken(), nullptr, recognizer->getContext(), false) {
@ -17,12 +31,10 @@ NoViableAltException::NoViableAltException(Parser *recognizer)
NoViableAltException::NoViableAltException(Parser *recognizer, TokenStream *input,Token *startToken, NoViableAltException::NoViableAltException(Parser *recognizer, TokenStream *input,Token *startToken,
Token *offendingToken, atn::ATNConfigSet *deadEndConfigs, ParserRuleContext *ctx, bool deleteConfigs) Token *offendingToken, atn::ATNConfigSet *deadEndConfigs, ParserRuleContext *ctx, bool deleteConfigs)
: RecognitionException("No viable alternative", recognizer, input, ctx, offendingToken), : RecognitionException("No viable alternative", recognizer, input, ctx, offendingToken),
_deadEndConfigs(deadEndConfigs), _startToken(startToken), _deleteConfigs(deleteConfigs) { _deadEndConfigs(buildConfigsRef(deadEndConfigs, deleteConfigs)), _startToken(startToken) {
} }
NoViableAltException::~NoViableAltException() { NoViableAltException::~NoViableAltException() {
if (_deleteConfigs)
delete _deadEndConfigs;
} }
Token* NoViableAltException::getStartToken() const { Token* NoViableAltException::getStartToken() const {
@ -30,5 +42,5 @@ Token* NoViableAltException::getStartToken() const {
} }
atn::ATNConfigSet* NoViableAltException::getDeadEndConfigs() const { atn::ATNConfigSet* NoViableAltException::getDeadEndConfigs() const {
return _deadEndConfigs; return _deadEndConfigs.get();
} }

View File

@ -27,10 +27,9 @@ namespace antlr4 {
private: private:
/// Which configurations did we try at input.index() that couldn't match input.LT(1)? /// Which configurations did we try at input.index() that couldn't match input.LT(1)?
atn::ATNConfigSet* _deadEndConfigs; /// Shared pointer that conditionally deletes the configurations (based on flag
/// passed during construction)
// Flag that indicates if we own the dead end config set and have to delete it on destruction. Ref<atn::ATNConfigSet> _deadEndConfigs;
bool _deleteConfigs;
/// The token object at the start index; the input stream might /// The token object at the start index; the input stream might
/// not be buffering tokens so get a reference to it. (At the /// not be buffering tokens so get a reference to it. (At the