diff --git a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp index 6245d2ae4..9a957d616 100644 --- a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp +++ b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "../../Epub.h" @@ -996,7 +997,7 @@ bool ChapterHtmlSlimParser::parseAndBuildPages() { paragraphAlignmentBlockStyle.alignment = align; startNewTextBlock(paragraphAlignmentBlockStyle); - const XML_Parser parser = XML_ParserCreate(nullptr); + XML_Parser parser = XML_ParserCreate(nullptr); int done; if (!parser) { @@ -1010,7 +1011,7 @@ bool ChapterHtmlSlimParser::parseAndBuildPages() { FsFile file; if (!Storage.openFileForRead("EHP", filepath, file)) { - XML_ParserFree(parser); + destroyXmlParser(parser); return false; } @@ -1029,10 +1030,8 @@ bool ChapterHtmlSlimParser::parseAndBuildPages() { void* const buf = XML_GetBuffer(parser, PARSE_BUFFER_SIZE); if (!buf) { LOG_ERR("EHP", "Couldn't allocate memory for buffer"); - XML_StopParser(parser, XML_FALSE); // Stop any pending processing - XML_SetElementHandler(parser, nullptr, nullptr); // Clear callbacks - XML_SetCharacterDataHandler(parser, nullptr); - XML_ParserFree(parser); + destroyXmlParser(parser); + file.close(); return false; } @@ -1040,10 +1039,8 @@ bool ChapterHtmlSlimParser::parseAndBuildPages() { if (len == 0 && file.available() > 0) { LOG_ERR("EHP", "File read error"); - XML_StopParser(parser, XML_FALSE); // Stop any pending processing - XML_SetElementHandler(parser, nullptr, nullptr); // Clear callbacks - XML_SetCharacterDataHandler(parser, nullptr); - XML_ParserFree(parser); + destroyXmlParser(parser); + file.close(); return false; } @@ -1052,19 +1049,15 @@ bool ChapterHtmlSlimParser::parseAndBuildPages() { if (XML_ParseBuffer(parser, static_cast(len), done) == XML_STATUS_ERROR) { LOG_ERR("EHP", "Parse error at line %lu:\n%s", XML_GetCurrentLineNumber(parser), XML_ErrorString(XML_GetErrorCode(parser))); - XML_StopParser(parser, XML_FALSE); // Stop any pending processing - XML_SetElementHandler(parser, nullptr, nullptr); // Clear callbacks - XML_SetCharacterDataHandler(parser, nullptr); - XML_ParserFree(parser); + destroyXmlParser(parser); + file.close(); return false; } } while (!done); LOG_DBG("EHP", "Time to parse and build pages: %lu ms", millis() - chapterStartTime); - XML_StopParser(parser, XML_FALSE); // Stop any pending processing - XML_SetElementHandler(parser, nullptr, nullptr); // Clear callbacks - XML_SetCharacterDataHandler(parser, nullptr); - XML_ParserFree(parser); + destroyXmlParser(parser); + file.close(); // Process last page if there is still text if (currentTextBlock) { diff --git a/lib/Epub/Epub/parsers/ContainerParser.cpp b/lib/Epub/Epub/parsers/ContainerParser.cpp index aa7a92a0b..0ce90a21b 100644 --- a/lib/Epub/Epub/parsers/ContainerParser.cpp +++ b/lib/Epub/Epub/parsers/ContainerParser.cpp @@ -1,6 +1,7 @@ #include "ContainerParser.h" #include +#include bool ContainerParser::setup() { parser = XML_ParserCreate(nullptr); @@ -14,14 +15,7 @@ bool ContainerParser::setup() { return true; } -ContainerParser::~ContainerParser() { - if (parser) { - XML_StopParser(parser, XML_FALSE); // Stop any pending processing - XML_SetElementHandler(parser, nullptr, nullptr); // Clear callbacks - XML_ParserFree(parser); - parser = nullptr; - } -} +ContainerParser::~ContainerParser() { destroyXmlParser(parser); } size_t ContainerParser::write(const uint8_t data) { return write(&data, 1); } @@ -35,6 +29,7 @@ size_t ContainerParser::write(const uint8_t* buffer, const size_t size) { void* const buf = XML_GetBuffer(parser, 1024); if (!buf) { LOG_DBG("CTR", "Couldn't allocate buffer"); + destroyXmlParser(parser); return 0; } @@ -43,6 +38,7 @@ size_t ContainerParser::write(const uint8_t* buffer, const size_t size) { if (XML_ParseBuffer(parser, static_cast(toRead), remainingSize == toRead) == XML_STATUS_ERROR) { LOG_ERR("CTR", "Parse error: %s", XML_ErrorString(XML_GetErrorCode(parser))); + destroyXmlParser(parser); return 0; } diff --git a/lib/Epub/Epub/parsers/ContentOpfParser.cpp b/lib/Epub/Epub/parsers/ContentOpfParser.cpp index 33518bc65..f75fd2d0c 100644 --- a/lib/Epub/Epub/parsers/ContentOpfParser.cpp +++ b/lib/Epub/Epub/parsers/ContentOpfParser.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "../BookMetadataCache.h" @@ -26,13 +27,7 @@ bool ContentOpfParser::setup() { } ContentOpfParser::~ContentOpfParser() { - if (parser) { - XML_StopParser(parser, XML_FALSE); // Stop any pending processing - XML_SetElementHandler(parser, nullptr, nullptr); // Clear callbacks - XML_SetCharacterDataHandler(parser, nullptr); - XML_ParserFree(parser); - parser = nullptr; - } + destroyXmlParser(parser); if (tempItemStore) { tempItemStore.close(); } @@ -55,11 +50,7 @@ size_t ContentOpfParser::write(const uint8_t* buffer, const size_t size) { if (!buf) { LOG_ERR("COF", "Couldn't allocate memory for buffer"); - XML_StopParser(parser, XML_FALSE); // Stop any pending processing - XML_SetElementHandler(parser, nullptr, nullptr); // Clear callbacks - XML_SetCharacterDataHandler(parser, nullptr); - XML_ParserFree(parser); - parser = nullptr; + destroyXmlParser(parser); return 0; } @@ -69,11 +60,7 @@ size_t ContentOpfParser::write(const uint8_t* buffer, const size_t size) { if (XML_ParseBuffer(parser, static_cast(toRead), remainingSize == toRead) == XML_STATUS_ERROR) { LOG_DBG("COF", "Parse error at line %lu: %s", XML_GetCurrentLineNumber(parser), XML_ErrorString(XML_GetErrorCode(parser))); - XML_StopParser(parser, XML_FALSE); // Stop any pending processing - XML_SetElementHandler(parser, nullptr, nullptr); // Clear callbacks - XML_SetCharacterDataHandler(parser, nullptr); - XML_ParserFree(parser); - parser = nullptr; + destroyXmlParser(parser); return 0; } diff --git a/lib/Epub/Epub/parsers/TocNavParser.cpp b/lib/Epub/Epub/parsers/TocNavParser.cpp index 8c8afdd51..dc293c141 100644 --- a/lib/Epub/Epub/parsers/TocNavParser.cpp +++ b/lib/Epub/Epub/parsers/TocNavParser.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "../BookMetadataCache.h" @@ -18,15 +19,7 @@ bool TocNavParser::setup() { return true; } -TocNavParser::~TocNavParser() { - if (parser) { - XML_StopParser(parser, XML_FALSE); - XML_SetElementHandler(parser, nullptr, nullptr); - XML_SetCharacterDataHandler(parser, nullptr); - XML_ParserFree(parser); - parser = nullptr; - } -} +TocNavParser::~TocNavParser() { destroyXmlParser(parser); } size_t TocNavParser::write(const uint8_t data) { return write(&data, 1); } @@ -40,11 +33,7 @@ size_t TocNavParser::write(const uint8_t* buffer, const size_t size) { void* const buf = XML_GetBuffer(parser, 1024); if (!buf) { LOG_DBG("NAV", "Couldn't allocate memory for buffer"); - XML_StopParser(parser, XML_FALSE); - XML_SetElementHandler(parser, nullptr, nullptr); - XML_SetCharacterDataHandler(parser, nullptr); - XML_ParserFree(parser); - parser = nullptr; + destroyXmlParser(parser); return 0; } @@ -54,11 +43,7 @@ size_t TocNavParser::write(const uint8_t* buffer, const size_t size) { if (XML_ParseBuffer(parser, static_cast(toRead), remainingSize == toRead) == XML_STATUS_ERROR) { LOG_DBG("NAV", "Parse error at line %lu: %s", XML_GetCurrentLineNumber(parser), XML_ErrorString(XML_GetErrorCode(parser))); - XML_StopParser(parser, XML_FALSE); - XML_SetElementHandler(parser, nullptr, nullptr); - XML_SetCharacterDataHandler(parser, nullptr); - XML_ParserFree(parser); - parser = nullptr; + destroyXmlParser(parser); return 0; } diff --git a/lib/Epub/Epub/parsers/TocNcxParser.cpp b/lib/Epub/Epub/parsers/TocNcxParser.cpp index 843790251..ac968010c 100644 --- a/lib/Epub/Epub/parsers/TocNcxParser.cpp +++ b/lib/Epub/Epub/parsers/TocNcxParser.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "../BookMetadataCache.h" @@ -18,15 +19,7 @@ bool TocNcxParser::setup() { return true; } -TocNcxParser::~TocNcxParser() { - if (parser) { - XML_StopParser(parser, XML_FALSE); // Stop any pending processing - XML_SetElementHandler(parser, nullptr, nullptr); // Clear callbacks - XML_SetCharacterDataHandler(parser, nullptr); - XML_ParserFree(parser); - parser = nullptr; - } -} +TocNcxParser::~TocNcxParser() { destroyXmlParser(parser); } size_t TocNcxParser::write(const uint8_t data) { return write(&data, 1); } @@ -40,11 +33,7 @@ size_t TocNcxParser::write(const uint8_t* buffer, const size_t size) { void* const buf = XML_GetBuffer(parser, 1024); if (!buf) { LOG_DBG("TOC", "Couldn't allocate memory for buffer"); - XML_StopParser(parser, XML_FALSE); // Stop any pending processing - XML_SetElementHandler(parser, nullptr, nullptr); // Clear callbacks - XML_SetCharacterDataHandler(parser, nullptr); - XML_ParserFree(parser); - parser = nullptr; + destroyXmlParser(parser); return 0; } @@ -54,11 +43,7 @@ size_t TocNcxParser::write(const uint8_t* buffer, const size_t size) { if (XML_ParseBuffer(parser, static_cast(toRead), remainingSize == toRead) == XML_STATUS_ERROR) { LOG_DBG("TOC", "Parse error at line %lu: %s", XML_GetCurrentLineNumber(parser), XML_ErrorString(XML_GetErrorCode(parser))); - XML_StopParser(parser, XML_FALSE); // Stop any pending processing - XML_SetElementHandler(parser, nullptr, nullptr); // Clear callbacks - XML_SetCharacterDataHandler(parser, nullptr); - XML_ParserFree(parser); - parser = nullptr; + destroyXmlParser(parser); return 0; } diff --git a/lib/OpdsParser/OpdsParser.cpp b/lib/OpdsParser/OpdsParser.cpp index 84feef74f..ef769f11f 100644 --- a/lib/OpdsParser/OpdsParser.cpp +++ b/lib/OpdsParser/OpdsParser.cpp @@ -1,6 +1,7 @@ #include "OpdsParser.h" #include +#include #include @@ -12,15 +13,7 @@ OpdsParser::OpdsParser() { } } -OpdsParser::~OpdsParser() { - if (parser) { - XML_StopParser(parser, XML_FALSE); - XML_SetElementHandler(parser, nullptr, nullptr); - XML_SetCharacterDataHandler(parser, nullptr); - XML_ParserFree(parser); - parser = nullptr; - } -} +OpdsParser::~OpdsParser() { destroyXmlParser(parser); } size_t OpdsParser::write(uint8_t c) { return write(&c, 1); } @@ -39,7 +32,8 @@ size_t OpdsParser::write(const uint8_t* xmlData, const size_t length) { void* const buf = XML_GetBuffer(parser, chunkSize); if (!buf) { errorOccured = true; - XML_ParserFree(parser); + LOG_DBG("OPDS", "Couldn't allocate memory for buffer"); + destroyXmlParser(parser); return length; } @@ -48,7 +42,9 @@ size_t OpdsParser::write(const uint8_t* xmlData, const size_t length) { if (XML_ParseBuffer(parser, static_cast(toRead), 0) == XML_STATUS_ERROR) { errorOccured = true; - XML_ParserFree(parser); + LOG_DBG("OPDS", "Parse error at line %lu: %s", XML_GetCurrentLineNumber(parser), + XML_ErrorString(XML_GetErrorCode(parser))); + destroyXmlParser(parser); return length; } currentPos += toRead; @@ -60,8 +56,7 @@ size_t OpdsParser::write(const uint8_t* xmlData, const size_t length) { void OpdsParser::flush() { if (XML_Parse(parser, nullptr, 0, XML_TRUE) != XML_STATUS_OK) { errorOccured = true; - XML_ParserFree(parser); - parser = nullptr; + destroyXmlParser(parser); } } diff --git a/lib/XmlParserUtils/XmlParserUtils.h b/lib/XmlParserUtils/XmlParserUtils.h new file mode 100644 index 000000000..bbab9c933 --- /dev/null +++ b/lib/XmlParserUtils/XmlParserUtils.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +// Safely tear down an expat parser: stop processing, clear callbacks, free, and null the pointer. +inline void destroyXmlParser(XML_Parser& parser) { + if (!parser) return; + XML_StopParser(parser, XML_FALSE); + XML_SetElementHandler(parser, nullptr, nullptr); + XML_SetCharacterDataHandler(parser, nullptr); + XML_ParserFree(parser); + parser = nullptr; +}