tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

FuzzURLPattern.cpp (5116B)


      1 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      4 * You can obtain one at http://mozilla.org/MPL/2.0/.
      5 */
      6 #include "FuzzedDataProvider.h"
      7 #include "FuzzingInterface.h"
      8 #include "js/RootingAPI.h"                    // JS::PersistentRooted
      9 #include "mozilla/ErrorResult.h"              // ErrorResult
     10 #include "mozilla/dom/BindingDeclarations.h"  // GlobalObject
     11 #include "mozilla/dom/ScriptSettings.h"       // AutoJSAPI
     12 #include "mozilla/dom/SimpleGlobalObject.h"   // SimpleGlobalObject
     13 #include "mozilla/dom/URLPattern.h"           // URLPattern class
     14 #include "mozilla/dom/URLPatternBinding.h"  // UTF8StringOrURLPatternInit, URLPatternOptions
     15 #include "nsReadableUtils.h"                // CopyUTF8toUTF16, CopyUTF16toUTF8
     16 
     17 using namespace mozilla;
     18 using namespace mozilla::dom;
     19 
     20 static MOZ_RUNINIT JS::PersistentRooted<JSObject*> global;
     21 
     22 static int FuzzingInit(int* argc, char*** argv) {
     23  JSObject* simpleGlobal =
     24      SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
     25  global.init(mozilla::dom::RootingCx());
     26  global.set(simpleGlobal);
     27  return 0;
     28 }
     29 
     30 // Helper function to simulate JS->WebIDL UTF8String conversion
     31 static void SanitizeToUTF8(const std::string& input, nsACString& output) {
     32  nsAutoString utf16;
     33  CopyUTF8toUTF16(mozilla::Span(input.data(), input.length()), utf16);
     34  CopyUTF16toUTF8(utf16, output);
     35 }
     36 
     37 // Helper function to create an optional baseURL string
     38 static void MaybeCreateBaseURL(FuzzedDataProvider& fdp,
     39                               Optional<nsACString>& base, nsCString& baseUrl) {
     40  if (fdp.ConsumeBool()) {
     41    std::string str = fdp.ConsumeRandomLengthString();
     42    SanitizeToUTF8(str, baseUrl);
     43    base = &baseUrl;
     44  }
     45 }
     46 
     47 static void CreateURLPatternInput(FuzzedDataProvider& fdp,
     48                                  UTF8StringOrURLPatternInit& input) {
     49  if (fdp.ConsumeBool()) {
     50    // URLPatternInit
     51    auto maybeSetField = [&fdp](auto& field) {
     52      if (fdp.ConsumeBool()) {
     53        std::string str = fdp.ConsumeRandomLengthString();
     54        nsCString sanitized;
     55        SanitizeToUTF8(str, sanitized);
     56        field.Construct(sanitized);
     57      }
     58    };
     59 
     60    URLPatternInit& init = input.SetAsURLPatternInit();
     61    maybeSetField(init.mProtocol);
     62    maybeSetField(init.mUsername);
     63    maybeSetField(init.mPassword);
     64    maybeSetField(init.mHostname);
     65    maybeSetField(init.mPort);
     66    maybeSetField(init.mPathname);
     67    maybeSetField(init.mSearch);
     68    maybeSetField(init.mHash);
     69    maybeSetField(init.mBaseURL);
     70  } else {
     71    // Plain UTF8String
     72    std::string str = fdp.ConsumeRandomLengthString();
     73    auto& utf8Str = input.RawSetAsUTF8String();
     74    SanitizeToUTF8(str, *reinterpret_cast<nsCString*>(&utf8Str));
     75  }
     76 }
     77 
     78 static int FuzzingRunURLPattern(const uint8_t* data, size_t size) {
     79  FuzzedDataProvider fdp(data, size);
     80 
     81  AutoJSAPI jsapi;
     82  MOZ_RELEASE_ASSERT(jsapi.Init(global));
     83  JSContext* cx = jsapi.cx();
     84  GlobalObject globalObj(cx, global);
     85 
     86  UTF8StringOrURLPatternInit input;
     87  CreateURLPatternInput(fdp, input);
     88 
     89  URLPatternOptions options;
     90  options.mIgnoreCase = fdp.ConsumeBool();
     91 
     92  ErrorResult rv;
     93 
     94  RefPtr<URLPattern> pattern;
     95  if (fdp.ConsumeBool()) {
     96    pattern = URLPattern::Constructor(globalObj, input, options, rv);
     97  } else {
     98    nsCString base;
     99    std::string str = fdp.ConsumeRandomLengthString();
    100    SanitizeToUTF8(str, base);
    101    pattern = URLPattern::Constructor(globalObj, input, base, options, rv);
    102  }
    103 
    104  if (MOZ_UNLIKELY(rv.Failed())) {
    105    return 0;
    106  }
    107 
    108  // Table of getters
    109  using GetterFunc = void (URLPattern::*)(nsACString&) const;
    110  static const GetterFunc kGetters[] = {
    111      &URLPattern::GetProtocol, &URLPattern::GetUsername,
    112      &URLPattern::GetPassword, &URLPattern::GetHostname,
    113      &URLPattern::GetPort,     &URLPattern::GetPathname,
    114      &URLPattern::GetSearch,   &URLPattern::GetHash,
    115  };
    116 
    117  while (fdp.remaining_bytes() > 0) {
    118    uint8_t operation = fdp.ConsumeIntegralInRange<uint8_t>(0, 10);
    119    if (operation <= 7) {
    120      // Access getters
    121      nsAutoCString result;
    122      (pattern.get()->*kGetters[operation])(result);
    123    } else if (operation == 8) {
    124      (void)pattern->HasRegExpGroups();
    125    } else if (operation == 9) {
    126      // Test
    127      UTF8StringOrURLPatternInit testInput;
    128      CreateURLPatternInput(fdp, testInput);
    129 
    130      Optional<nsACString> base;
    131      nsCString baseUrl;
    132      MaybeCreateBaseURL(fdp, base, baseUrl);
    133 
    134      ErrorResult testRv;
    135      (void)pattern->Test(testInput, base, testRv);
    136    } else if (operation == 10) {
    137      // Exec
    138      UTF8StringOrURLPatternInit execInput;
    139      CreateURLPatternInput(fdp, execInput);
    140 
    141      Optional<nsACString> base;
    142      nsCString baseUrl;
    143      MaybeCreateBaseURL(fdp, base, baseUrl);
    144 
    145      Nullable<URLPatternResult> result;
    146      ErrorResult execRv;
    147      pattern->Exec(execInput, base, result, execRv);
    148    }
    149  }
    150 
    151  return 0;
    152 }
    153 
    154 MOZ_FUZZING_INTERFACE_RAW(FuzzingInit, FuzzingRunURLPattern, URLPattern);