summaryrefslogtreecommitdiffstats
path: root/tools/fuzzing/libfuzzer/harness
diff options
context:
space:
mode:
Diffstat (limited to 'tools/fuzzing/libfuzzer/harness')
-rw-r--r--tools/fuzzing/libfuzzer/harness/LibFuzzerRegistry.cpp32
-rw-r--r--tools/fuzzing/libfuzzer/harness/LibFuzzerRegistry.h41
-rw-r--r--tools/fuzzing/libfuzzer/harness/LibFuzzerRunner.cpp38
-rw-r--r--tools/fuzzing/libfuzzer/harness/LibFuzzerRunner.h23
-rw-r--r--tools/fuzzing/libfuzzer/harness/LibFuzzerTestHarness.h298
-rw-r--r--tools/fuzzing/libfuzzer/harness/moz.build19
6 files changed, 451 insertions, 0 deletions
diff --git a/tools/fuzzing/libfuzzer/harness/LibFuzzerRegistry.cpp b/tools/fuzzing/libfuzzer/harness/LibFuzzerRegistry.cpp
new file mode 100644
index 000000000..5390c91c2
--- /dev/null
+++ b/tools/fuzzing/libfuzzer/harness/LibFuzzerRegistry.cpp
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * * 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/. */
+
+#include "LibFuzzerRegistry.h"
+
+extern "C" {
+ void MOZ_EXPORT XRE_LibFuzzerGetFuncs(const char* moduleName, LibFuzzerInitFunc* initFunc, LibFuzzerTestingFunc* testingFunc) {
+ std::string moduleNameStr(moduleName);
+ mozilla::LibFuzzerFunctions funcs = mozilla::LibFuzzerRegistry::getInstance().getModuleFunctions(moduleNameStr);
+ *initFunc = funcs.first;
+ *testingFunc = funcs.second;
+ }
+}
+
+namespace mozilla {
+
+LibFuzzerRegistry& LibFuzzerRegistry::getInstance() {
+ static LibFuzzerRegistry instance;
+ return instance;
+}
+
+void LibFuzzerRegistry::registerModule(std::string moduleName, LibFuzzerInitFunc initFunc, LibFuzzerTestingFunc testingFunc) {
+ moduleMap.insert(std::pair<std::string, LibFuzzerFunctions>(moduleName,LibFuzzerFunctions(initFunc, testingFunc)));
+}
+
+LibFuzzerFunctions LibFuzzerRegistry::getModuleFunctions(std::string& moduleName) {
+ return moduleMap[moduleName];
+}
+
+} // namespace mozilla
diff --git a/tools/fuzzing/libfuzzer/harness/LibFuzzerRegistry.h b/tools/fuzzing/libfuzzer/harness/LibFuzzerRegistry.h
new file mode 100644
index 000000000..e459ade33
--- /dev/null
+++ b/tools/fuzzing/libfuzzer/harness/LibFuzzerRegistry.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * * 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/. */
+
+#ifndef _LibFuzzerRegistry_h__
+#define _LibFuzzerRegistry_h__
+
+#include <cstdint>
+#include <map>
+#include <string>
+#include <utility>
+
+#include "mozilla/Attributes.h"
+
+typedef int(*LibFuzzerMain)(int, char**);
+typedef int(*LibFuzzerInitFunc)(int*, char***);
+typedef int(*LibFuzzerTestingFunc)(const uint8_t*, size_t);
+
+namespace mozilla {
+
+typedef std::pair<LibFuzzerInitFunc, LibFuzzerTestingFunc> LibFuzzerFunctions;
+
+class LibFuzzerRegistry {
+ public:
+ MOZ_EXPORT static LibFuzzerRegistry& getInstance();
+ MOZ_EXPORT void registerModule(std::string moduleName, LibFuzzerInitFunc initFunc, LibFuzzerTestingFunc testingFunc);
+ MOZ_EXPORT LibFuzzerFunctions getModuleFunctions(std::string& moduleName);
+
+ LibFuzzerRegistry(LibFuzzerRegistry const&) = delete;
+ void operator=(LibFuzzerRegistry const&) = delete;
+
+ private:
+ LibFuzzerRegistry() {};
+ std::map<std::string, LibFuzzerFunctions> moduleMap;
+};
+
+} // namespace mozilla
+
+
+#endif // _LibFuzzerRegistry_h__
diff --git a/tools/fuzzing/libfuzzer/harness/LibFuzzerRunner.cpp b/tools/fuzzing/libfuzzer/harness/LibFuzzerRunner.cpp
new file mode 100644
index 000000000..2a57ddac8
--- /dev/null
+++ b/tools/fuzzing/libfuzzer/harness/LibFuzzerRunner.cpp
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * * 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/. */
+
+#include "LibFuzzerRunner.h"
+#include "mozilla/Attributes.h"
+#include "prenv.h"
+
+#include "LibFuzzerTestHarness.h"
+
+namespace mozilla {
+
+// We use a static var 'libFuzzerRunner' defined in nsAppRunner.cpp.
+// libFuzzerRunner is initialized to nullptr but if LibFuzzer (this file)
+// is linked in then libFuzzerRunner will be set here indicating that
+// we want to call into LibFuzzer's main.
+class _InitLibFuzzer {
+public:
+ _InitLibFuzzer() {
+ libFuzzerRunner = new LibFuzzerRunner();
+ }
+} InitLibFuzzer;
+
+int LibFuzzerRunner::Run() {
+ ScopedXPCOM xpcom("LibFuzzer");
+ return mFuzzerMain(mArgc, mArgv);
+}
+
+typedef int(*LibFuzzerMain)(int, char**);
+
+void LibFuzzerRunner::setParams(int argc, char** argv, LibFuzzerMain main) {
+ mArgc = argc;
+ mArgv = argv;
+ mFuzzerMain = main;
+}
+
+} // namespace mozilla
diff --git a/tools/fuzzing/libfuzzer/harness/LibFuzzerRunner.h b/tools/fuzzing/libfuzzer/harness/LibFuzzerRunner.h
new file mode 100644
index 000000000..c2362f4e9
--- /dev/null
+++ b/tools/fuzzing/libfuzzer/harness/LibFuzzerRunner.h
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * * 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/. */
+
+namespace mozilla {
+
+typedef int(*LibFuzzerMain)(int, char**);
+
+class LibFuzzerRunner {
+public:
+ int Run();
+ void setParams(int argc, char** argv, LibFuzzerMain main);
+
+private:
+ int mArgc;
+ char** mArgv;
+ LibFuzzerMain mFuzzerMain;
+};
+
+extern LibFuzzerRunner* libFuzzerRunner;
+
+} // namespace mozilla
diff --git a/tools/fuzzing/libfuzzer/harness/LibFuzzerTestHarness.h b/tools/fuzzing/libfuzzer/harness/LibFuzzerTestHarness.h
new file mode 100644
index 000000000..6ac2344e3
--- /dev/null
+++ b/tools/fuzzing/libfuzzer/harness/LibFuzzerTestHarness.h
@@ -0,0 +1,298 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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/. */
+
+/*
+ * Test harness for XPCOM objects, providing a scoped XPCOM initializer,
+ * nsCOMPtr, nsRefPtr, do_CreateInstance, do_GetService, ns(Auto|C|)String,
+ * and stdio.h/stdlib.h.
+ */
+
+#ifndef LibFuzzerTestHarness_h__
+#define LibFuzzerTestHarness_h__
+
+#include "mozilla/ArrayUtils.h"
+
+#include "prenv.h"
+#include "nsComponentManagerUtils.h"
+#include "nsServiceManagerUtils.h"
+#include "nsCOMPtr.h"
+#include "nsAutoPtr.h"
+#include "nsStringGlue.h"
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsDirectoryServiceUtils.h"
+#include "nsIDirectoryService.h"
+#include "nsIFile.h"
+#include "nsIProperties.h"
+#include "nsIObserverService.h"
+#include "nsXULAppAPI.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+namespace {
+
+static uint32_t gFailCount = 0;
+
+/**
+ * Prints the given failure message and arguments using printf, prepending
+ * "TEST-UNEXPECTED-FAIL " for the benefit of the test harness and
+ * appending "\n" to eliminate having to type it at each call site.
+ */
+void fail(const char* msg, ...)
+{
+ va_list ap;
+
+ printf("TEST-UNEXPECTED-FAIL | ");
+
+ va_start(ap, msg);
+ vprintf(msg, ap);
+ va_end(ap);
+
+ putchar('\n');
+ ++gFailCount;
+}
+
+/**
+ * Prints the given success message and arguments using printf, prepending
+ * "TEST-PASS " for the benefit of the test harness and
+ * appending "\n" to eliminate having to type it at each call site.
+ */
+void passed(const char* msg, ...)
+{
+ va_list ap;
+
+ printf("TEST-PASS | ");
+
+ va_start(ap, msg);
+ vprintf(msg, ap);
+ va_end(ap);
+
+ putchar('\n');
+}
+
+//-----------------------------------------------------------------------------
+
+static class ScopedXPCOM : public nsIDirectoryServiceProvider2
+{
+ public:
+ NS_DECL_ISUPPORTS
+
+ explicit ScopedXPCOM(const char* testName,
+ nsIDirectoryServiceProvider *dirSvcProvider = nullptr)
+ : mDirSvcProvider(dirSvcProvider)
+ {
+ mTestName = testName;
+ printf("Running %s tests...\n", mTestName);
+
+ nsresult rv = NS_InitXPCOM2(&mServMgr, nullptr, this);
+ if (NS_FAILED(rv))
+ {
+ fail("NS_InitXPCOM2 returned failure code 0x%x", rv);
+ mServMgr = nullptr;
+ return;
+ }
+ }
+
+ ~ScopedXPCOM()
+ {
+ // If we created a profile directory, we need to remove it.
+ if (mProfD) {
+ nsCOMPtr<nsIObserverService> os =
+ do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
+ MOZ_ASSERT(os);
+ if (os) {
+ MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-change-net-teardown", nullptr));
+ MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-change-teardown", nullptr));
+ MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-before-change", nullptr));
+ MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-before-change-qm", nullptr));
+ MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-before-change-telemetry", nullptr));
+ }
+
+ if (NS_FAILED(mProfD->Remove(true))) {
+ NS_WARNING("Problem removing profile directory");
+ }
+
+ mProfD = nullptr;
+ }
+
+ if (mServMgr)
+ {
+ NS_RELEASE(mServMgr);
+ nsresult rv = NS_ShutdownXPCOM(nullptr);
+ if (NS_FAILED(rv))
+ {
+ fail("XPCOM shutdown failed with code 0x%x", rv);
+ exit(1);
+ }
+ }
+
+ printf("Finished running %s tests.\n", mTestName);
+ }
+
+ bool failed()
+ {
+ return mServMgr == nullptr;
+ }
+
+ already_AddRefed<nsIFile> GetProfileDirectory()
+ {
+ if (mProfD) {
+ nsCOMPtr<nsIFile> copy = mProfD;
+ return copy.forget();
+ }
+
+ // Create a unique temporary folder to use for this test.
+ // Note that runcppunittests.py will run tests with a temp
+ // directory as the cwd, so just put something under that.
+ nsCOMPtr<nsIFile> profD;
+ nsresult rv = NS_GetSpecialDirectory(NS_OS_CURRENT_PROCESS_DIR,
+ getter_AddRefs(profD));
+ NS_ENSURE_SUCCESS(rv, nullptr);
+
+ rv = profD->Append(NS_LITERAL_STRING("cpp-unit-profd"));
+ NS_ENSURE_SUCCESS(rv, nullptr);
+
+ rv = profD->CreateUnique(nsIFile::DIRECTORY_TYPE, 0755);
+ NS_ENSURE_SUCCESS(rv, nullptr);
+
+ mProfD = profD;
+ return profD.forget();
+ }
+
+ already_AddRefed<nsIFile> GetGREDirectory()
+ {
+ if (mGRED) {
+ nsCOMPtr<nsIFile> copy = mGRED;
+ return copy.forget();
+ }
+
+ char* env = PR_GetEnv("MOZ_XRE_DIR");
+ nsCOMPtr<nsIFile> greD;
+ if (env) {
+ NS_NewLocalFile(NS_ConvertUTF8toUTF16(env), false,
+ getter_AddRefs(greD));
+ }
+
+ mGRED = greD;
+ return greD.forget();
+ }
+
+ already_AddRefed<nsIFile> GetGREBinDirectory()
+ {
+ if (mGREBinD) {
+ nsCOMPtr<nsIFile> copy = mGREBinD;
+ return copy.forget();
+ }
+
+ nsCOMPtr<nsIFile> greD = GetGREDirectory();
+ if (!greD) {
+ return greD.forget();
+ }
+ greD->Clone(getter_AddRefs(mGREBinD));
+
+#ifdef XP_MACOSX
+ nsAutoCString leafName;
+ mGREBinD->GetNativeLeafName(leafName);
+ if (leafName.Equals("Resources")) {
+ mGREBinD->SetNativeLeafName(NS_LITERAL_CSTRING("MacOS"));
+ }
+#endif
+
+ nsCOMPtr<nsIFile> copy = mGREBinD;
+ return copy.forget();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //// nsIDirectoryServiceProvider
+
+ NS_IMETHODIMP GetFile(const char *aProperty, bool *_persistent,
+ nsIFile **_result) override
+ {
+ // If we were supplied a directory service provider, ask it first.
+ if (mDirSvcProvider &&
+ NS_SUCCEEDED(mDirSvcProvider->GetFile(aProperty, _persistent,
+ _result))) {
+ return NS_OK;
+ }
+
+ // Otherwise, the test harness provides some directories automatically.
+ if (0 == strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) ||
+ 0 == strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR) ||
+ 0 == strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
+ nsCOMPtr<nsIFile> profD = GetProfileDirectory();
+ NS_ENSURE_TRUE(profD, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIFile> clone;
+ nsresult rv = profD->Clone(getter_AddRefs(clone));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ *_persistent = true;
+ clone.forget(_result);
+ return NS_OK;
+ } else if (0 == strcmp(aProperty, NS_GRE_DIR)) {
+ nsCOMPtr<nsIFile> greD = GetGREDirectory();
+ NS_ENSURE_TRUE(greD, NS_ERROR_FAILURE);
+
+ *_persistent = true;
+ greD.forget(_result);
+ return NS_OK;
+ } else if (0 == strcmp(aProperty, NS_GRE_BIN_DIR)) {
+ nsCOMPtr<nsIFile> greBinD = GetGREBinDirectory();
+ NS_ENSURE_TRUE(greBinD, NS_ERROR_FAILURE);
+
+ *_persistent = true;
+ greBinD.forget(_result);
+ return NS_OK;
+ }
+
+ return NS_ERROR_FAILURE;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //// nsIDirectoryServiceProvider2
+
+ NS_IMETHODIMP GetFiles(const char *aProperty, nsISimpleEnumerator **_enum) override
+ {
+ // If we were supplied a directory service provider, ask it first.
+ nsCOMPtr<nsIDirectoryServiceProvider2> provider =
+ do_QueryInterface(mDirSvcProvider);
+ if (provider && NS_SUCCEEDED(provider->GetFiles(aProperty, _enum))) {
+ return NS_OK;
+ }
+
+ return NS_ERROR_FAILURE;
+ }
+
+ private:
+ const char* mTestName;
+ nsIServiceManager* mServMgr;
+ nsCOMPtr<nsIDirectoryServiceProvider> mDirSvcProvider;
+ nsCOMPtr<nsIFile> mProfD;
+ nsCOMPtr<nsIFile> mGRED;
+ nsCOMPtr<nsIFile> mGREBinD;
+};
+
+NS_IMPL_QUERY_INTERFACE(
+ ScopedXPCOM,
+ nsIDirectoryServiceProvider,
+ nsIDirectoryServiceProvider2
+)
+
+NS_IMETHODIMP_(MozExternalRefCountType)
+ScopedXPCOM::AddRef()
+{
+ return 2;
+}
+
+NS_IMETHODIMP_(MozExternalRefCountType)
+ScopedXPCOM::Release()
+{
+ return 1;
+}
+
+} // namespace
+
+#endif // LibFuzzerTestHarness_h__
diff --git a/tools/fuzzing/libfuzzer/harness/moz.build b/tools/fuzzing/libfuzzer/harness/moz.build
new file mode 100644
index 000000000..596018cb3
--- /dev/null
+++ b/tools/fuzzing/libfuzzer/harness/moz.build
@@ -0,0 +1,19 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Library('fuzzer-runner')
+
+SOURCES += [
+ 'LibFuzzerRegistry.cpp',
+ 'LibFuzzerRunner.cpp',
+]
+
+EXPORTS += [
+ 'LibFuzzerRegistry.h',
+ 'LibFuzzerRunner.h',
+]
+
+FINAL_LIBRARY = "xul"