tor-browser

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

TestJARFuzzing.cpp (5095B)


      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 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
      6 
      7 #include <iostream>
      8 
      9 #include "FuzzingInterface.h"
     10 #include "nsComponentManagerUtils.h"
     11 #include "nsCOMPtr.h"
     12 #include "nsIZipReader.h"
     13 #include "nsNetUtil.h"
     14 #include "nsNetCID.h"
     15 #include "nsPrintfCString.h"
     16 #include "nsString.h"
     17 #include "nsIInputStream.h"
     18 #include "nsIStringEnumerator.h"
     19 
     20 enum FuzzMethodType {
     21  eTest = 0,
     22  eGetEntry,
     23  eHasEntry,
     24  eFindEntries,
     25  eInputStream,
     26  eOpenInner,
     27  eLastMethod,
     28 };
     29 static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
     30 
     31 template <typename T>
     32 T jar_get_num(char** buf, size_t* size) {
     33  if (sizeof(T) > *size) {
     34    return 0;
     35  }
     36 
     37  T* iptr = reinterpret_cast<T*>(*buf);
     38  *buf += sizeof(T);
     39  *size -= sizeof(T);
     40  return *iptr;
     41 }
     42 
     43 nsAutoCString jar_get_string(char** buf, size_t* size) {
     44  uint8_t len = jar_get_num<uint8_t>(buf, size);
     45  if (len > *size) {
     46    len = static_cast<uint8_t>(*size);
     47  }
     48  nsAutoCString str(*buf, len);
     49 
     50  *buf += len;
     51  *size -= len;
     52  return str;
     53 }
     54 
     55 nsresult FuzzEntries(char** buf, size_t* size, nsIZipReader* aReader,
     56                     const nsACString& aName) {
     57  uint8_t iters = jar_get_num<uint8_t>(buf, size);
     58  nsresult rv;
     59  for (uint8_t i = 0; i < iters; ++i) {
     60    nsAutoCString out;
     61    uint64_t written;
     62    nsCOMPtr<nsIZipEntry> entry;
     63    nsCOMPtr<nsIInputStream> stream;
     64 
     65    switch (jar_get_num<uint8_t>(buf, size) % eLastMethod) {
     66      case eTest: {
     67        rv = aReader->Test(aName);
     68        NS_ENSURE_SUCCESS(rv, rv);
     69        break;
     70      }
     71      case eGetEntry: {
     72        rv = aReader->GetEntry(aName, getter_AddRefs(entry));
     73        NS_ENSURE_SUCCESS(rv, rv);
     74        break;
     75      }
     76      case eHasEntry: {
     77        bool has = false;
     78        rv = aReader->HasEntry(aName, &has);
     79        NS_ENSURE_SUCCESS(rv, rv);
     80        break;
     81      }
     82      case eInputStream:
     83        rv = aReader->GetInputStream(aName, getter_AddRefs(stream));
     84        NS_ENSURE_SUCCESS(rv, rv);
     85        if (NS_FAILED(rv)) {
     86          break;
     87        }
     88        rv = NS_ReadInputStreamToString(stream, out, -1, &written);
     89        NS_ENSURE_SUCCESS(rv, rv);
     90        break;
     91      default:
     92        break;
     93    }
     94  }
     95  return NS_OK;
     96 }
     97 
     98 nsresult FuzzReader(char** buf, size_t* size, nsIZipReader* aReader) {
     99  nsresult rv;
    100  nsAutoCString name;
    101  nsCOMPtr<nsIZipEntry> entry;
    102  bool has = false;
    103  nsAutoCString pattern;
    104  nsCOMPtr<nsIUTF8StringEnumerator> enumerator;
    105  nsCOMPtr<nsIInputStream> stream;
    106  bool hasMore;
    107  nsAutoCString out;
    108  uint64_t written;
    109  nsCOMPtr<nsIZipReader> newReader = do_CreateInstance(kZipReaderCID, &rv);
    110  switch (jar_get_num<uint8_t>(buf, size) % eLastMethod) {
    111    case eTest:
    112      rv = aReader->Test(""_ns);
    113      NS_ENSURE_SUCCESS(rv, rv);
    114      break;
    115    case eGetEntry:
    116      name = jar_get_string(buf, size);
    117      rv = aReader->GetEntry(name, getter_AddRefs(entry));
    118      NS_ENSURE_SUCCESS(rv, rv);
    119      break;
    120    case eHasEntry:
    121      name = jar_get_string(buf, size);
    122      rv = aReader->HasEntry(name, &has);
    123      NS_ENSURE_SUCCESS(rv, rv);
    124      break;
    125    case eFindEntries:
    126      pattern = jar_get_string(buf, size);
    127      rv = aReader->FindEntries(pattern, getter_AddRefs(enumerator));
    128      NS_ENSURE_SUCCESS(rv, rv);
    129      while (NS_SUCCEEDED(enumerator->HasMore(&hasMore)) && hasMore) {
    130        if (NS_FAILED(enumerator->GetNext(name))) {
    131          break;
    132        }
    133        rv = FuzzEntries(buf, size, aReader, name);
    134        NS_ENSURE_SUCCESS(rv, rv);
    135      }
    136 
    137      break;
    138    case eInputStream:
    139      name = jar_get_string(buf, size);
    140      rv = aReader->GetInputStream(name, getter_AddRefs(stream));
    141      NS_ENSURE_SUCCESS(rv, rv);
    142      rv = NS_ReadInputStreamToString(stream, out, -1, &written);
    143      NS_ENSURE_SUCCESS(rv, rv);
    144      break;
    145    case eOpenInner:
    146      name = jar_get_string(buf, size);
    147      rv = newReader->OpenInner(aReader, name);
    148      NS_ENSURE_SUCCESS(rv, rv);
    149      rv = FuzzReader(buf, size, newReader);
    150      NS_ENSURE_SUCCESS(rv, rv);
    151      break;
    152    default:
    153      break;
    154  }
    155  return rv;
    156 }
    157 
    158 static int FuzzingRunJARParser(const uint8_t* data, size_t size) {
    159  char* buf = (char*)data;
    160  nsresult rv;
    161 
    162  nsCOMPtr<nsIURI> uri;
    163  nsAutoCString jardata = jar_get_string(&buf, &size);
    164 
    165  nsCOMPtr<nsIZipReader> reader = do_CreateInstance(kZipReaderCID, &rv);
    166  rv = reader->OpenMemory((void*)jardata.get(), jardata.Length());
    167  NS_ENSURE_SUCCESS(rv, 0);
    168 
    169 #if 0
    170  // For easily exporting the last test case that triggered a crash.
    171  FILE * f = fopen("/tmp/input.jar", "wb");
    172  fwrite((void*)jardata.get(), 1, jardata.Length(), f);
    173  fclose(f);
    174 #endif
    175 
    176  uint8_t iters = jar_get_num<uint8_t>(&buf, &size);
    177  for (uint8_t i = 0; i < iters; ++i) {
    178    rv = FuzzReader(&buf, &size, reader);
    179    NS_ENSURE_SUCCESS(rv, 0);
    180  }
    181 
    182  return 0;
    183 }
    184 
    185 MOZ_FUZZING_INTERFACE_RAW(nullptr, FuzzingRunJARParser, JARParser);