From 5c9ca45a14429699ab06e59442add14ca72feabf Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Tue, 4 Nov 2025 16:45:21 +0200 Subject: [PATCH] Disable by default XML_PARSE_HUGE IB-8686 Signed-off-by: Raul Metsma --- .github/workflows/build.yml | 4 +++- src/XMLDocument.h | 10 ++++++++-- test/data/xml-bomb-attr.xml | 21 +++++++++++++++++++++ test/data/xml-bomb-cont.xml | 17 +++++++++++++++++ test/libdigidocpp_boost.cpp | 24 +++++++++++++++++------- 5 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 test/data/xml-bomb-attr.xml create mode 100644 test/data/xml-bomb-cont.xml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 71699fe56..22e3e59d8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,10 +22,12 @@ jobs: run: | brew update brew install --formula swig doxygen boost - brew unlink python@3.12 || true brew unlink python@3.13 || true + brew unlink python@3.14 || true brew unlink openssl@3 || true brew unlink xz + sudo rm -rf /Library/Frameworks/Python.framework/Versions/3.13 + sudo rm -rf /Library/Frameworks/Python.framework/Versions/3.14 - name: Cache uses: actions/cache@v4 id: cache diff --git a/src/XMLDocument.h b/src/XMLDocument.h index c05d0a7e4..277158246 100644 --- a/src/XMLDocument.h +++ b/src/XMLDocument.h @@ -315,13 +315,19 @@ struct XMLDocument: public unique_free_d, public XMLNode return is->good() || is->eof() ? int(is->gcount()) : -1; }, nullptr, &is, XML_CHAR_ENCODING_NONE)); #if VERSION_CHECK(XMLSEC_VERSION_MAJOR, XMLSEC_VERSION_MINOR, XMLSEC_VERSION_SUBMINOR) >= VERSION_CHECK(1, 3, 0) - ctxt->options |= xmlSecParserGetDefaultOptions(); + ctxt->options |= xmlSecParserGetDefaultOptions() & ~XML_PARSE_HUGE; #else - ctxt->options |= XML_PARSE_NOENT|XML_PARSE_DTDLOAD|XML_PARSE_DTDATTR|XML_PARSE_NONET; + ctxt->options |= XML_PARSE_NOENT|XML_PARSE_DTDLOAD|XML_PARSE_DTDATTR|XML_PARSE_NONET|XML_PARSE_NODICT; #endif ctxt->loadsubset |= XML_DETECT_IDS|XML_COMPLETE_ATTRS; if(hugeFile) + { ctxt->options |= XML_PARSE_HUGE; +#if LIBXML_VERSION < 21300 + if(ctxt->sax) + ctxt->sax->entityDecl = 0; +#endif + } auto result = xmlParseDocument(ctxt.get()); if(result != 0 || !ctxt->wellFormed) { diff --git a/test/data/xml-bomb-attr.xml b/test/data/xml-bomb-attr.xml new file mode 100644 index 000000000..740be0b5c --- /dev/null +++ b/test/data/xml-bomb-attr.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + +]> + + + + \ No newline at end of file diff --git a/test/data/xml-bomb-cont.xml b/test/data/xml-bomb-cont.xml new file mode 100644 index 000000000..82b51bb13 --- /dev/null +++ b/test/data/xml-bomb-cont.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + +]> + +&lol9; + \ No newline at end of file diff --git a/test/libdigidocpp_boost.cpp b/test/libdigidocpp_boost.cpp index 2adeccd16..d7be0735b 100644 --- a/test/libdigidocpp_boost.cpp +++ b/test/libdigidocpp_boost.cpp @@ -25,18 +25,12 @@ #include #include #include +#include #include #include #include #include -#include - -constexpr auto VERSION_CHECK(int major, int minor, int patch) -{ - return (major<<16)|(minor<<8)|patch; -} - namespace digidoc { @@ -590,3 +584,19 @@ BOOST_AUTO_TEST_CASE(OpenInvalidMimetypeContainer) BOOST_CHECK_THROW(Container::openPtr("test-invalid.asics"), Exception); } BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE(XMLTestSuite) +BOOST_AUTO_TEST_CASE(XMLBomb) +{ + BOOST_CHECK_EQUAL(XMLDocument("xml-bomb-attr.xml"), false); + BOOST_CHECK_EQUAL(XMLDocument("xml-bomb-cont.xml"), false); + if(std::fstream f{"xml-bomb-attr.xml"}) + BOOST_CHECK_THROW(XMLDocument::openStream(f), Exception); + if(std::fstream f{"xml-bomb-cont.xml"}) + BOOST_CHECK_THROW(XMLDocument::openStream(f), Exception); + if(std::fstream f{"xml-bomb-attr.xml"}) + BOOST_CHECK_THROW(XMLDocument::openStream(f, {}, true), Exception); + if(std::fstream f{"xml-bomb-cont.xml"}) + BOOST_CHECK_THROW(XMLDocument::openStream(f, {}, true), Exception); +} +BOOST_AUTO_TEST_SUITE_END()