fix(client): validate LSYN payload length before parsing remote layouts
fixes: #10107 A malicious server can send a language synchronisation (LSYN) message with a single-byte payload. size()-2 then underflows to SIZE_MAX and substr(2, 2) throws std::out_of_range, terminating the client. Reject odd-length payloads before mutating state, mirroring the existing DSOP even-length check; an empty payload is still treated as a normal clear.
This commit is contained in:
parent
fac2f540c5
commit
adb4f89453
3 changed files with 26 additions and 5 deletions
|
|
@ -35,13 +35,16 @@ KeyboardLayoutManager::KeyboardLayoutManager(const std::vector<std::string> &loc
|
||||||
|
|
||||||
void KeyboardLayoutManager::setRemoteLayouts(const std::string_view &remoteLayouts)
|
void KeyboardLayoutManager::setRemoteLayouts(const std::string_view &remoteLayouts)
|
||||||
{
|
{
|
||||||
|
if (!remoteLayouts.empty() && remoteLayouts.size() % 2 != 0) {
|
||||||
|
LOG_ERR("remote layouts are the incorrect size, can not process them");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_remoteLayouts.clear();
|
m_remoteLayouts.clear();
|
||||||
if (!remoteLayouts.empty()) {
|
for (size_t i = 0; i + 2 <= remoteLayouts.size(); i += 2) {
|
||||||
for (size_t i = 0; i <= remoteLayouts.size() - 2; i += 2) {
|
|
||||||
auto rLangs = remoteLayouts.substr(i, 2);
|
auto rLangs = remoteLayouts.substr(i, 2);
|
||||||
m_remoteLayouts.emplace_back(rLangs);
|
m_remoteLayouts.emplace_back(rLangs);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
LOG_INFO("remote layouts: %s", vectorToString(m_remoteLayouts, ", ").c_str());
|
LOG_INFO("remote layouts: %s", vectorToString(m_remoteLayouts, ", ").c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,22 @@ void KeyboardLayoutManagerTests::remoteLayouts()
|
||||||
QVERIFY(manager.getRemoteLayouts().empty());
|
QVERIFY(manager.getRemoteLayouts().empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KeyboardLayoutManagerTests::remoteLayouts_tooShort_returnsEmpty()
|
||||||
|
{
|
||||||
|
deskflow::KeyboardLayoutManager manager({"ru", "en", "uk"});
|
||||||
|
|
||||||
|
manager.setRemoteLayouts("a");
|
||||||
|
QVERIFY(manager.getRemoteLayouts().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardLayoutManagerTests::remoteLayouts_oddLength_returnsEmpty()
|
||||||
|
{
|
||||||
|
deskflow::KeyboardLayoutManager manager({"ru", "en", "uk"});
|
||||||
|
|
||||||
|
manager.setRemoteLayouts("rue");
|
||||||
|
QVERIFY(manager.getRemoteLayouts().empty());
|
||||||
|
}
|
||||||
|
|
||||||
void KeyboardLayoutManagerTests::localLayout()
|
void KeyboardLayoutManagerTests::localLayout()
|
||||||
{
|
{
|
||||||
std::vector<std::string> localLayouts = {"ru", "en", "uk"};
|
std::vector<std::string> localLayouts = {"ru", "en", "uk"};
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ private Q_SLOTS:
|
||||||
void initTestCase();
|
void initTestCase();
|
||||||
// Test are run in order top to bottom
|
// Test are run in order top to bottom
|
||||||
void remoteLayouts();
|
void remoteLayouts();
|
||||||
|
void remoteLayouts_tooShort_returnsEmpty();
|
||||||
|
void remoteLayouts_oddLength_returnsEmpty();
|
||||||
void localLayout();
|
void localLayout();
|
||||||
void missedLayout();
|
void missedLayout();
|
||||||
void serializeLocalLayouts();
|
void serializeLocalLayouts();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue