diff --git a/browser/app/moz.build b/browser/app/moz.build
index 68092c7b12303306a599d9744d45a759ad3ed034..520ce4425d044f118b30e23ddf74eede572b0f1c 100644
--- a/browser/app/moz.build
+++ b/browser/app/moz.build
@@ -33,6 +33,9 @@ USE_LIBS += [
     'mozglue',
 ]
 
+if CONFIG['LIBFUZZER']:
+  USE_LIBS += [ 'fuzzer' ]
+
 if CONFIG['_MSC_VER']:
     # Always enter a Windows program through wmain, whether or not we're
     # a console application.
diff --git a/browser/app/nsBrowserApp.cpp b/browser/app/nsBrowserApp.cpp
index 019bf6043f5241c859f3523e62f12a0325c73f7c..335b32354daa20b43cfd167216fb896cda6c30a6 100644
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -127,6 +127,10 @@ XRE_GetProcessTypeType XRE_GetProcessType;
 XRE_SetProcessTypeType XRE_SetProcessType;
 XRE_InitChildProcessType XRE_InitChildProcess;
 XRE_EnableSameExecutableForContentProcType XRE_EnableSameExecutableForContentProc;
+#ifdef LIBFUZZER
+XRE_LibFuzzerSetMainType XRE_LibFuzzerSetMain;
+XRE_LibFuzzerGetFuncsType XRE_LibFuzzerGetFuncs;
+#endif
 
 static const nsDynamicFunctionLoad kXULFuncs[] = {
     { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
@@ -141,9 +145,24 @@ static const nsDynamicFunctionLoad kXULFuncs[] = {
     { "XRE_SetProcessType", (NSFuncPtr*) &XRE_SetProcessType },
     { "XRE_InitChildProcess", (NSFuncPtr*) &XRE_InitChildProcess },
     { "XRE_EnableSameExecutableForContentProc", (NSFuncPtr*) &XRE_EnableSameExecutableForContentProc },
+#ifdef LIBFUZZER
+    { "XRE_LibFuzzerSetMain", (NSFuncPtr*) &XRE_LibFuzzerSetMain },
+    { "XRE_LibFuzzerGetFuncs", (NSFuncPtr*) &XRE_LibFuzzerGetFuncs },
+#endif
     { nullptr, nullptr }
 };
 
+#ifdef LIBFUZZER
+int libfuzzer_main(int argc, char **argv);
+
+/* This wrapper is used by the libFuzzer main to call into libxul */
+
+void libFuzzerGetFuncs(const char* moduleName, LibFuzzerInitFunc* initFunc,
+                       LibFuzzerTestingFunc* testingFunc) {
+  return XRE_LibFuzzerGetFuncs(moduleName, initFunc, testingFunc);
+}
+#endif
+
 static int do_main(int argc, char* argv[], char* envp[], nsIFile *xreDirectory)
 {
   nsCOMPtr<nsIFile> appini;
@@ -254,6 +273,11 @@ static int do_main(int argc, char* argv[], char* envp[], nsIFile *xreDirectory)
   appData.sandboxBrokerServices = brokerServices;
 #endif
 
+#ifdef LIBFUZZER
+  if (getenv("LIBFUZZER"))
+    XRE_LibFuzzerSetMain(argc, argv, libfuzzer_main);
+#endif
+
   return XRE_main(argc, argv, &appData, mainFlags);
 }
 
diff --git a/moz.build b/moz.build
index fee89428deeac1ef1bf1be2c3854a0ea39979931..ea1e3af117a25d45040b154530a3370014cd1f8e 100644
--- a/moz.build
+++ b/moz.build
@@ -57,6 +57,7 @@ DIRS += [
     'memory',
     'mfbt',
     'mozglue',
+    'tools/fuzzing',
 ]
 
 if not CONFIG['JS_STANDALONE']:
diff --git a/toolkit/moz.configure b/toolkit/moz.configure
index facd2a9dd9d5f7ad2658eed42b7b7e3e652b5ac7..0c98c7ad4a0cfae0c6da734a5ce21079ad1d52b5 100644
--- a/toolkit/moz.configure
+++ b/toolkit/moz.configure
@@ -764,3 +764,15 @@ def skia_includes(skia, skia_gpu):
     return includes
 
 set_config('SKIA_INCLUDES', skia_includes)
+
+# Support various fuzzing options
+# ==============================================================
+option('--enable-libfuzzer', help='Enable libfuzzer support')
+
+@depends('--enable-libfuzzer')
+def enable_libfuzzer(value):
+    if value:
+        return True
+
+set_config('LIBFUZZER', enable_libfuzzer)
+set_define('LIBFUZZER', enable_libfuzzer)
diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
index 15ebf9efd28cfb22a91c802054c94ae4a3658ac7..08521f8799533fe52a43de55b707975cb1eda6ae 100644
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -259,6 +259,18 @@ nsString gAbsoluteArgv0Path;
 extern "C" MFBT_API bool IsSignalHandlingBroken();
 #endif
 
+#ifdef LIBFUZZER
+#include "LibFuzzerRunner.h"
+
+namespace mozilla {
+LibFuzzerRunner* libFuzzerRunner = 0;
+} // namespace mozilla
+
+extern "C" MOZ_EXPORT void XRE_LibFuzzerSetMain(int argc, char** argv, LibFuzzerMain main) {
+  mozilla::libFuzzerRunner->setParams(argc, argv, main);
+}
+#endif
+
 namespace mozilla {
 int (*RunGTest)() = 0;
 } // namespace mozilla
@@ -3669,6 +3681,13 @@ XREMain::XRE_mainStartup(bool* aExitFlag)
     return 1;
 #endif /* MOZ_WIDGET_GTK */
 
+#ifdef LIBFUZZER
+  if (PR_GetEnv("LIBFUZZER")) {
+    *aExitFlag = true;
+    return mozilla::libFuzzerRunner->Run();
+  }
+#endif
+
   if (PR_GetEnv("MOZ_RUN_GTEST")) {
     int result;
 #ifdef XP_WIN
diff --git a/tools/fuzzing/libfuzzer/FuzzerCustomMain.cpp b/tools/fuzzing/libfuzzer/FuzzerCustomMain.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2293efd95d8ee1decf07b25004c7e0bc02925097
--- /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 0000000000000000000000000000000000000000..7ffe876852a4d65edd03cc035e59cc24bd03f174
--- /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 0000000000000000000000000000000000000000..6170362ac9fbf8fc2a41ce8c3b97e9045fe4b3a3
--- /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 0000000000000000000000000000000000000000..5390c91c2a4b7a7366a51da94cbf7846c4155ef6
--- /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 0000000000000000000000000000000000000000..e459ade33e7148957b5f8e75f51a053274bc0a56
--- /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 0000000000000000000000000000000000000000..2eda9d2dde54247b190ac28d8c7f93ecc5df6c31
--- /dev/null
+++ b/tools/fuzzing/libfuzzer/harness/LibFuzzerRunner.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 "LibFuzzerRunner.h"
+#include "mozilla/Attributes.h"
+#include "testing/TestHarness.h"
+#include "prenv.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 0000000000000000000000000000000000000000..c2362f4e99eca116ae1480d13a7296860b01118f
--- /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/moz.build b/tools/fuzzing/libfuzzer/harness/moz.build
new file mode 100644
index 0000000000000000000000000000000000000000..596018cb3c74f5570dc6b3bddcecf2091401364f
--- /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 0000000000000000000000000000000000000000..b37afdf9ce1fa9861134ad2fc46b0048c14e44d7
--- /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 0000000000000000000000000000000000000000..527b7c1d50b02fe7411cc355407758501e515049
--- /dev/null
+++ b/tools/fuzzing/moz.build
@@ -0,0 +1,10 @@
+# -*- 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/.
+
+if CONFIG['LIBFUZZER']:
+  DIRS += [
+    'libfuzzer',
+  ]
diff --git a/xpcom/build/nsXULAppAPI.h b/xpcom/build/nsXULAppAPI.h
index a87e85ab1445ce4b9818835b27ddd07c4657f842..7551cb20a1916ced3e34b21cc615ee90662cf75a 100644
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -520,4 +520,16 @@ XRE_API(void,
         XRE_GlibInit, ())
 #endif
 
+
+#ifdef LIBFUZZER
+#include "LibFuzzerRegistry.h"
+
+XRE_API(void,
+        XRE_LibFuzzerSetMain, (int, char**, LibFuzzerMain))
+
+XRE_API(void,
+        XRE_LibFuzzerGetFuncs, (const char*, LibFuzzerInitFunc*,
+                                LibFuzzerTestingFunc*))
+#endif // LIBFUZZER
+
 #endif // _nsXULAppAPI_h__