mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1764259 - [Fuzzing] Nyx replay mode. r=truber
Differential Revision: https://phabricator.services.mozilla.com/D143458
This commit is contained in:
parent
cde0054620
commit
8e5b003502
@ -29,14 +29,18 @@
|
||||
});
|
||||
# endif
|
||||
|
||||
# define MOZ_FUZZING_HANDLE_CRASH_EVENT2(aType, aReason) \
|
||||
do { \
|
||||
nyx_handle_event(aType, __FILE__, __LINE__, aReason); \
|
||||
# define MOZ_FUZZING_HANDLE_CRASH_EVENT2(aType, aReason) \
|
||||
do { \
|
||||
if (nyx_handle_event) { \
|
||||
nyx_handle_event(aType, __FILE__, __LINE__, aReason); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
# define MOZ_FUZZING_HANDLE_CRASH_EVENT4(aType, aFilename, aLine, aReason) \
|
||||
do { \
|
||||
nyx_handle_event(aType, aFilename, aLine, aReason); \
|
||||
if (nyx_handle_event) { \
|
||||
nyx_handle_event(aType, aFilename, aLine, aReason); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
# define MOZ_FUZZING_NYX_PRINT(aMsg) \
|
||||
|
@ -5,7 +5,15 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "mozilla/fuzzing/Nyx.h"
|
||||
#include "prinrval.h"
|
||||
#include "prthread.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace fuzzing {
|
||||
@ -47,6 +55,72 @@ void Nyx::start(void) {
|
||||
MOZ_RELEASE_ASSERT(!mInited);
|
||||
mInited = true;
|
||||
|
||||
// Check if we are in replay mode.
|
||||
char* testFilePtr = getenv("MOZ_FUZZ_TESTFILE");
|
||||
if (testFilePtr) {
|
||||
mReplayMode = true;
|
||||
|
||||
MOZ_FUZZING_NYX_PRINT("[Replay Mode] Reading data file...\n");
|
||||
|
||||
std::string testFile(testFilePtr);
|
||||
std::ifstream is;
|
||||
is.open(testFile, std::ios::binary);
|
||||
|
||||
uint64_t chksum, num_ops, num_data, op_offset, data_offset;
|
||||
|
||||
// If only C++ supported streaming operators on binary files...
|
||||
is.read(reinterpret_cast<char*>(&chksum), sizeof(uint64_t));
|
||||
is.read(reinterpret_cast<char*>(&num_ops), sizeof(uint64_t));
|
||||
is.read(reinterpret_cast<char*>(&num_data), sizeof(uint64_t));
|
||||
is.read(reinterpret_cast<char*>(&op_offset), sizeof(uint64_t));
|
||||
is.read(reinterpret_cast<char*>(&data_offset), sizeof(uint64_t));
|
||||
|
||||
if (!is.good()) {
|
||||
MOZ_FUZZING_NYX_PRINT("[Replay Mode] Error reading input file.\n");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
is.seekg(data_offset);
|
||||
|
||||
// The data chunks we receive through Nyx are stored in the data
|
||||
// section of the testfile as chunks prefixed with a 16-bit data
|
||||
// length. We read all chunks and store them away to simulate how
|
||||
// we originally received the data via Nyx.
|
||||
|
||||
while (is.good()) {
|
||||
uint16_t pktsize;
|
||||
is.read(reinterpret_cast<char*>(&pktsize), sizeof(uint16_t));
|
||||
|
||||
if (!is.good()) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto buffer = new Vector<uint8_t>();
|
||||
|
||||
buffer->initLengthUninitialized(pktsize);
|
||||
is.read(reinterpret_cast<char*>(buffer->begin()), buffer->length());
|
||||
|
||||
MOZ_FUZZING_NYX_PRINTF("[Replay Mode] Read data packet of size %zu\n",
|
||||
buffer->length());
|
||||
|
||||
mReplayBuffers.push_back(buffer);
|
||||
}
|
||||
|
||||
if (!mReplayBuffers.size()) {
|
||||
MOZ_FUZZING_NYX_PRINT("[Replay Mode] Error: No buffers read.\n");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
is.close();
|
||||
|
||||
if (!!getenv("MOZ_FUZZ_WAIT_BEFORE_REPLAY")) {
|
||||
// This can be useful in some cases to reproduce intermittent issues.
|
||||
PR_Sleep(PR_MillisecondsToInterval(5000));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
NYX_CHECK_API(nyx_start);
|
||||
NYX_CHECK_API(nyx_get_next_fuzz_data);
|
||||
NYX_CHECK_API(nyx_release);
|
||||
@ -66,19 +140,58 @@ bool Nyx::is_enabled(const char* identifier) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Nyx::is_replay() { return mReplayMode; }
|
||||
|
||||
uint32_t Nyx::get_data(uint8_t* data, uint32_t size) {
|
||||
MOZ_RELEASE_ASSERT(mInited);
|
||||
|
||||
if (mReplayMode) {
|
||||
if (!mReplayBuffers.size()) {
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
Vector<uint8_t>* buffer = mReplayBuffers.front();
|
||||
mReplayBuffers.pop_front();
|
||||
|
||||
size = std::min(size, (uint32_t)buffer->length());
|
||||
memcpy(data, buffer->begin(), size);
|
||||
|
||||
delete buffer;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
return nyx_get_next_fuzz_data(data, size);
|
||||
}
|
||||
|
||||
void Nyx::release(uint32_t iterations) {
|
||||
MOZ_RELEASE_ASSERT(mInited);
|
||||
|
||||
if (mReplayMode) {
|
||||
MOZ_FUZZING_NYX_PRINT("[Replay Mode] Nyx::release() called.\n");
|
||||
|
||||
// If we reach this point in replay mode, we are essentially done.
|
||||
// Let's wait a bit further for things to settle and then exit.
|
||||
PR_Sleep(PR_MillisecondsToInterval(5000));
|
||||
_exit(1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
nyx_release(iterations);
|
||||
}
|
||||
|
||||
void Nyx::handle_event(const char* type, const char* file, int line,
|
||||
const char* reason) {
|
||||
MOZ_RELEASE_ASSERT(mInited);
|
||||
|
||||
if (mReplayMode) {
|
||||
MOZ_FUZZING_NYX_PRINTF(
|
||||
"[Replay Mode] Nyx::handle_event() called: %s at %s:%d : %s\n", type,
|
||||
file, line, reason);
|
||||
return;
|
||||
}
|
||||
|
||||
nyx_handle_event(type, file, line, reason);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <atomic>
|
||||
#include <list>
|
||||
|
||||
#ifndef NYX_DISALLOW_COPY_AND_ASSIGN
|
||||
# define NYX_DISALLOW_COPY_AND_ASSIGN(T) \
|
||||
@ -17,6 +18,11 @@
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class MallocAllocPolicy;
|
||||
template <class T, size_t MinInlineCapacity, class AllocPolicy>
|
||||
class Vector;
|
||||
|
||||
namespace fuzzing {
|
||||
|
||||
class Nyx {
|
||||
@ -26,6 +32,7 @@ class Nyx {
|
||||
void start(void);
|
||||
bool started(void);
|
||||
bool is_enabled(const char* identifier);
|
||||
bool is_replay();
|
||||
uint32_t get_data(uint8_t* data, uint32_t size);
|
||||
void release(uint32_t iterations = 1);
|
||||
void handle_event(const char* type, const char* file, int line,
|
||||
@ -34,6 +41,9 @@ class Nyx {
|
||||
private:
|
||||
std::atomic<bool> mInited;
|
||||
|
||||
std::atomic<bool> mReplayMode;
|
||||
std::list<Vector<uint8_t, 0, MallocAllocPolicy>*> mReplayBuffers;
|
||||
|
||||
Nyx();
|
||||
NYX_DISALLOW_COPY_AND_ASSIGN(Nyx);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user