2016-06-22 08:57:01 -05:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* 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>
|
2017-03-08 10:38:22 -06:00
|
|
|
|
2016-06-22 08:57:01 -05:00
|
|
|
#include <cassert>
|
|
|
|
#include <iostream>
|
2016-12-07 15:32:08 -06:00
|
|
|
#include <random>
|
2016-06-22 08:57:01 -05:00
|
|
|
|
2017-12-20 07:06:26 -06:00
|
|
|
#include <Common.hpp>
|
|
|
|
#include <IoUtil.hpp>
|
|
|
|
#include <Protocol.hpp>
|
2016-11-10 02:47:25 -06:00
|
|
|
#include <LOOLWebSocket.hpp>
|
2017-12-20 07:06:26 -06:00
|
|
|
#include <Unit.hpp>
|
|
|
|
#include <Util.hpp>
|
2016-06-22 08:57:01 -05:00
|
|
|
|
|
|
|
#include <Poco/Timestamp.h>
|
|
|
|
#include <Poco/StringTokenizer.h>
|
2016-12-07 15:32:08 -06:00
|
|
|
#include <Poco/Net/HTTPServerRequest.h>
|
2016-06-22 08:57:01 -05:00
|
|
|
|
|
|
|
// Inside the WSD process
|
|
|
|
class UnitFuzz : public UnitWSD
|
|
|
|
{
|
2016-12-07 15:32:08 -06:00
|
|
|
std::random_device _rd;
|
|
|
|
std::mt19937 _mt;
|
|
|
|
std::uniform_int_distribution<> _dist;
|
2016-06-22 08:57:01 -05:00
|
|
|
public:
|
2016-12-07 15:32:08 -06:00
|
|
|
UnitFuzz() :
|
|
|
|
_mt(_rd()),
|
|
|
|
_dist(0, 1000)
|
2016-06-22 08:57:01 -05:00
|
|
|
{
|
2016-12-07 15:32:08 -06:00
|
|
|
std::cerr << "\n\nYour WSD process is being randomly fuzzed\n\n\n";
|
2016-06-22 08:57:01 -05:00
|
|
|
setHasKitHooks();
|
2016-12-07 15:32:08 -06:00
|
|
|
setTimeout(3600 * 1000); /* one hour */
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string corruptString(const std::string &str)
|
|
|
|
{
|
|
|
|
std::string ret;
|
2017-03-11 13:42:50 -06:00
|
|
|
for (auto it = str.begin(); it != str.end(); ++it)
|
2016-12-07 15:32:08 -06:00
|
|
|
{
|
|
|
|
int op = _dist(_mt);
|
|
|
|
if (op < 10) {
|
|
|
|
switch (op) {
|
|
|
|
case 0:
|
|
|
|
ret += 0xff;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
case 3:
|
|
|
|
ret += *it & 0x80;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret += *it ^ _dist(_mt);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Note: Fuzzers are fragile and their performance is rather
|
|
|
|
* sensitive. Please avoid random code tweaking in this method.
|
|
|
|
*/
|
2016-12-12 18:53:58 -06:00
|
|
|
virtual bool filterSessionInput(Session *, const char *buffer,
|
2016-12-07 15:32:08 -06:00
|
|
|
int length,
|
|
|
|
std::unique_ptr< std::vector<char> > &replace) override
|
|
|
|
{
|
|
|
|
// Avoid fuzzing most messages
|
|
|
|
if (_dist(_mt) < 875)
|
|
|
|
return false;
|
|
|
|
|
2018-02-07 03:17:42 -06:00
|
|
|
std::unique_ptr<std::vector<char>> fuzzed(new std::vector<char>());
|
2016-12-07 15:32:08 -06:00
|
|
|
fuzzed->assign(buffer, buffer+length);
|
|
|
|
|
|
|
|
int resize = _dist(_mt);
|
|
|
|
if (resize < 50) { // truncate
|
|
|
|
size_t shrink = (fuzzed->size() * _dist(_mt))/1000;
|
|
|
|
fuzzed->resize(shrink);
|
|
|
|
|
|
|
|
} else if (resize < 200) {
|
|
|
|
bool prepend = resize < 100;
|
|
|
|
bool middle = resize < 150;
|
|
|
|
size_t count = 1 + _dist(_mt)/100;
|
|
|
|
for (size_t i = 0; i < count; ++i)
|
|
|
|
{
|
|
|
|
char c = (_dist(_mt) * 256 / 1000);
|
|
|
|
if (prepend)
|
|
|
|
fuzzed->insert(fuzzed->begin(), c);
|
|
|
|
else if (middle)
|
|
|
|
fuzzed->insert(fuzzed->begin() + fuzzed->size()/2, c);
|
|
|
|
else
|
|
|
|
fuzzed->push_back(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int numCorrupt = (_dist(_mt) / 100) - 75;
|
|
|
|
for (int i = 0; i < numCorrupt; ++i)
|
|
|
|
{
|
|
|
|
size_t offset = (_dist(_mt) * fuzzed->size() - 1) / 1000;
|
|
|
|
char c = (*fuzzed)[offset];
|
|
|
|
int change = _dist(_mt);
|
|
|
|
if (change < 256)
|
|
|
|
c ^= change;
|
|
|
|
else if (c >= '0' && c <= '9')
|
|
|
|
c = '0' + (change - 256)/100;
|
|
|
|
else
|
|
|
|
c |= 0x80;
|
|
|
|
}
|
|
|
|
|
2018-12-18 02:14:43 -06:00
|
|
|
replace = std::move(fuzzed);
|
2016-12-07 15:32:08 -06:00
|
|
|
|
|
|
|
return true;
|
2016-06-22 08:57:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool filterHandleRequest(
|
|
|
|
TestRequest /* type */,
|
2017-05-05 05:51:43 -05:00
|
|
|
SocketDisposition & /* disposition */,
|
2017-03-16 13:32:12 -05:00
|
|
|
WebSocketHandler & /* socket */) override
|
2016-06-22 08:57:01 -05:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Inside the forkit & kit processes
|
|
|
|
class UnitKitFuzz : public UnitKit
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
UnitKitFuzz()
|
|
|
|
{
|
2016-12-07 15:32:08 -06:00
|
|
|
std::cerr << "\n\nYour KIT process has fuzzing hooks\n\n\n";
|
|
|
|
setTimeout(3600 * 1000); /* one hour */
|
2016-06-22 08:57:01 -05:00
|
|
|
}
|
2018-11-07 17:00:32 -06:00
|
|
|
virtual bool filterKitMessage(WebSocketHandler *, std::string & /* message */) override
|
2016-06-22 08:57:01 -05:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
UnitBase *unit_create_wsd(void)
|
|
|
|
{
|
|
|
|
return new UnitFuzz();
|
|
|
|
}
|
|
|
|
|
|
|
|
UnitBase *unit_create_kit(void)
|
|
|
|
{
|
|
|
|
return new UnitKitFuzz();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|