2015-04-13 04:09:02 -05:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
2015-03-26 09:49:07 -05:00
|
|
|
/*
|
2023-11-09 12:23:00 -06:00
|
|
|
* Copyright the Collabora Online contributors.
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MPL-2.0
|
|
|
|
*
|
2015-03-26 09:49:07 -05:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*/
|
|
|
|
|
2017-12-20 07:06:26 -06:00
|
|
|
#include <config.h>
|
loolwsd: include cleanup and organization
A source file (.cpp) must include its own header first.
This insures that the header is self-contained and
doesn't depend on arbitrary (and accidental) includes
before it to compile.
Furthermore, system headers should go next, followed by
C then C++ headers, then libraries (Poco, etc) and, finally,
project headers come last.
This makes sure that headers and included in the same dependency
order to avoid side-effects. For example, Poco should never rely on
anything from our project in the same way that a C header should
never rely on anything in C++, Poco, or project headers.
Also, includes ought to be sorted where possible, to improve
readability and avoid accidental duplicates (of which there
were a few).
Change-Id: I62cc1343e4a091d69195e37ed659dba20cfcb1ef
Reviewed-on: https://gerrit.libreoffice.org/25262
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2016-05-21 09:23:07 -05:00
|
|
|
|
2017-03-08 10:38:22 -06:00
|
|
|
#include "Protocol.hpp"
|
|
|
|
|
2015-04-14 09:50:38 -05:00
|
|
|
#include <cstring>
|
2015-04-27 13:09:27 -05:00
|
|
|
#include <map>
|
|
|
|
#include <string>
|
2024-01-05 01:16:13 -06:00
|
|
|
#include <string_view>
|
2015-03-26 09:49:07 -05:00
|
|
|
|
|
|
|
#define LOK_USE_UNSTABLE_API
|
|
|
|
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
|
|
|
|
|
2021-11-18 06:08:14 -06:00
|
|
|
namespace COOLProtocol
|
2015-03-26 09:49:07 -05:00
|
|
|
{
|
2016-02-23 02:22:18 -06:00
|
|
|
std::tuple<int, int, std::string> ParseVersion(const std::string& version)
|
2016-01-06 11:00:44 -06:00
|
|
|
{
|
2016-02-23 02:22:18 -06:00
|
|
|
int major = -1;
|
|
|
|
int minor = -1;
|
2016-01-06 11:00:44 -06:00
|
|
|
std::string patch;
|
|
|
|
|
2022-03-29 20:37:57 -05:00
|
|
|
StringVector firstTokens(StringVector::tokenize(version, '.'));
|
2019-11-08 07:50:33 -06:00
|
|
|
if (firstTokens.size() > 0)
|
2016-01-06 11:00:44 -06:00
|
|
|
{
|
|
|
|
major = std::stoi(firstTokens[0]);
|
|
|
|
|
2020-02-28 03:50:58 -06:00
|
|
|
StringVector secondTokens;
|
common: fix crash when the version string contains no dot character
==13901==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000904678 bp 0x7ffdb9e21580 sp 0x7ffdb9e21340 T0)
==13901==The signal is caused by a READ memory access.
==13901==Hint: address points to the zero page.
#0 0x904677 in LOOLProtocol::tokenize[abi:cxx11](char const*, unsigned long, char) common/Protocol.hpp:113:40
#1 0x898c52 in LOOLProtocol::tokenize(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char) common/Protocol.hpp:141:16
#2 0x18dc2d9 in LOOLProtocol::ParseVersion(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) common/Protocol.cpp:35:51
#3 0x1148824 in ClientSession::_handleInput(char const*, int) wsd/ClientSession.cpp:358:64
#4 0x18efcb8 in Session::handleMessage(bool, WSOpCode, std::vector<char, std::allocator<char> >&) common/Session.cpp:232:13
Next commit will add the actual simple fuzzer that found this.
Change-Id: I8623b4451a57390f6f84c11084c5a1120a11fcc5
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/89225
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
2020-02-21 08:36:28 -06:00
|
|
|
if (firstTokens.size() > 1)
|
|
|
|
{
|
2022-03-29 20:37:57 -05:00
|
|
|
secondTokens = StringVector::tokenize(firstTokens[1], '-');
|
common: fix crash when the version string contains no dot character
==13901==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000904678 bp 0x7ffdb9e21580 sp 0x7ffdb9e21340 T0)
==13901==The signal is caused by a READ memory access.
==13901==Hint: address points to the zero page.
#0 0x904677 in LOOLProtocol::tokenize[abi:cxx11](char const*, unsigned long, char) common/Protocol.hpp:113:40
#1 0x898c52 in LOOLProtocol::tokenize(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char) common/Protocol.hpp:141:16
#2 0x18dc2d9 in LOOLProtocol::ParseVersion(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) common/Protocol.cpp:35:51
#3 0x1148824 in ClientSession::_handleInput(char const*, int) wsd/ClientSession.cpp:358:64
#4 0x18efcb8 in Session::handleMessage(bool, WSOpCode, std::vector<char, std::allocator<char> >&) common/Session.cpp:232:13
Next commit will add the actual simple fuzzer that found this.
Change-Id: I8623b4451a57390f6f84c11084c5a1120a11fcc5
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/89225
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
2020-02-21 08:36:28 -06:00
|
|
|
}
|
|
|
|
if (secondTokens.size() > 0)
|
|
|
|
{
|
|
|
|
minor = std::stoi(secondTokens[0]);
|
|
|
|
}
|
2016-01-06 11:00:44 -06:00
|
|
|
|
2019-11-08 07:50:33 -06:00
|
|
|
if (secondTokens.size() > 1)
|
2016-01-06 11:00:44 -06:00
|
|
|
patch = secondTokens[1];
|
|
|
|
}
|
|
|
|
return std::make_tuple(major, minor, patch);
|
|
|
|
}
|
|
|
|
|
2023-06-09 14:26:05 -05:00
|
|
|
bool getTokenInteger(const std::string& token, const std::string_view name, int& value)
|
2015-03-26 09:49:07 -05:00
|
|
|
{
|
2017-01-30 19:43:27 -06:00
|
|
|
if (token.size() > (name.size() + 1) &&
|
|
|
|
token.compare(0, name.size(), name) == 0 &&
|
|
|
|
token[name.size()] == '=')
|
2015-03-26 09:49:07 -05:00
|
|
|
{
|
2017-01-30 19:43:27 -06:00
|
|
|
const char* str = token.data() + name.size() + 1;
|
|
|
|
char* endptr = nullptr;
|
|
|
|
value = strtol(str, &endptr, 10);
|
|
|
|
return (endptr > str);
|
2015-03-26 09:49:07 -05:00
|
|
|
}
|
2015-04-27 13:09:27 -05:00
|
|
|
|
2017-01-30 19:43:27 -06:00
|
|
|
return false;
|
2015-03-26 09:49:07 -05:00
|
|
|
}
|
|
|
|
|
2023-06-09 14:26:05 -05:00
|
|
|
bool getTokenUInt64(const std::string& token, const std::string_view name, uint64_t& value)
|
2017-01-04 06:36:13 -06:00
|
|
|
{
|
2017-01-30 19:43:27 -06:00
|
|
|
if (token.size() > (name.size() + 1) &&
|
|
|
|
token.compare(0, name.size(), name) == 0 &&
|
|
|
|
token[name.size()] == '=')
|
2017-01-04 06:36:13 -06:00
|
|
|
{
|
2017-01-30 19:43:27 -06:00
|
|
|
const char* str = token.data() + name.size() + 1;
|
|
|
|
char* endptr = nullptr;
|
|
|
|
value = strtoull(str, &endptr, 10);
|
|
|
|
return (endptr > str);
|
2017-01-04 06:36:13 -06:00
|
|
|
}
|
|
|
|
|
2017-01-30 19:43:27 -06:00
|
|
|
return false;
|
2017-01-04 06:36:13 -06:00
|
|
|
}
|
|
|
|
|
2023-06-09 14:26:05 -05:00
|
|
|
bool getTokenUInt32(const std::string& token, const std::string_view name, uint32_t& value)
|
2017-06-14 11:28:07 -05:00
|
|
|
{
|
|
|
|
if (token.size() > (name.size() + 1) &&
|
|
|
|
token.compare(0, name.size(), name) == 0 &&
|
|
|
|
token[name.size()] == '=')
|
|
|
|
{
|
|
|
|
const char* str = token.data() + name.size() + 1;
|
|
|
|
char* endptr = nullptr;
|
|
|
|
value = strtoul(str, &endptr, 10);
|
|
|
|
return (endptr > str);
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-06-09 14:26:05 -05:00
|
|
|
bool getTokenString(const std::string& token, const std::string_view name, std::string& value)
|
2015-03-26 09:49:07 -05:00
|
|
|
{
|
2018-02-07 12:30:45 -06:00
|
|
|
if (token.size() >= (name.size() + 1) &&
|
2017-01-30 19:43:27 -06:00
|
|
|
token.compare(0, name.size(), name) == 0 &&
|
|
|
|
token[name.size()] == '=')
|
2015-03-26 09:49:07 -05:00
|
|
|
{
|
2017-01-30 19:43:27 -06:00
|
|
|
value = token.substr(name.size() + 1);
|
|
|
|
return true;
|
2015-03-26 09:49:07 -05:00
|
|
|
}
|
2016-05-15 16:44:40 -05:00
|
|
|
|
2017-01-30 19:43:27 -06:00
|
|
|
return false;
|
2015-03-26 09:49:07 -05:00
|
|
|
}
|
|
|
|
|
2023-06-09 14:26:05 -05:00
|
|
|
bool getTokenKeyword(const std::string& token, const std::string_view name,
|
2017-01-30 19:43:27 -06:00
|
|
|
const std::map<std::string, int>& map, int& value)
|
2015-04-27 13:09:27 -05:00
|
|
|
{
|
2017-01-30 19:43:27 -06:00
|
|
|
std::string t;
|
|
|
|
if (getTokenString(token, name, t))
|
|
|
|
{
|
|
|
|
if (t[0] == '\'' && t[t.size() - 1] == '\'')
|
|
|
|
{
|
|
|
|
t = t.substr(1, t.size() - 2);
|
|
|
|
}
|
2015-04-27 13:09:27 -05:00
|
|
|
|
2017-01-30 19:43:27 -06:00
|
|
|
const auto p = map.find(t);
|
|
|
|
if (p != map.cend())
|
|
|
|
{
|
|
|
|
value = p->second;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2015-04-27 13:09:27 -05:00
|
|
|
|
2017-01-30 19:43:27 -06:00
|
|
|
return false;
|
2015-04-27 13:09:27 -05:00
|
|
|
}
|
|
|
|
|
2023-06-09 14:26:05 -05:00
|
|
|
bool getTokenInteger(const StringVector& tokens, const std::string_view name, int& value)
|
2016-04-20 08:44:12 -05:00
|
|
|
{
|
2019-11-08 07:50:33 -06:00
|
|
|
for (size_t i = 0; i < tokens.size(); i++)
|
2016-04-20 08:44:12 -05:00
|
|
|
{
|
|
|
|
if (getTokenInteger(tokens[i], name, value))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-06-09 14:26:05 -05:00
|
|
|
bool getTokenKeyword(const StringVector& tokens, const std::string_view name, const std::map<std::string, int>& map, int& value)
|
2016-04-20 08:44:12 -05:00
|
|
|
{
|
2019-11-08 07:50:33 -06:00
|
|
|
for (size_t i = 0; i < tokens.size(); i++)
|
2016-04-20 08:44:12 -05:00
|
|
|
{
|
|
|
|
if (getTokenKeyword(tokens[i], name, map, value))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-06-09 14:26:05 -05:00
|
|
|
bool getTokenStringFromMessage(const std::string& message, const std::string_view name, std::string& value)
|
2016-09-26 11:31:19 -05:00
|
|
|
{
|
2016-11-20 15:16:13 -06:00
|
|
|
if (message.size() > name.size() + 1)
|
|
|
|
{
|
2018-02-07 03:17:19 -06:00
|
|
|
size_t pos = message.find(name);
|
2016-11-20 15:16:13 -06:00
|
|
|
while (pos != std::string::npos)
|
|
|
|
{
|
2017-06-20 15:49:02 -05:00
|
|
|
bool spaceBefore = pos == 0 || message[pos-1] == ' ';
|
2018-02-07 03:17:19 -06:00
|
|
|
const size_t beg = pos + name.size();
|
2017-06-20 15:49:02 -05:00
|
|
|
if (spaceBefore && message[beg] == '=')
|
2016-11-20 15:16:13 -06:00
|
|
|
{
|
2018-02-07 03:17:19 -06:00
|
|
|
const size_t end = message.find_first_of(" \n", beg);
|
2016-11-20 15:16:13 -06:00
|
|
|
value = message.substr(beg + 1, end - beg - 1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
pos = message.find(name, pos + name.size());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2016-09-26 11:31:19 -05:00
|
|
|
}
|
|
|
|
|
2023-06-09 14:26:05 -05:00
|
|
|
bool getTokenKeywordFromMessage(const std::string& message, const std::string_view name, const std::map<std::string, int>& map, int& value)
|
2016-09-26 11:31:19 -05:00
|
|
|
{
|
2022-03-29 20:37:57 -05:00
|
|
|
return getTokenKeyword(StringVector::tokenize(message), name, map, value);
|
2016-09-26 11:31:19 -05:00
|
|
|
}
|
2015-03-26 09:49:07 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|