Skip to content

Commit 64102b6

Browse files
committed
Handle hardened XML checks with path API
IB-8939 Signed-off-by: Raul Metsma <raul@metsma.ee>
1 parent e36175f commit 64102b6

3 files changed

Lines changed: 29 additions & 6 deletions

File tree

src/XMLDocument.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
#include <openssl/evp.h>
3636

37+
#include <fstream>
3738
#include <istream>
3839

3940
namespace digidoc {
@@ -308,9 +309,13 @@ struct XMLDocument: public unique_free_d<xmlFreeDoc>, public XMLNode
308309
d = {};
309310
}
310311

311-
XMLDocument(const std::string &path, const XMLName &n = {}) noexcept
312-
: XMLDocument(path.empty() ? nullptr : xmlParseFile(path.c_str()), n)
313-
{}
312+
XMLDocument(const std::string &path, const XMLName &n = {})
313+
{
314+
if(path.empty())
315+
return;
316+
if(std::ifstream f{path})
317+
*this = openStream(f, n);
318+
}
314319

315320
template <typename F>
316321
static XMLDocument open(F &&f, const XMLName &name = {}, bool hugeFile = false)

src/XmlConf.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,9 @@ XmlConf::Private::Private(Conf *self, const string &path, string schema)
124124
auto XmlConf::Private::loadDoc(const string &path) const
125125
{
126126
LIBXML_TEST_VERSION
127-
auto doc = XMLDocument(path, {"configuration"});
127+
XMLDocument doc;
128+
try { doc = XMLDocument(path, {"configuration"}); }
129+
catch(const Exception &) {}
128130
if(!doc)
129131
{
130132
WARN("Failed to parse configuration: %s", path.c_str());

test/libdigidocpp_boost.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -605,8 +605,8 @@ BOOST_AUTO_TEST_SUITE_END()
605605
BOOST_AUTO_TEST_SUITE(XMLTestSuite)
606606
BOOST_AUTO_TEST_CASE(XMLBomb)
607607
{
608-
BOOST_CHECK_EQUAL(XMLDocument("xml-bomb-attr.xml"), false);
609-
BOOST_CHECK_EQUAL(XMLDocument("xml-bomb-cont.xml"), false);
608+
BOOST_CHECK_THROW(XMLDocument("xml-bomb-attr.xml"), Exception);
609+
BOOST_CHECK_THROW(XMLDocument("xml-bomb-cont.xml"), Exception);
610610
if(std::fstream f{"xml-bomb-attr.xml"})
611611
BOOST_CHECK_THROW(XMLDocument::openStream(f), Exception);
612612
if(std::fstream f{"xml-bomb-cont.xml"})
@@ -655,6 +655,7 @@ BOOST_AUTO_TEST_CASE(XMLXXE)
655655
"]><root>&sentinel;</root>",
656656
};
657657

658+
size_t payloadIndex = 0;
658659
for(const auto &payload : payloads) {
659660
for(bool huge : {false, true}) {
660661
std::istringstream is{std::string(payload)};
@@ -664,6 +665,21 @@ BOOST_AUTO_TEST_CASE(XMLXXE)
664665
BOOST_CHECK(!text.contains("XXESENTINEL"));
665666
xmlFree(raw);
666667
}
668+
669+
const auto path = (fs::temp_directory_path() /
670+
("libdigidocpp-xxe-payload-" + std::to_string(payloadIndex++) + ".xml")).string();
671+
std::ofstream out{path, std::ofstream::binary};
672+
BOOST_REQUIRE(out.is_open());
673+
out << payload;
674+
out.close();
675+
BOOST_REQUIRE(out.good());
676+
677+
auto doc = XMLDocument(path);
678+
xmlChar *raw = xmlNodeGetContent(doc.d);
679+
std::string_view text = raw ? (const char*)raw : "";
680+
BOOST_CHECK(!text.contains("XXESENTINEL"));
681+
xmlFree(raw);
682+
fs::remove(path);
667683
}
668684
}
669685
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)