From: Francis Dupont Date: Mon, 28 Nov 2016 14:31:10 +0000 (+0100) Subject: [5014_phase2] Fixed lexer cleanup on any exit (note parser uses try-catch) X-Git-Tag: trac5036_base2~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=58bb8f3445a80600548996c58d267fa5eb12327f;p=thirdparty%2Fkea.git [5014_phase2] Fixed lexer cleanup on any exit (note parser uses try-catch) --- diff --git a/src/bin/dhcp6/dhcp6_lexer.ll b/src/bin/dhcp6/dhcp6_lexer.ll index f6012f19f7..7a77b189de 100644 --- a/src/bin/dhcp6/dhcp6_lexer.ll +++ b/src/bin/dhcp6/dhcp6_lexer.ll @@ -882,6 +882,14 @@ null { driver.locs_.pop_back(); driver.file_ = driver.files_.back(); driver.files_.pop_back(); + if (driver.sfile_) { + fclose(driver.sfile_); + driver.sfile_ = 0; + } + if (!driver.sfiles_.empty()) { + driver.sfile_ = driver.sfiles_.back(); + driver.sfiles_.pop_back(); + } parser6__delete_buffer(YY_CURRENT_BUFFER); parser6__switch_to_buffer(driver.states_.back()); driver.states_.pop_back(); @@ -896,11 +904,11 @@ using namespace isc::dhcp; void Parser6Context::scanStringBegin(const std::string& str, ParserType parser_type) { - static_cast(parser6_lex_destroy()); start_token_flag = true; start_token_value = parser_type; file_ = ""; + sfile_ = 0; loc_.initialize(&file_); yy_flex_debug = trace_scanning_; YY_BUFFER_STATE buffer; @@ -911,22 +919,16 @@ Parser6Context::scanStringBegin(const std::string& str, ParserType parser_type) } } -void -Parser6Context::scanStringEnd() -{ - yy_delete_buffer(YY_CURRENT_BUFFER); -} - void Parser6Context::scanFileBegin(FILE * f, const std::string& filename, ParserType parser_type) { - static_cast(parser6_lex_destroy()); start_token_flag = true; start_token_value = parser_type; file_ = filename; + sfile_ = f; loc_.initialize(&file_); yy_flex_debug = trace_scanning_; YY_BUFFER_STATE buffer; @@ -940,9 +942,24 @@ Parser6Context::scanFileBegin(FILE * f, } void -Parser6Context::scanFileEnd(FILE * f) { - fclose(f); - yy_delete_buffer(YY_CURRENT_BUFFER); +Parser6Context::scanEnd() { + if (sfile_) + fclose(sfile_); + sfile_ = 0; + static_cast(parser6_lex_destroy()); + // Close files + while (!sfiles_.empty()) { + FILE* f = sfiles_.back(); + if (f) { + fclose(f); + } + sfiles_.pop_back(); + } + // Delete states + while (!states_.empty()) { + parser6__delete_buffer(states_.back()); + states_.pop_back(); + } } void @@ -955,6 +972,10 @@ Parser6Context::includeFile(const std::string& filename) { if (!f) { fatal("Can't open include file " + filename); } + if (sfile_) { + sfiles_.push_back(sfile_); + } + sfile_ = f; states_.push_back(YY_CURRENT_BUFFER); YY_BUFFER_STATE buffer; buffer = parser6__create_buffer(f, 65536 /*buffer size*/); diff --git a/src/bin/dhcp6/dhcp6_parser.yy b/src/bin/dhcp6/dhcp6_parser.yy index 7cff1b89d5..f48bff75c4 100644 --- a/src/bin/dhcp6/dhcp6_parser.yy +++ b/src/bin/dhcp6/dhcp6_parser.yy @@ -259,9 +259,9 @@ global_objects: global_object // This represents a single top level entry, e.g. Dhcp6 or DhcpDdns. global_object: dhcp6_object | logging_object - | dhcp4_json_object - | dhcpddns_json_object - | unknown_map_entry + | dhcp4_json_object + | dhcpddns_json_object + | unknown_map_entry ; dhcp6_object: DHCP6 { diff --git a/src/bin/dhcp6/parser_context.cc b/src/bin/dhcp6/parser_context.cc index db5eec4dba..7bf69ecbb5 100644 --- a/src/bin/dhcp6/parser_context.cc +++ b/src/bin/dhcp6/parser_context.cc @@ -28,21 +28,7 @@ isc::data::ConstElementPtr Parser6Context::parseString(const std::string& str, ParserType parser_type) { scanStringBegin(str, parser_type); - isc::dhcp::Dhcp6Parser parser(*this); - // Uncomment this to get detailed parser logs. - // trace_parsing_ = true; - parser.set_debug_level(trace_parsing_); - int res = parser.parse(); - if (res != 0) { - // @todo: handle exception here - } - scanStringEnd(); - if (stack_.size() == 1) { - return (stack_[0]); - } else { - isc_throw(Dhcp6ParseError, "Expected exactly one terminal Element expected, found " - << stack_.size()); - } + return (parseCommon()); } isc::data::ConstElementPtr @@ -52,16 +38,26 @@ Parser6Context::parseFile(const std::string& filename, ParserType parser_type) { isc_throw(Dhcp6ParseError, "Unable to open file " << filename); } scanFileBegin(f, filename, parser_type); + return (parseCommon()); +} +isc::data::ConstElementPtr +Parser6Context::parseCommon() { isc::dhcp::Dhcp6Parser parser(*this); // Uncomment this to get detailed parser logs. // trace_parsing_ = true; parser.set_debug_level(trace_parsing_); - int res = parser.parse(); - if (res != 0) { - // @todo: handle exception here + try { + int res = parser.parse(); + if (res != 0) { + isc_throw(Dhcp6ParseError, "Parser abort"); + } + scanEnd(); + } + catch (...) { + scanEnd(); + throw; } - scanFileEnd(f); if (stack_.size() == 1) { return (stack_[0]); } else { diff --git a/src/bin/dhcp6/parser_context.h b/src/bin/dhcp6/parser_context.h index 7317acdbaa..cafee4be90 100644 --- a/src/bin/dhcp6/parser_context.h +++ b/src/bin/dhcp6/parser_context.h @@ -53,14 +53,11 @@ public: /// @brief Method called before scanning starts on a string. void scanStringBegin(const std::string& str, ParserType type); - /// @brief Method called after the last tokens are scanned from a string. - void scanStringEnd(); - /// @brief Method called before scanning starts on a file. void scanFileBegin(FILE * f, const std::string& filename, ParserType type); - /// @brief Method called after the last tokens are scanned from a file. - void scanFileEnd(FILE * f); + /// @brief Method called after the last tokens are scanned. + void scanEnd(); /// @brief Divert input to an include file. void includeFile(const std::string& filename); @@ -144,9 +141,15 @@ public: /// @brief Location stack std::vector locs_; - /// @brief State stack + /// @brief Lexer state stack std::vector states_;; + /// @brief sFile (aka FILE) + FILE* sfile_; + + /// @brief sFile (aka FILE) stack + std::vector sfiles_; + /// @brief Current syntactic context ParserContext ctx_; @@ -169,6 +172,9 @@ public: /// @brief Syntactic context stack std::vector cstack_; + + /// @brief Common part of parseXXX + isc::data::ConstElementPtr parseCommon(); }; }; // end of isc::eval namespace