1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 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);
|