Commit 870c84a3 authored by mbarbella's avatar mbarbella Committed by Commit bot

Combine traits for IPC mutation and generation fuzzing plus other refactoring.

R=inferno@chromium.org,tsepez@chromium.org
BUG=450268

Review URL: https://codereview.chromium.org/1000373004

Cr-Commit-Position: refs/heads/master@{#321369}
parent 13cf4d07
...@@ -8,13 +8,12 @@ ...@@ -8,13 +8,12 @@
}, },
'targets': [ 'targets': [
{ {
'target_name': 'ipc_fuzzer', 'target_name': 'ipc_fuzzer_all',
'type': 'none', 'type': 'none',
'dependencies': [ 'dependencies': [
'dump/dump.gyp:ipc_message_dump', 'dump/dump.gyp:ipc_message_dump',
'ipclist/ipclist.gyp:ipclist', 'ipclist/ipclist.gyp:ipclist',
'mutate/mutate.gyp:ipc_fuzzer_mutate', 'mutate/mutate.gyp:ipc_fuzzer',
'mutate/mutate.gyp:ipc_fuzzer_generate',
'mutate/mutate.gyp:ipc_message_util', 'mutate/mutate.gyp:ipc_message_util',
'replay/replay.gyp:ipc_fuzzer_replay', 'replay/replay.gyp:ipc_fuzzer_replay',
], ],
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef TOOLS_IPC_FUZZER_MUTATE_FUZZER_H_
#define TOOLS_IPC_FUZZER_MUTATE_FUZZER_H_
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/strings/string_util.h"
#include "ipc/ipc_message.h"
namespace ipc_fuzzer {
// Interface implemented by those who generate basic types. The types all
// correspond to the types which a pickle from base/pickle.h can pickle,
// plus the floating point types.
class Fuzzer {
public:
// Functions for various data types.
virtual void FuzzBool(bool* value) = 0;
virtual void FuzzInt(int* value) = 0;
virtual void FuzzLong(long* value) = 0;
virtual void FuzzSize(size_t* value) = 0;
virtual void FuzzUChar(unsigned char* value) = 0;
virtual void FuzzWChar(wchar_t* value) = 0;
virtual void FuzzUInt16(uint16* value) = 0;
virtual void FuzzUInt32(uint32* value) = 0;
virtual void FuzzInt64(int64* value) = 0;
virtual void FuzzUInt64(uint64* value) = 0;
virtual void FuzzFloat(float* value) = 0;
virtual void FuzzDouble(double *value) = 0;
virtual void FuzzString(std::string* value) = 0;
virtual void FuzzString16(base::string16* value) = 0;
virtual void FuzzData(char* data, int length) = 0;
virtual void FuzzBytes(void* data, int data_len) = 0;
// Used to determine if a completely new value should be generated for
// certain types instead of attempting to modify the existing one.
virtual bool ShouldGenerate();
};
class NoOpFuzzer : public Fuzzer {
public:
NoOpFuzzer() {}
virtual ~NoOpFuzzer() {}
void FuzzBool(bool* value) override {}
void FuzzInt(int* value) override {}
void FuzzLong(long* value) override {}
void FuzzSize(size_t* value) override {}
void FuzzUChar(unsigned char* value) override {}
void FuzzWChar(wchar_t* value) override {}
void FuzzUInt16(uint16* value) override {}
void FuzzUInt32(uint32* value) override {}
void FuzzInt64(int64* value) override {}
void FuzzUInt64(uint64* value) override {}
void FuzzFloat(float* value) override {}
void FuzzDouble(double* value) override {}
void FuzzString(std::string* value) override {}
void FuzzString16(base::string16* value) override {}
void FuzzData(char* data, int length) override {}
void FuzzBytes(void* data, int data_len) override {}
};
typedef IPC::Message* (*FuzzerFunction)(IPC::Message*, Fuzzer*);
// Used for mutating messages. Once populated, the map associates a message ID
// with a FuzzerFunction used for mutation of that message type.
typedef base::hash_map<uint32, FuzzerFunction> FuzzerFunctionMap;
void PopulateFuzzerFunctionMap(FuzzerFunctionMap* map);
// Used for generating new messages. Once populated, the vector contains
// FuzzerFunctions for all message types that we know how to generate.
typedef std::vector<FuzzerFunction> FuzzerFunctionVector;
void PopulateFuzzerFunctionVector(FuzzerFunctionVector* function_vector);
// Since IPC::Message can be serialized, we also track a global function vector
// to handle generation of new messages while fuzzing.
extern FuzzerFunctionVector g_function_vector;
} // namespace ipc_fuzzer
#endif // TOOLS_IPC_FUZZER_MUTATE_FUZZER_H_
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <iostream>
#include <set>
#include <vector>
#include "base/command_line.h"
#include "base/strings/string_split.h"
#include "ipc/ipc_message_macros.h"
#include "tools/ipc_fuzzer/message_lib/message_file.h"
#include "tools/ipc_fuzzer/mutate/fuzzer.h"
#include "tools/ipc_fuzzer/mutate/generator.h"
#include "tools/ipc_fuzzer/mutate/mutator.h"
#include "tools/ipc_fuzzer/mutate/rand_util.h"
namespace ipc_fuzzer {
namespace {
// TODO(mbarbella): Check to see if this value is actually reasonable.
const int kFrequency = 23;
const char kCountSwitch[] = "count";
const char kCountSwitchHelp[] =
"Number of messages to generate (generator).";
const char kFrequencySwitch[] = "frequency";
const char kFrequencySwitchHelp[] =
"Probability of mutation; tweak every 1/|q| times (mutator).";
const char kFuzzerNameSwitch[] = "fuzzer-name";
const char kFuzzerNameSwitchHelp[] =
"Select generator, mutator, or no-op fuzzer. Default: generator";
const char kHelpSwitch[] = "help";
const char kHelpSwitchHelp[] =
"Show this message.";
const char kPermuteSwitch[] = "permute";
const char kPermuteSwitchHelp[] =
"Randomly shuffle the order of all messages (mutator).";
const char kTypeListSwitch[] = "type-list";
const char kTypeListSwitchHelp[] =
"Explicit list of the only message-ids to mutate (mutator).";
void usage() {
std::cerr << "Mutate messages from an exiting message file.\n";
std::cerr << "Usage:\n"
<< " ipc_fuzzer"
<< " [--" << kCountSwitch << "=c]"
<< " [--" << kFrequencySwitch << "=q]"
<< " [--" << kFuzzerNameSwitch << "=f]"
<< " [--" << kHelpSwitch << "]"
<< " [--" << kTypeListSwitch << "=x,y,z...]"
<< " [--" << kPermuteSwitch << "]"
<< " [infile (mutation only)] outfile\n";
std::cerr
<< " --" << kCountSwitch << " - " << kCountSwitchHelp << "\n"
<< " --" << kFrequencySwitch << " - " << kFrequencySwitchHelp << "\n"
<< " --" << kFuzzerNameSwitch << " - " << kFuzzerNameSwitchHelp << "\n"
<< " --" << kHelpSwitch << " - " << kHelpSwitchHelp << "\n"
<< " --" << kTypeListSwitch << " - " << kTypeListSwitchHelp << "\n"
<< " --" << kPermuteSwitch << " - " << kPermuteSwitchHelp << "\n";
}
} // namespace
class FuzzerFactory {
public:
static Fuzzer *Create(const std::string& name, int frequency) {
if (name == "default")
return new Generator();
if (name == "generate")
return new Generator();
if (name == "mutate")
return new Mutator(frequency);
if (name == "no-op")
return new NoOpFuzzer();
std::cerr << "No such fuzzer: " << name << "\n";
return 0;
}
};
static IPC::Message* RewriteMessage(
IPC::Message* message,
Fuzzer* fuzzer,
FuzzerFunctionMap* map) {
FuzzerFunctionMap::iterator it = map->find(message->type());
if (it == map->end()) {
// This usually indicates a missing message file in all_messages.h, or
// that the message dump file is taken from a different revision of
// chromium from this executable.
std::cerr << "Unknown message type: ["
<< IPC_MESSAGE_ID_CLASS(message->type()) << ", "
<< IPC_MESSAGE_ID_LINE(message->type()) << "].\n";
return 0;
}
return (*it->second)(message, fuzzer);
}
int Generate(base::CommandLine* cmd, Fuzzer* fuzzer) {
base::CommandLine::StringVector args = cmd->GetArgs();
if (args.size() != 1) {
usage();
return EXIT_FAILURE;
}
base::FilePath::StringType output_file_name = args[0];
int message_count = 1000;
if (cmd->HasSwitch(kCountSwitch))
message_count = atoi(cmd->GetSwitchValueASCII(kCountSwitch).c_str());
MessageVector message_vector;
int bad_count = 0;
if (message_count < 0) {
// Enumerate them all.
for (size_t i = 0; i < g_function_vector.size(); ++i) {
if (IPC::Message* new_message = (*g_function_vector[i])(NULL, fuzzer))
message_vector.push_back(new_message);
else
bad_count += 1;
}
} else {
// Fuzz a random batch.
for (int i = 0; i < message_count; ++i) {
size_t index = RandInRange(g_function_vector.size());
if (IPC::Message* new_message = (*g_function_vector[index])(NULL, fuzzer))
message_vector.push_back(new_message);
else
bad_count += 1;
}
}
std::cerr << "Failed to generate " << bad_count << " messages.\n";
if (!MessageFile::Write(base::FilePath(output_file_name), message_vector))
return EXIT_FAILURE;
return EXIT_SUCCESS;
}
int Mutate(base::CommandLine* cmd, Fuzzer* fuzzer) {
base::CommandLine::StringVector args = cmd->GetArgs();
if (args.size() != 2) {
usage();
return EXIT_FAILURE;
}
base::FilePath::StringType input_file_name = args[0];
base::FilePath::StringType output_file_name = args[1];
bool permute = cmd->HasSwitch(kPermuteSwitch);
std::string type_string_list = cmd->GetSwitchValueASCII(kTypeListSwitch);
std::vector<std::string> type_string_vector;
base::SplitString(type_string_list, ',', &type_string_vector);
std::set<uint32> type_set;
for (size_t i = 0; i < type_string_vector.size(); ++i) {
type_set.insert(atoi(type_string_vector[i].c_str()));
}
FuzzerFunctionMap fuzz_function_map;
PopulateFuzzerFunctionMap(&fuzz_function_map);
MessageVector message_vector;
if (!MessageFile::Read(base::FilePath(input_file_name), &message_vector))
return EXIT_FAILURE;
for (size_t i = 0; i < message_vector.size(); ++i) {
IPC::Message* msg = message_vector[i];
// If an explicit type set is specified, make sure we should be mutating
// this message type on this run.
if (!type_set.empty() && type_set.end() == std::find(
type_set.begin(), type_set.end(), msg->type())) {
continue;
}
IPC::Message* new_message = RewriteMessage(msg, fuzzer, &fuzz_function_map);
if (new_message) {
IPC::Message* old_message = message_vector[i];
delete old_message;
message_vector[i] = new_message;
}
}
if (permute) {
std::random_shuffle(message_vector.begin(), message_vector.end(),
RandInRange);
}
if (!MessageFile::Write(base::FilePath(output_file_name), message_vector))
return EXIT_FAILURE;
return EXIT_SUCCESS;
}
int FuzzerMain(int argc, char** argv) {
base::CommandLine::Init(argc, argv);
base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
base::CommandLine::StringVector args = cmd->GetArgs();
if (args.size() == 0 || args.size() > 2 || cmd->HasSwitch(kHelpSwitch)) {
usage();
return EXIT_FAILURE;
}
InitRand();
PopulateFuzzerFunctionVector(&g_function_vector);
std::cerr << "Counted " << g_function_vector.size()
<< " distinct messages present in chrome.\n";
std::string fuzzer_name = "default";
if (cmd->HasSwitch(kFuzzerNameSwitch))
fuzzer_name = cmd->GetSwitchValueASCII(kFuzzerNameSwitch);
int frequency = kFrequency;
if (cmd->HasSwitch(kFrequencySwitch))
frequency = atoi(cmd->GetSwitchValueASCII(kFrequencySwitch).c_str());
Fuzzer* fuzzer = FuzzerFactory::Create(fuzzer_name, frequency);
if (!fuzzer)
return EXIT_FAILURE;
int result;
base::FilePath::StringType output_file_name;
if (fuzzer_name == "default" || fuzzer_name == "generate") {
result = Generate(cmd, fuzzer);
} else {
result = Mutate(cmd, fuzzer);
}
return result;
}
} // namespace ipc_fuzzer
int main(int argc, char** argv) {
return ipc_fuzzer::FuzzerMain(argc, argv);
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <string>
#include "base/basictypes.h"
#include "base/strings/string_util.h"
#include "tools/ipc_fuzzer/mutate/generator.h"
#include "tools/ipc_fuzzer/mutate/rand_util.h"
namespace ipc_fuzzer {
template <typename T>
void GenerateIntegralType(T* value) {
switch (RandInRange(16)) {
case 0:
*value = static_cast<T>(0);
break;
case 1:
*value = static_cast<T>(1);
break;
case 2:
*value = static_cast<T>(-1);
break;
case 3:
*value = static_cast<T>(2);
break;
default:
*value = static_cast<T>(RandU64());
break;
}
}
template <typename T>
void GenerateFloatingType(T* value) {
*value = RandDouble();
}
template <typename T>
void GenerateStringType(T* value) {
T temp_string;
size_t length = RandInRange(300);
for (size_t i = 0; i < length; ++i)
temp_string += RandInRange(256);
*value = temp_string;
}
void Generator::FuzzBool(bool* value) {
*value = RandInRange(2) ? true: false;
}
void Generator::FuzzInt(int* value) {
GenerateIntegralType<int>(value);
}
void Generator::FuzzLong(long* value) {
GenerateIntegralType<long>(value);
}
void Generator::FuzzSize(size_t* value) {
GenerateIntegralType<size_t>(value);
}
void Generator::FuzzUChar(unsigned char* value) {
GenerateIntegralType<unsigned char>(value);
}
void Generator::FuzzWChar(wchar_t* value) {
GenerateIntegralType<wchar_t>(value);
}
void Generator::FuzzUInt16(uint16* value) {
GenerateIntegralType<uint16>(value);
}
void Generator::FuzzUInt32(uint32* value) {
GenerateIntegralType<uint32>(value);
}
void Generator::FuzzInt64(int64* value) {
GenerateIntegralType<int64>(value);
}
void Generator::FuzzUInt64(uint64* value) {
GenerateIntegralType<uint64>(value);
}
void Generator::FuzzFloat(float* value) {
GenerateFloatingType<float>(value);
}
void Generator::FuzzDouble(double* value) {
GenerateFloatingType<double>(value);
}
void Generator::FuzzString(std::string* value) {
GenerateStringType<std::string>(value);
}
void Generator::FuzzString16(base::string16* value) {
GenerateStringType<base::string16>(value);
}
void Generator::FuzzData(char* data, int length) {
for (int i = 0; i < length; ++i) {
GenerateIntegralType<char>(&data[i]);
}
}
void Generator::FuzzBytes(void* data, int data_len) {
FuzzData(static_cast<char*>(data), data_len);
}
bool Generator::ShouldGenerate() {
// The generator fuzzer should always generate new values.
return true;
}
} // namespace ipc_fuzzer
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef TOOLS_IPC_FUZZER_MUTATE_GENERATOR_H_
#define TOOLS_IPC_FUZZER_MUTATE_GENERATOR_H_
#include <string>
#include "tools/ipc_fuzzer/mutate/fuzzer.h"
namespace ipc_fuzzer {
class Generator : public Fuzzer {
public:
Generator() {}
virtual ~Generator() {}
void FuzzBool(bool* value) override;
void FuzzInt(int* value) override;
void FuzzLong(long* value) override;
void FuzzSize(size_t* value) override;
void FuzzUChar(unsigned char* value) override;
void FuzzWChar(wchar_t* value) override;
void FuzzUInt16(uint16* value) override;
void FuzzUInt32(uint32* value) override;
void FuzzInt64(int64* value) override;
void FuzzUInt64(uint64* value) override;
void FuzzFloat(float* value) override;
void FuzzDouble(double* value) override;
void FuzzString(std::string* value) override;
void FuzzString16(base::string16* value) override;
void FuzzData(char* data, int length) override;
void FuzzBytes(void* data, int data_len) override;
bool ShouldGenerate() override;
};
} // namespace ipc_fuzzer
#endif // TOOLS_IPC_FUZZER_MUTATE_GENERATOR_H_
...@@ -14,8 +14,7 @@ import subprocess ...@@ -14,8 +14,7 @@ import subprocess
import sys import sys
import utils import utils
IPC_GENERATE_APPLICATION = 'ipc_fuzzer_generate' FUZZER_NAME_OPTION = '--fuzzer-name=generate'
IPC_REPLAY_APPLICATION = 'ipc_fuzzer_replay'
MAX_IPC_MESSAGES_PER_TESTCASE = 1500 MAX_IPC_MESSAGES_PER_TESTCASE = 1500
...@@ -26,12 +25,10 @@ class GenerationalFuzzer: ...@@ -26,12 +25,10 @@ class GenerationalFuzzer:
def set_application_paths(self): def set_application_paths(self):
chrome_application_path = utils.get_application_path() chrome_application_path = utils.get_application_path()
chrome_application_directory = os.path.dirname(chrome_application_path) chrome_application_directory = os.path.dirname(chrome_application_path)
self.ipc_generate_binary = utils.application_name_for_platform( self.ipc_fuzzer_binary = utils.get_fuzzer_application_name()
IPC_GENERATE_APPLICATION) self.ipc_replay_binary = utils.get_replay_application_name()
self.ipc_replay_binary = utils.application_name_for_platform( self.ipc_fuzzer_binary_path = os.path.join(
IPC_REPLAY_APPLICATION) chrome_application_directory, self.ipc_fuzzer_binary)
self.ipc_generate_binary_path = os.path.join(
chrome_application_directory, self.ipc_generate_binary)
self.ipc_replay_binary_path = os.path.join( self.ipc_replay_binary_path = os.path.join(
chrome_application_directory, self.ipc_replay_binary) chrome_application_directory, self.ipc_replay_binary)
...@@ -41,10 +38,15 @@ class GenerationalFuzzer: ...@@ -41,10 +38,15 @@ class GenerationalFuzzer:
num_ipc_messages = random.randint(1, MAX_IPC_MESSAGES_PER_TESTCASE) num_ipc_messages = random.randint(1, MAX_IPC_MESSAGES_PER_TESTCASE)
count_option = '--count=%d' % num_ipc_messages count_option = '--count=%d' % num_ipc_messages
cmd = [self.ipc_generate_binary_path, count_option, ipcdump_testcase_path] cmd = [
self.ipc_fuzzer_binary_path,
FUZZER_NAME_OPTION,
count_option,
ipcdump_testcase_path,
]
if subprocess.call(cmd): if subprocess.call(cmd):
sys.exit('%s failed.' % self.ipc_generate_binary) sys.exit('%s failed.' % self.ipc_fuzzer_binary)
utils.create_flags_file(ipcdump_testcase_path, self.ipc_replay_binary_path) utils.create_flags_file(ipcdump_testcase_path, self.ipc_replay_binary_path)
......
...@@ -17,9 +17,8 @@ import subprocess ...@@ -17,9 +17,8 @@ import subprocess
import sys import sys
import utils import utils
FUZZER_NAME_OPTION = '--fuzzer-name=mutate'
IPC_MESSAGE_UTIL_APPLICATION = 'ipc_message_util' IPC_MESSAGE_UTIL_APPLICATION = 'ipc_message_util'
IPC_MUTATE_APPLICATION = 'ipc_fuzzer_mutate'
IPC_REPLAY_APPLICATION = 'ipc_fuzzer_replay'
IPCDUMP_MERGE_LIMIT = 50 IPCDUMP_MERGE_LIMIT = 50
class MutationalFuzzer: class MutationalFuzzer:
...@@ -32,14 +31,12 @@ class MutationalFuzzer: ...@@ -32,14 +31,12 @@ class MutationalFuzzer:
self.ipc_message_util_binary = utils.application_name_for_platform( self.ipc_message_util_binary = utils.application_name_for_platform(
IPC_MESSAGE_UTIL_APPLICATION) IPC_MESSAGE_UTIL_APPLICATION)
self.ipc_mutate_binary = utils.application_name_for_platform( self.ipc_fuzzer_binary = utils.get_fuzzer_application_name()
IPC_MUTATE_APPLICATION) self.ipc_replay_binary = utils.get_replay_application_name()
self.ipc_replay_binary = utils.application_name_for_platform(
IPC_REPLAY_APPLICATION)
self.ipc_message_util_binary_path = os.path.join( self.ipc_message_util_binary_path = os.path.join(
chrome_application_directory, self.ipc_message_util_binary) chrome_application_directory, self.ipc_message_util_binary)
self.ipc_mutate_binary_path = os.path.join( self.ipc_fuzzer_binary_path = os.path.join(
chrome_application_directory, self.ipc_mutate_binary) chrome_application_directory, self.ipc_fuzzer_binary)
self.ipc_replay_binary_path = os.path.join( self.ipc_replay_binary_path = os.path.join(
chrome_application_directory, self.ipc_replay_binary) chrome_application_directory, self.ipc_replay_binary)
...@@ -66,12 +63,13 @@ class MutationalFuzzer: ...@@ -66,12 +63,13 @@ class MutationalFuzzer:
# Mutate tmp_ipcdump -> mutated_ipcdump. # Mutate tmp_ipcdump -> mutated_ipcdump.
cmd = [ cmd = [
self.ipc_mutate_binary_path, self.ipc_fuzzer_binary_path,
FUZZER_NAME_OPTION,
tmp_ipcdump_testcase, tmp_ipcdump_testcase,
mutated_ipcdump_testcase, mutated_ipcdump_testcase,
] ]
if subprocess.call(cmd): if subprocess.call(cmd):
sys.exit('%s failed.' % self.ipc_mutate_binary) sys.exit('%s failed.' % self.ipc_fuzzer_binary)
utils.create_flags_file( utils.create_flags_file(
mutated_ipcdump_testcase, self.ipc_replay_binary_path) mutated_ipcdump_testcase, self.ipc_replay_binary_path)
......
This diff is collapsed.
...@@ -8,48 +8,26 @@ ...@@ -8,48 +8,26 @@
}, },
'targets': [ 'targets': [
{ {
'target_name': 'ipc_fuzzer_mutate', 'target_name': 'ipc_fuzzer',
'type': 'executable', 'type': 'executable',
'dependencies': [ 'dependencies': [
'../message_lib/message_lib.gyp:ipc_message_lib', '../message_lib/message_lib.gyp:ipc_message_lib',
], ],
'sources': [ 'sources': [
'mutate.cc', 'fuzzer.h',
'fuzzer.cc',
'fuzzer_main.cc',
'generator.h',
'generator.cc',
'mutator.h',
'mutator.cc',
'rand_util.h', 'rand_util.h',
'rand_util.cc', 'rand_util.cc',
], ],
'conditions': [ 'conditions': [
['asan==1', { ['asan==1', {
'cflags!': [ 'cflags!': [
# Compiling mutate.cc with ASan takes too long, see # Compiling fuzzer.cc with ASan takes too long, see
# http://crbug.com/360158.
'-fsanitize=address',
'-fsanitize-coverage=<(sanitizer_coverage)',
],
}],
],
'include_dirs': [
'../../..',
],
'defines': [
'USE_CUPS',
],
},
{
'target_name': 'ipc_fuzzer_generate',
'type': 'executable',
'dependencies': [
'../message_lib/message_lib.gyp:ipc_message_lib',
],
'sources': [
'generate.cc',
'rand_util.h',
'rand_util.cc',
],
'conditions': [
['asan==1', {
'cflags!': [
# Compiling generate.cc with ASan takes too long, see
# http://crbug.com/360158. # http://crbug.com/360158.
'-fsanitize=address', '-fsanitize=address',
'-fsanitize-coverage=<(sanitizer_coverage)', '-fsanitize-coverage=<(sanitizer_coverage)',
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <algorithm>
#include <string>
#include "base/basictypes.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "tools/ipc_fuzzer/mutate/mutator.h"
#include "tools/ipc_fuzzer/mutate/rand_util.h"
namespace ipc_fuzzer {
template <typename T>
void FuzzIntegralType(T* value, unsigned int frequency) {
if (RandEvent(frequency)) {
switch (RandInRange(4)) {
case 0: (*value) = 0; break;
case 1: (*value)--; break;
case 2: (*value)++; break;
case 3: (*value) = RandU64(); break;
}
}
}
template <typename T>
void FuzzStringType(T* value, unsigned int frequency,
const T& literal1, const T& literal2) {
if (RandEvent(frequency)) {
switch (RandInRange(5)) {
case 4: (*value) = (*value) + (*value); // FALLTHROUGH
case 3: (*value) = (*value) + (*value); // FALLTHROUGH
case 2: (*value) = (*value) + (*value); break;
case 1: (*value) += literal1; break;
case 0: (*value) = literal2; break;
}
}
}
void Mutator::FuzzBool(bool* value) {
if (RandEvent(frequency_))
(*value) = !(*value);
}
void Mutator::FuzzInt(int* value) {
FuzzIntegralType<int>(value, frequency_);
}
void Mutator::FuzzLong(long* value) {
FuzzIntegralType<long>(value, frequency_);
}
void Mutator::FuzzSize(size_t* value) {
FuzzIntegralType<size_t>(value, frequency_);
}
void Mutator::FuzzUChar(unsigned char* value) {
FuzzIntegralType<unsigned char>(value, frequency_);
}
void Mutator::FuzzWChar(wchar_t* value) {
FuzzIntegralType<wchar_t>(value, frequency_);
}
void Mutator::FuzzUInt16(uint16* value) {
FuzzIntegralType<uint16>(value, frequency_);
}
void Mutator::FuzzUInt32(uint32* value) {
FuzzIntegralType<uint32>(value, frequency_);
}
void Mutator::FuzzInt64(int64* value) {
FuzzIntegralType<int64>(value, frequency_);
}
void Mutator::FuzzUInt64(uint64* value) {
FuzzIntegralType<uint64>(value, frequency_);
}
void Mutator::FuzzFloat(float* value) {
if (RandEvent(frequency_))
*value = RandDouble();
}
void Mutator::FuzzDouble(double* value) {
if (RandEvent(frequency_))
*value = RandDouble();
}
void Mutator:: FuzzString(std::string* value) {
FuzzStringType<std::string>(value, frequency_, "BORKED", std::string());
}
void Mutator::FuzzString16(base::string16* value) {
FuzzStringType<base::string16>(value, frequency_,
base::WideToUTF16(L"BORKED"),
base::WideToUTF16(L""));
}
void Mutator::FuzzData(char* data, int length) {
if (RandEvent(frequency_)) {
for (int i = 0; i < length; ++i) {
FuzzIntegralType<char>(&data[i], frequency_);
}
}
}
void Mutator::FuzzBytes(void* data, int data_len) {
FuzzData(static_cast<char*>(data), data_len);
}
bool Mutator::ShouldGenerate() {
// TODO(mbarbella): With a low probability, allow something to be fully
// rewritten while mutating instead of always changing the existing value.
return false;
}
} // namespace ipc_fuzzer
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef TOOLS_IPC_FUZZER_MUTATE_MUTATOR_H_
#define TOOLS_IPC_FUZZER_MUTATE_MUTATOR_H_
#include <string>
#include "tools/ipc_fuzzer/mutate/fuzzer.h"
namespace ipc_fuzzer {
class Mutator : public Fuzzer {
public:
explicit Mutator(unsigned int frequency) : frequency_(frequency) {}
virtual ~Mutator() {}
void FuzzBool(bool* value) override;
void FuzzInt(int* value) override;
void FuzzLong(long* value) override;
void FuzzSize(size_t* value) override;
void FuzzUChar(unsigned char* value) override;
void FuzzWChar(wchar_t* value) override;
void FuzzUInt16(uint16* value) override;
void FuzzUInt32(uint32* value) override;
void FuzzInt64(int64* value) override;
void FuzzUInt64(uint64* value) override;
void FuzzFloat(float* value) override;
void FuzzDouble(double* value) override;
void FuzzString(std::string* value) override;
void FuzzString16(base::string16* value) override;
void FuzzData(char* data, int length) override;
void FuzzBytes(void* data, int data_len) override;
bool ShouldGenerate() override;
private:
// TODO(mbarbella): Use double frequencies.
unsigned int frequency_;
};
} // namespace ipc_fuzzer
#endif // TOOLS_IPC_FUZZER_MUTATE_MUTATOR_H_
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "tools/ipc_fuzzer/mutate/rand_util.h"
#include "base/rand_util.h" #include "base/rand_util.h"
#include "tools/ipc_fuzzer/mutate/rand_util.h"
namespace ipc_fuzzer { namespace ipc_fuzzer {
......
...@@ -16,6 +16,7 @@ import tempfile ...@@ -16,6 +16,7 @@ import tempfile
APP_PATH_KEY = 'APP_PATH' APP_PATH_KEY = 'APP_PATH'
FLAGS_PREFIX = 'flags-' FLAGS_PREFIX = 'flags-'
FUZZ_PREFIX = 'fuzz-' FUZZ_PREFIX = 'fuzz-'
IPC_FUZZER_APPLICATION = 'ipc_fuzzer'
IPC_REPLAY_APPLICATION = 'ipc_fuzzer_replay' IPC_REPLAY_APPLICATION = 'ipc_fuzzer_replay'
IPCDUMP_EXTENSION = '.ipcdump' IPCDUMP_EXTENSION = '.ipcdump'
LAUNCH_PREFIXES = [ LAUNCH_PREFIXES = [
...@@ -48,6 +49,14 @@ def create_temp_file(): ...@@ -48,6 +49,14 @@ def create_temp_file():
temp_file.close() temp_file.close()
return temp_file.name return temp_file.name
def get_fuzzer_application_name():
"""Get the application name for the fuzzer binary."""
return application_name_for_platform(IPC_FUZZER_APPLICATION)
def get_replay_application_name():
"""Get the application name for the replay binary."""
return application_name_for_platform(IPC_REPLAY_APPLICATION)
def parse_arguments(): def parse_arguments():
"""Parse fuzzer arguments.""" """Parse fuzzer arguments."""
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
...@@ -90,4 +99,4 @@ def get_application_path(): ...@@ -90,4 +99,4 @@ def get_application_path():
sys.exit( sys.exit(
'Environment variable %s should be set to chrome path.' % APP_PATH_KEY) 'Environment variable %s should be set to chrome path.' % APP_PATH_KEY)
return os.environ[APP_PATH_KEY] return os.environ[APP_PATH_KEY]
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment