157 lines
5.0 KiB
C++
157 lines
5.0 KiB
C++
/* 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 constinit 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())) {
|
|
rv.SuppressException();
|
|
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);
|
|
testRv.SuppressException();
|
|
} 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);
|
|
execRv.SuppressException();
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
MOZ_FUZZING_INTERFACE_RAW(FuzzingInit, FuzzingRunURLPattern, URLPattern);
|