wsd: fix reading past the end of the clipboard in postProcessCopyPayload()
Add a way to search with an offset in findInVector() and then we can avoid strstr() which assumes a null-terminated input, which may not be the case. READ of size 55 at 0x606000068a56 thread T8 (docbroker_001) #0 0x55d0d6718a5a in StrstrCheck(void*, char*, char const*, char const*) /home/abuild/rpmbuild/BUILD/llvm-15.0.7.src/build/../projects/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:652:5 #1 0x55d0d6718882 in __interceptor_strstr /home/abuild/rpmbuild/BUILD/llvm-15.0.7.src/build/../projects/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:669:5 #2 0x55d0d71872c9 in ClientSession::postProcessCopyPayload(std::shared_ptr<Message> const&)::$_4::operator()(std::vector<char, std::allocator<char>>&) const /home/vmiklos/git/collaboraonline/online-23.05-san/wsd/ClientSession.cpp:1631:31 During unit-uno-command. Signed-off-by: Miklos Vajna <vmiklos@collabora.com> Change-Id: Id42669d912bab4746d9f7d99a192c4c3f1d175f7pull/8072/head
parent
ee708edf0d
commit
33310613cd
|
@ -978,16 +978,16 @@ namespace Util
|
|||
return http_time;
|
||||
}
|
||||
|
||||
std::size_t findInVector(const std::vector<char>& tokens, const char *cstring)
|
||||
std::size_t findInVector(const std::vector<char>& tokens, const char *cstring, std::size_t offset)
|
||||
{
|
||||
assert(cstring);
|
||||
for (std::size_t i = 0; i < tokens.size(); ++i)
|
||||
for (std::size_t i = 0; i < tokens.size() - offset; ++i)
|
||||
{
|
||||
std::size_t j;
|
||||
for (j = 0; i + j < tokens.size() && cstring[j] != '\0' && tokens[i + j] == cstring[j]; ++j)
|
||||
for (j = 0; i + j < tokens.size() - offset && cstring[j] != '\0' && tokens[i + j + offset] == cstring[j]; ++j)
|
||||
;
|
||||
if (cstring[j] == '\0')
|
||||
return i;
|
||||
return i + offset;
|
||||
}
|
||||
return std::string::npos;
|
||||
}
|
||||
|
|
|
@ -516,7 +516,7 @@ namespace Util
|
|||
return oss.str();
|
||||
}
|
||||
|
||||
size_t findInVector(const std::vector<char>& tokens, const char *cstring);
|
||||
size_t findInVector(const std::vector<char>& tokens, const char *cstring, std::size_t offset = 0);
|
||||
|
||||
/// Trim spaces from the left. Just spaces.
|
||||
inline std::string& ltrim(std::string& s)
|
||||
|
|
|
@ -70,6 +70,7 @@ class WhiteBoxTests : public CPPUNIT_NS::TestFixture
|
|||
#if ENABLE_DEBUG
|
||||
CPPUNIT_TEST(testUtf8);
|
||||
#endif
|
||||
CPPUNIT_TEST(testFindInVector);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
void testCOOLProtocolFunctions();
|
||||
|
@ -100,6 +101,7 @@ class WhiteBoxTests : public CPPUNIT_NS::TestFixture
|
|||
void testBytesToHex();
|
||||
void testJsonUtilEscapeJSONValue();
|
||||
void testUtf8();
|
||||
void testFindInVector();
|
||||
};
|
||||
|
||||
void WhiteBoxTests::testCOOLProtocolFunctions()
|
||||
|
@ -1384,6 +1386,28 @@ void WhiteBoxTests::testUtf8()
|
|||
#endif
|
||||
}
|
||||
|
||||
void WhiteBoxTests::testFindInVector()
|
||||
{
|
||||
constexpr auto testname = __func__;
|
||||
std::string s("fooBarfooBaz");
|
||||
std::vector<char> v(s.begin(), s.end());
|
||||
|
||||
// Normal case, we find the first "foo".
|
||||
std::size_t ret = Util::findInVector(v, "foo");
|
||||
std::size_t expected = 0;
|
||||
LOK_ASSERT_EQUAL(expected, ret);
|
||||
|
||||
// Offset, so we find the second "foo".
|
||||
ret = Util::findInVector(v, "foo", 1);
|
||||
expected = 6;
|
||||
LOK_ASSERT_EQUAL(expected, ret);
|
||||
|
||||
// Negative testing.
|
||||
ret = Util::findInVector(v, "blah");
|
||||
expected = std::string::npos;
|
||||
LOK_ASSERT_EQUAL(expected, ret);
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(WhiteBoxTests);
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
|
|
@ -1627,27 +1627,25 @@ void ClientSession::postProcessCopyPayload(const std::shared_ptr<Message>& paylo
|
|||
|
||||
// New-style: <div> inside <body>, that is not sanitized by Chrome.
|
||||
payload->rewriteDataBody([=](std::vector<char>& data) {
|
||||
const char* pos = strstr(data.data(), "<body");
|
||||
if (pos)
|
||||
std::size_t pos = Util::findInVector(data, "<body");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
pos = strstr(pos, ">");
|
||||
pos = Util::findInVector(data, ">", pos);
|
||||
}
|
||||
|
||||
if (pos)
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
const std::string meta = getClipboardURI();
|
||||
LOG_TRC("Inject clipboard cool origin of '" << meta << "'");
|
||||
std::string origin = "<div id=\"meta-origin\" data-coolorigin=\"" + meta + "\">\n";
|
||||
size_t offset = pos - data.data();
|
||||
data.insert(data.begin() + offset + strlen(">"), origin.begin(), origin.end());
|
||||
data.insert(data.begin() + pos + strlen(">"), origin.begin(), origin.end());
|
||||
|
||||
const char* end = "</body>";
|
||||
pos = strstr(data.data(), end);
|
||||
if (pos)
|
||||
pos = Util::findInVector(data, end);
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
origin = "</div>";
|
||||
offset = pos - data.data();
|
||||
data.insert(data.begin() + offset, origin.begin(), origin.end());
|
||||
data.insert(data.begin() + pos, origin.begin(), origin.end());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue