commit bcb27f714ab3d80877fe1c29c90310bf839f54f0
parent dd5db50db5d86b0619da53f2acaef6d9b6354802
Author: pyoor <pyoor@users.noreply.github.com>
Date: Thu, 20 Nov 2025 03:23:51 +0000
Bug 1998504 - Add Fuzz Target for URLPattern. r=truber,edgul
Differential Revision: https://phabricator.services.mozilla.com/D271461
Diffstat:
3 files changed, 185 insertions(+), 0 deletions(-)
diff --git a/dom/urlpattern/fuzztest/FuzzURLPattern.cpp b/dom/urlpattern/fuzztest/FuzzURLPattern.cpp
@@ -0,0 +1,154 @@
+/* -*- Mode: IDL; 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 "FuzzedDataProvider.h"
+#include "FuzzingInterface.h"
+#include "js/RootingAPI.h" // JS::PersistentRooted
+#include "mozilla/ErrorResult.h" // ErrorResult
+#include "mozilla/dom/BindingDeclarations.h" // GlobalObject
+#include "mozilla/dom/ScriptSettings.h" // AutoJSAPI
+#include "mozilla/dom/SimpleGlobalObject.h" // SimpleGlobalObject
+#include "mozilla/dom/URLPattern.h" // URLPattern class
+#include "mozilla/dom/URLPatternBinding.h" // UTF8StringOrURLPatternInit, URLPatternOptions
+#include "nsReadableUtils.h" // CopyUTF8toUTF16, CopyUTF16toUTF8
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+static MOZ_RUNINIT JS::PersistentRooted<JSObject*> global;
+
+static int FuzzingInit(int* argc, char*** argv) {
+ JSObject* simpleGlobal =
+ SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
+ global.init(mozilla::dom::RootingCx());
+ global.set(simpleGlobal);
+ return 0;
+}
+
+// Helper function to simulate JS->WebIDL UTF8String conversion
+static void SanitizeToUTF8(const std::string& input, nsACString& output) {
+ nsAutoString utf16;
+ CopyUTF8toUTF16(mozilla::Span(input.data(), input.length()), utf16);
+ CopyUTF16toUTF8(utf16, output);
+}
+
+// Helper function to create an optional baseURL string
+static void MaybeCreateBaseURL(FuzzedDataProvider& fdp,
+ Optional<nsACString>& base, nsCString& baseUrl) {
+ if (fdp.ConsumeBool()) {
+ std::string str = fdp.ConsumeRandomLengthString();
+ SanitizeToUTF8(str, baseUrl);
+ base = &baseUrl;
+ }
+}
+
+static void CreateURLPatternInput(FuzzedDataProvider& fdp,
+ UTF8StringOrURLPatternInit& input) {
+ if (fdp.ConsumeBool()) {
+ // URLPatternInit
+ auto maybeSetField = [&fdp](auto& field) {
+ if (fdp.ConsumeBool()) {
+ std::string str = fdp.ConsumeRandomLengthString();
+ nsCString sanitized;
+ SanitizeToUTF8(str, sanitized);
+ field.Construct(sanitized);
+ }
+ };
+
+ URLPatternInit& init = input.SetAsURLPatternInit();
+ maybeSetField(init.mProtocol);
+ maybeSetField(init.mUsername);
+ maybeSetField(init.mPassword);
+ maybeSetField(init.mHostname);
+ maybeSetField(init.mPort);
+ maybeSetField(init.mPathname);
+ maybeSetField(init.mSearch);
+ maybeSetField(init.mHash);
+ maybeSetField(init.mBaseURL);
+ } else {
+ // Plain UTF8String
+ std::string str = fdp.ConsumeRandomLengthString();
+ auto& utf8Str = input.RawSetAsUTF8String();
+ SanitizeToUTF8(str, *reinterpret_cast<nsCString*>(&utf8Str));
+ }
+}
+
+static int FuzzingRunURLPattern(const uint8_t* data, size_t size) {
+ FuzzedDataProvider fdp(data, size);
+
+ AutoJSAPI jsapi;
+ MOZ_RELEASE_ASSERT(jsapi.Init(global));
+ JSContext* cx = jsapi.cx();
+ GlobalObject globalObj(cx, global);
+
+ UTF8StringOrURLPatternInit input;
+ CreateURLPatternInput(fdp, input);
+
+ URLPatternOptions options;
+ options.mIgnoreCase = fdp.ConsumeBool();
+
+ ErrorResult rv;
+
+ RefPtr<URLPattern> pattern;
+ if (fdp.ConsumeBool()) {
+ pattern = URLPattern::Constructor(globalObj, input, options, rv);
+ } else {
+ nsCString base;
+ std::string str = fdp.ConsumeRandomLengthString();
+ SanitizeToUTF8(str, base);
+ pattern = URLPattern::Constructor(globalObj, input, base, options, rv);
+ }
+
+ if (MOZ_UNLIKELY(rv.Failed())) {
+ return 0;
+ }
+
+ // Table of getters
+ using GetterFunc = void (URLPattern::*)(nsACString&) const;
+ static const GetterFunc kGetters[] = {
+ &URLPattern::GetProtocol, &URLPattern::GetUsername,
+ &URLPattern::GetPassword, &URLPattern::GetHostname,
+ &URLPattern::GetPort, &URLPattern::GetPathname,
+ &URLPattern::GetSearch, &URLPattern::GetHash,
+ };
+
+ while (fdp.remaining_bytes() > 0) {
+ uint8_t operation = fdp.ConsumeIntegralInRange<uint8_t>(0, 10);
+ if (operation <= 7) {
+ // Access getters
+ nsAutoCString result;
+ (pattern.get()->*kGetters[operation])(result);
+ } else if (operation == 8) {
+ (void)pattern->HasRegExpGroups();
+ } else if (operation == 9) {
+ // Test
+ UTF8StringOrURLPatternInit testInput;
+ CreateURLPatternInput(fdp, testInput);
+
+ Optional<nsACString> base;
+ nsCString baseUrl;
+ MaybeCreateBaseURL(fdp, base, baseUrl);
+
+ ErrorResult testRv;
+ (void)pattern->Test(testInput, base, testRv);
+ } else if (operation == 10) {
+ // Exec
+ UTF8StringOrURLPatternInit execInput;
+ CreateURLPatternInput(fdp, execInput);
+
+ Optional<nsACString> base;
+ nsCString baseUrl;
+ MaybeCreateBaseURL(fdp, base, baseUrl);
+
+ Nullable<URLPatternResult> result;
+ ErrorResult execRv;
+ pattern->Exec(execInput, base, result, execRv);
+ }
+ }
+
+ return 0;
+}
+
+MOZ_FUZZING_INTERFACE_RAW(FuzzingInit, FuzzingRunURLPattern, URLPattern);
diff --git a/dom/urlpattern/fuzztest/moz.build b/dom/urlpattern/fuzztest/moz.build
@@ -0,0 +1,24 @@
+# -*- Mode: python; 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("FuzzingURLPattern")
+
+SOURCES += [
+ "FuzzURLPattern.cpp",
+]
+
+LOCAL_INCLUDES += [
+ "/dom/base",
+ "/dom/ipc",
+ "/dom/urlpattern",
+]
+
+include("/ipc/chromium/chromium-config.mozbuild")
+
+# Add libFuzzer configuration directives
+include("/tools/fuzzing/libfuzzer-config.mozbuild")
+
+FINAL_LIBRARY = "xul-gtest"
diff --git a/dom/urlpattern/moz.build b/dom/urlpattern/moz.build
@@ -11,6 +11,13 @@ EXPORTS.mozilla.dom += [
"URLPattern.h",
]
+if CONFIG["FUZZING"]:
+ if CONFIG["FUZZING_INTERFACES"]:
+ TEST_DIRS += ["fuzztest"]
+
+# Add libFuzzer configuration directives
+include("/tools/fuzzing/libfuzzer-config.mozbuild")
+
UNIFIED_SOURCES += ["URLPattern.cpp"]
FINAL_LIBRARY = "xul"