From 37062207bf02a85cd6dada11f2832ab3aa9b790a Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Tue, 11 Jun 2024 12:53:34 +0200 Subject: [PATCH] cool#9219 clipboard: only accept downloaded data in own format Signed-off-by: Miklos Vajna Change-Id: If11229b713174a6c3d1a9794281858d6a8f64294 --- common/Clipboard.hpp | 30 ++++++++++++++++++++++++++++++ test/HttpWhiteBoxTests.cpp | 26 ++++++++++++++++++++++++++ wsd/ClientSession.cpp | 15 ++++++++++++--- 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/common/Clipboard.hpp b/common/Clipboard.hpp index 625605335..03da2c9eb 100644 --- a/common/Clipboard.hpp +++ b/common/Clipboard.hpp @@ -32,6 +32,36 @@ struct ClipboardData { } + /// Determines if inStream is a list of mimetype-length-bytes tuples, as expected. + static bool isOwnFormat(std::istream& inStream) + { + if (inStream.eof()) + { + return false; + } + + std::string mime, hexLen; + std::getline(inStream, mime, '\n'); + if (mime.empty()) + { + return false; + } + + std::getline(inStream, hexLen, '\n'); + if (hexLen.empty()) + { + return false; + } + + uint64_t len = strtoll(hexLen.c_str(), nullptr, 16); + if (len == 0) + { + return false; + } + + return true; + } + void read(std::istream& inStream) { while (!inStream.eof()) diff --git a/test/HttpWhiteBoxTests.cpp b/test/HttpWhiteBoxTests.cpp index b565134a9..389326566 100644 --- a/test/HttpWhiteBoxTests.cpp +++ b/test/HttpWhiteBoxTests.cpp @@ -13,6 +13,7 @@ #include +#include #include #include @@ -36,6 +37,7 @@ class HttpWhiteBoxTests : public CPPUNIT_NS::TestFixture CPPUNIT_TEST(testRequestParserValidComplete); CPPUNIT_TEST(testRequestParserValidIncomplete); + CPPUNIT_TEST(testClipboardIsOwnFormat); CPPUNIT_TEST_SUITE_END(); @@ -46,6 +48,7 @@ class HttpWhiteBoxTests : public CPPUNIT_NS::TestFixture void testHeader(); void testRequestParserValidComplete(); void testRequestParserValidIncomplete(); + void testClipboardIsOwnFormat(); }; void HttpWhiteBoxTests::testStatusLineParserValidComplete() @@ -226,6 +229,29 @@ void HttpWhiteBoxTests::testRequestParserValidIncomplete() LOK_ASSERT_EQUAL(expHost, req.header().get("Host")); } +void HttpWhiteBoxTests::testClipboardIsOwnFormat() +{ + constexpr auto testname = __func__; + { + std::string body = R"x(application/x-openoffice-embed-source-xml;windows_formatname="Star Embed Source (XML)" +1def +PK)x"; + std::istringstream stream(body); + + LOK_ASSERT_EQUAL(ClipboardData::isOwnFormat(stream), true); + } + { + std::string body = R"( + +)"; + std::istringstream stream(body); + + // This is expected to fail: format is mimetype-length-bytes tuples and here the second line + // is not a hex size. + LOK_ASSERT_EQUAL(ClipboardData::isOwnFormat(stream), false); + } +} + CPPUNIT_TEST_SUITE_REGISTRATION(HttpWhiteBoxTests); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp index 93eee469f..761d8e19d 100644 --- a/wsd/ClientSession.cpp +++ b/wsd/ClientSession.cpp @@ -343,9 +343,18 @@ void ClientSession::handleClipboardRequest(DocumentBroker::ClipboardRequest } std::string body = httpResponse->getBody(); - docBroker->forwardToChild(client_from_this(), "setclipboard\n" + body, - true); - docBroker->forwardToChild(client_from_this(), "uno " + commandName); + std::istringstream stream(body); + if (ClipboardData::isOwnFormat(stream)) + { + docBroker->forwardToChild(client_from_this(), "setclipboard\n" + body, + true); + docBroker->forwardToChild(client_from_this(), "uno " + commandName); + } + else + { + LOG_ERR("Clipboard download: unexpected data format"); + return; + } }; std::shared_ptr httpSession = http::Session::create(url);