tor-browser

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

testRegExp.cpp (3366B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 */
      4 /* This Source Code Form is subject to the terms of the Mozilla Public
      5 * License, v. 2.0. If a copy of the MPL was not distributed with this
      6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      7 
      8 #include "mozilla/ScopeExit.h"
      9 
     10 #include "jsapi.h"
     11 
     12 #include "fuzz-tests/tests.h"
     13 #include "irregexp/RegExpAPI.h"
     14 #include "vm/Interpreter.h"
     15 #include "vm/JSAtomUtils.h"  // AtomizeUTF8Chars
     16 #include "vm/MatchPairs.h"
     17 
     18 #include "vm/JSContext-inl.h"
     19 
     20 using namespace JS;
     21 using namespace js;
     22 
     23 extern JS::PersistentRootedObject gGlobal;
     24 extern JSContext* gCx;
     25 
     26 static int testRegExpInit(int* argc, char*** argv) { return 0; }
     27 
     28 static int testRegExpFuzz(const uint8_t* buf, size_t size) {
     29  auto gcGuard = mozilla::MakeScopeExit([&] {
     30    JS::PrepareForFullGC(gCx);
     31    JS::NonIncrementalGC(gCx, JS::GCOptions::Normal, JS::GCReason::API);
     32  });
     33 
     34  const uint32_t HEADER_LEN = 2;
     35  if (size <= HEADER_LEN) {
     36    return 0;
     37  }
     38 
     39  uint8_t rawFlags = buf[0];
     40  int32_t patternLength = buf[1];
     41 
     42  const uint32_t startIndex = 0;
     43 
     44  RegExpFlags flags(rawFlags & RegExpFlag::AllFlags);
     45 
     46  int32_t inputLength = size - HEADER_LEN - patternLength;
     47 
     48  const char* patternChars = reinterpret_cast<const char*>(buf + HEADER_LEN);
     49 
     50  const char* inputChars;
     51  if (inputLength < 0) {
     52    patternLength = size - HEADER_LEN;
     53 
     54    bool useUnicodeInput = (buf[1] & 1) == 0;
     55    inputChars = useUnicodeInput ? "Привет мир" : "Hello\nworld!";
     56    inputLength = strlen(inputChars);
     57  } else {
     58    inputChars = patternChars + patternLength;
     59  }
     60 
     61  Rooted<JSAtom*> pattern(gCx,
     62                          AtomizeUTF8Chars(gCx, patternChars, patternLength));
     63  if (!pattern) {
     64    ReportOutOfMemory(gCx);
     65    return 0;
     66  }
     67  Rooted<JSAtom*> input(gCx, AtomizeUTF8Chars(gCx, inputChars, inputLength));
     68  if (!input) {
     69    ReportOutOfMemory(gCx);
     70    return 0;
     71  }
     72 
     73  VectorMatchPairs interpretedMatches;
     74  VectorMatchPairs compiledMatches;
     75 
     76  RegExpRunStatus iStatus = irregexp::ExecuteForFuzzing(
     77      gCx, pattern, input, flags, startIndex, &interpretedMatches,
     78      RegExpShared::CodeKind::Bytecode);
     79  if (iStatus == RegExpRunStatus::Error) {
     80    if (gCx->isThrowingOverRecursed()) {
     81      return 0;
     82    }
     83    gCx->clearPendingException();
     84  }
     85  RegExpRunStatus cStatus = irregexp::ExecuteForFuzzing(
     86      gCx, pattern, input, flags, startIndex, &compiledMatches,
     87      RegExpShared::CodeKind::Jitcode);
     88  if (cStatus == RegExpRunStatus::Error) {
     89    if (gCx->isThrowingOverRecursed()) {
     90      return 0;
     91    }
     92    gCx->clearPendingException();
     93  }
     94 
     95  // Use release asserts to enable fuzzing on non-debug builds.
     96  MOZ_RELEASE_ASSERT(iStatus == cStatus);
     97  if (iStatus == RegExpRunStatus::Success) {
     98    MOZ_RELEASE_ASSERT(interpretedMatches.pairCount() ==
     99                       compiledMatches.pairCount());
    100    for (uint32_t i = 0; i < interpretedMatches.pairCount(); i++) {
    101      MOZ_RELEASE_ASSERT(
    102          interpretedMatches[i].start == compiledMatches[i].start &&
    103          interpretedMatches[i].limit == compiledMatches[i].limit);
    104    }
    105  }
    106  return 0;
    107 }
    108 
    109 MOZ_FUZZING_INTERFACE_RAW(testRegExpInit, /* init function */
    110                          testRegExpFuzz, /* fuzzing function */
    111                          RegExp          /* module name */
    112 );