diff options
Diffstat (limited to 'tools/fuzzing')
-rw-r--r-- | tools/fuzzing/interface/FuzzingInterface.cpp | 67 | ||||
-rw-r--r-- | tools/fuzzing/interface/FuzzingInterface.h | 100 | ||||
-rw-r--r-- | tools/fuzzing/interface/moz.build | 15 | ||||
-rw-r--r-- | tools/fuzzing/libfuzzer/FuzzerCustomMain.cpp | 37 | ||||
-rw-r--r-- | tools/fuzzing/libfuzzer/Makefile.in | 12 | ||||
-rwxr-xr-x | tools/fuzzing/libfuzzer/clone_libfuzzer.sh | 7 | ||||
-rw-r--r-- | tools/fuzzing/libfuzzer/harness/LibFuzzerRegistry.cpp | 32 | ||||
-rw-r--r-- | tools/fuzzing/libfuzzer/harness/LibFuzzerRegistry.h | 41 | ||||
-rw-r--r-- | tools/fuzzing/libfuzzer/harness/LibFuzzerRunner.cpp | 38 | ||||
-rw-r--r-- | tools/fuzzing/libfuzzer/harness/LibFuzzerRunner.h | 23 | ||||
-rw-r--r-- | tools/fuzzing/libfuzzer/harness/LibFuzzerTestHarness.h | 298 | ||||
-rw-r--r-- | tools/fuzzing/libfuzzer/harness/moz.build | 19 | ||||
-rw-r--r-- | tools/fuzzing/libfuzzer/moz.build | 26 | ||||
-rw-r--r-- | tools/fuzzing/moz.build | 14 |
14 files changed, 729 insertions, 0 deletions
diff --git a/tools/fuzzing/interface/FuzzingInterface.cpp b/tools/fuzzing/interface/FuzzingInterface.cpp new file mode 100644 index 0000000000..59077f3828 --- /dev/null +++ b/tools/fuzzing/interface/FuzzingInterface.cpp @@ -0,0 +1,67 @@ +/* -*- 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/. */ + +/* + * Interface implementation for the unified fuzzing interface + */ + +#include "FuzzingInterface.h" + +#include "nsNetUtil.h" + +namespace mozilla { + +#ifdef __AFL_COMPILER +void afl_interface_stream(const char* testFile, FuzzingTestFuncStream testFunc) { + nsresult rv; + nsCOMPtr<nsIProperties> dirService = + do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID); + MOZ_RELEASE_ASSERT(dirService != nullptr); + nsCOMPtr<nsIFile> file; + rv = dirService->Get(NS_OS_CURRENT_WORKING_DIR, + NS_GET_IID(nsIFile), getter_AddRefs(file)); + MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv)); + file->AppendNative(nsDependentCString(testFile)); + while(__AFL_LOOP(1000)) { + nsCOMPtr<nsIInputStream> inputStream; + rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), file); + MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv)); + if (!NS_InputStreamIsBuffered(inputStream)) { + nsCOMPtr<nsIInputStream> bufStream; + rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), + inputStream, 1024); + MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv)); + inputStream = bufStream; + } + testFunc(inputStream.forget()); + } +} + +void afl_interface_raw(const char* testFile, FuzzingTestFuncRaw testFunc) { + char* buf = NULL; + + while(__AFL_LOOP(1000)) { + std::ifstream is; + is.open (testFile, std::ios::binary); + is.seekg (0, std::ios::end); + int len = is.tellg(); + is.seekg (0, std::ios::beg); + MOZ_RELEASE_ASSERT(len >= 0); + if (!len) { + is.close(); + continue; + } + buf = (char*)realloc(buf, len); + MOZ_RELEASE_ASSERT(buf); + is.read(buf,len); + is.close(); + testFunc((uint8_t*)buf, (size_t)len); + } + + free(buf); +} +#endif + +} // namespace mozilla diff --git a/tools/fuzzing/interface/FuzzingInterface.h b/tools/fuzzing/interface/FuzzingInterface.h new file mode 100644 index 0000000000..c2838e807f --- /dev/null +++ b/tools/fuzzing/interface/FuzzingInterface.h @@ -0,0 +1,100 @@ +/* -*- 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/. */ + +/* + * Interface definitions for the unified fuzzing interface + */ + +#ifndef FuzzingInterface_h__ +#define FuzzingInterface_h__ + +#include "gtest/gtest.h" +#include "nsComponentManagerUtils.h" +#include "nsCOMPtr.h" +#include "nsIInputStream.h" + +#include "nsDirectoryServiceDefs.h" +#include "nsIDirectoryService.h" +#include "nsIFile.h" +#include "nsStreamUtils.h" +#include "nsStringStream.h" + +#include <fstream> + +namespace mozilla { + +typedef int(*FuzzingTestFuncRaw)(const uint8_t*, size_t); +typedef int(*FuzzingTestFuncStream)(nsCOMPtr<nsIInputStream>); + +#ifdef __AFL_COMPILER +void afl_interface_stream(const char* testFile, FuzzingTestFuncStream testFunc); +void afl_interface_raw(const char* testFile, FuzzingTestFuncRaw testFunc); + +#define MOZ_AFL_INTERFACE_COMMON(initFunc) \ + initFunc(NULL, NULL); \ + char* testFilePtr = getenv("MOZ_FUZZ_TESTFILE"); \ + if (!testFilePtr) { \ + EXPECT_TRUE(false) << "Must specify testfile in MOZ_FUZZ_TESTFILE environment variable."; \ + return; \ + } \ + /* Make a copy of testFilePtr so the testing function can safely call getenv */ \ + std::string testFile(testFilePtr); + +#define MOZ_AFL_INTERFACE_STREAM(initFunc, testFunc, moduleName) \ + TEST(AFL, moduleName) { \ + MOZ_AFL_INTERFACE_COMMON(initFunc); \ + ::mozilla::afl_interface_stream(testFile.c_str(), testFunc); \ + } + +#define MOZ_AFL_INTERFACE_RAW(initFunc, testFunc, moduleName) \ + TEST(AFL, moduleName) { \ + MOZ_AFL_INTERFACE_COMMON(initFunc); \ + ::mozilla::afl_interface_raw(testFile.c_str(), testFunc); \ + } +#else +#define MOZ_AFL_INTERFACE_STREAM(initFunc, testFunc, moduleName) /* Nothing */ +#define MOZ_AFL_INTERFACE_RAW(initFunc, testFunc, moduleName) /* Nothing */ +#endif + +#ifdef LIBFUZZER +#define MOZ_LIBFUZZER_INTERFACE_STREAM(initFunc, testFunc, moduleName) \ + static int LibFuzzerTest##moduleName (const uint8_t *data, size_t size) { \ + if (size > INT32_MAX) \ + return 0; \ + nsCOMPtr<nsIInputStream> stream; \ + nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream), \ + (const char*)data, size, NS_ASSIGNMENT_DEPEND); \ + MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv)); \ + testFunc(stream.forget()); \ + return 0; \ + } \ + static void __attribute__ ((constructor)) LibFuzzerRegister() { \ + ::mozilla::LibFuzzerRegistry::getInstance().registerModule( \ + #moduleName, initFunc, LibFuzzerTest##moduleName \ + ); \ + } + +#define MOZ_LIBFUZZER_INTERFACE_RAW(initFunc, testFunc, moduleName) \ + static void __attribute__ ((constructor)) LibFuzzerRegister() { \ + ::mozilla::LibFuzzerRegistry::getInstance().registerModule( \ + #moduleName, initFunc, testFunc \ + ); \ + } +#else +#define MOZ_LIBFUZZER_INTERFACE_STREAM(initFunc, testFunc, moduleName) /* Nothing */ +#define MOZ_LIBFUZZER_INTERFACE_RAW(initFunc, testFunc, moduleName) /* Nothing */ +#endif + +#define MOZ_FUZZING_INTERFACE_STREAM(initFunc, testFunc, moduleName) \ + MOZ_LIBFUZZER_INTERFACE_STREAM(initFunc, testFunc, moduleName); \ + MOZ_AFL_INTERFACE_STREAM(initFunc, testFunc, moduleName); + +#define MOZ_FUZZING_INTERFACE_RAW(initFunc, testFunc, moduleName) \ + MOZ_LIBFUZZER_INTERFACE_RAW(initFunc, testFunc, moduleName); \ + MOZ_AFL_INTERFACE_RAW(initFunc, testFunc, moduleName); + +} // namespace mozilla + +#endif // FuzzingInterface_h__ diff --git a/tools/fuzzing/interface/moz.build b/tools/fuzzing/interface/moz.build new file mode 100644 index 0000000000..6b2bb968cf --- /dev/null +++ b/tools/fuzzing/interface/moz.build @@ -0,0 +1,15 @@ +# -*- 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/. + +EXPORTS += [ + 'FuzzingInterface.h', +] + +SOURCES += [ + 'FuzzingInterface.cpp', +] + +FINAL_LIBRARY = 'xul-gtest' diff --git a/tools/fuzzing/libfuzzer/FuzzerCustomMain.cpp b/tools/fuzzing/libfuzzer/FuzzerCustomMain.cpp new file mode 100644 index 0000000000..2293efd95d --- /dev/null +++ b/tools/fuzzing/libfuzzer/FuzzerCustomMain.cpp @@ -0,0 +1,37 @@ +/* -*- 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 <cstdlib> + +#include "FuzzerInterface.h" +#include "FuzzerInternal.h" +#include "harness/LibFuzzerRegistry.h" + +/* This is a wrapper defined in browser/app/nsBrowserApp.cpp, + * encapsulating the XRE_ equivalent defined in libxul */ +extern void libFuzzerGetFuncs(const char*, LibFuzzerInitFunc*, + LibFuzzerTestingFunc*); + +int libfuzzer_main(int argc, char **argv) { + LibFuzzerInitFunc initFunc = nullptr; + LibFuzzerTestingFunc testingFunc = nullptr; + + libFuzzerGetFuncs(getenv("LIBFUZZER"), &initFunc, &testingFunc); + + if (initFunc) { + int ret = initFunc(&argc, &argv); + if (ret) { + fprintf(stderr, "LibFuzzer: Error: Initialize callback failed\n"); + return ret; + } + } + + if (!testingFunc) { + fprintf(stderr, "LibFuzzer: Error: No testing callback found\n"); + return 1; + } + + return fuzzer::FuzzerDriver(&argc, &argv, testingFunc); +} diff --git a/tools/fuzzing/libfuzzer/Makefile.in b/tools/fuzzing/libfuzzer/Makefile.in new file mode 100644 index 0000000000..7ffe876852 --- /dev/null +++ b/tools/fuzzing/libfuzzer/Makefile.in @@ -0,0 +1,12 @@ +# 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 $(topsrcdir)/config/rules.mk + +# According to the LLVM docs, LibFuzzer isn't supposed to be built with any +# sanitizer flags and in fact, building it with ASan coverage currently causes +# Clang 3.9+ to crash, so we filter out all sanitizer-related flags here. +CXXFLAGS := $(filter-out -fsanitize%,$(CXXFLAGS)) +CFLAGS := $(filter-out -fsanitize%,$(CFLAGS)) +LDFLAGS := $(filter-out -fsanitize%,$(LDFLAGS)) diff --git a/tools/fuzzing/libfuzzer/clone_libfuzzer.sh b/tools/fuzzing/libfuzzer/clone_libfuzzer.sh new file mode 100755 index 0000000000..6170362ac9 --- /dev/null +++ b/tools/fuzzing/libfuzzer/clone_libfuzzer.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +mkdir tmp/ +git clone --no-checkout --depth 1 https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer tmp/ +mv tmp/.git . +rm -Rf tmp +git reset --hard HEAD diff --git a/tools/fuzzing/libfuzzer/harness/LibFuzzerRegistry.cpp b/tools/fuzzing/libfuzzer/harness/LibFuzzerRegistry.cpp new file mode 100644 index 0000000000..5390c91c2a --- /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 0000000000..e459ade33e --- /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 0000000000..2a57ddac80 --- /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 0000000000..c2362f4e99 --- /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 0000000000..6ac2344e31 --- /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 0000000000..596018cb3c --- /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" diff --git a/tools/fuzzing/libfuzzer/moz.build b/tools/fuzzing/libfuzzer/moz.build new file mode 100644 index 0000000000..b37afdf9ce --- /dev/null +++ b/tools/fuzzing/libfuzzer/moz.build @@ -0,0 +1,26 @@ +# -*- 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') + +DIRS += [ + 'harness', +] + +SOURCES += [ + 'FuzzerCrossOver.cpp', + 'FuzzerCustomMain.cpp', + 'FuzzerDriver.cpp', + 'FuzzerExtFunctionsDlsym.cpp', + 'FuzzerExtFunctionsWeak.cpp', + 'FuzzerIO.cpp', + 'FuzzerLoop.cpp', + 'FuzzerMutate.cpp', + 'FuzzerSHA1.cpp', + 'FuzzerTracePC.cpp', + 'FuzzerTraceState.cpp', + 'FuzzerUtil.cpp', +] diff --git a/tools/fuzzing/moz.build b/tools/fuzzing/moz.build new file mode 100644 index 0000000000..a9ac90e87e --- /dev/null +++ b/tools/fuzzing/moz.build @@ -0,0 +1,14 @@ +# -*- 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/. + +DIRS += [ + 'interface', +] + +if CONFIG['LIBFUZZER']: + DIRS += [ + 'libfuzzer', + ] |