tor-browser

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

gfxOTSUtils.h (6693B)


      1 /* -*- Mode: C++; tab-width: 20; 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
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #ifndef GFX_OTS_UTILS_H
      7 #define GFX_OTS_UTILS_H
      8 
      9 #include "gfxFontUtils.h"
     10 
     11 #include "opentype-sanitiser.h"
     12 
     13 struct gfxOTSMozAlloc {
     14  void* Grow(void* aPtr, size_t aLength) { return moz_xrealloc(aPtr, aLength); }
     15  void* ShrinkToFit(void* aPtr, size_t aLength) {
     16    return moz_xrealloc(aPtr, aLength);
     17  }
     18  void Free(void* aPtr) { free(aPtr); }
     19 };
     20 
     21 // Based on ots::ExpandingMemoryStream from ots-memory-stream.h,
     22 // adapted to use Mozilla allocators and to allow the final
     23 // memory buffer to be adopted by the client.
     24 template <typename AllocT = gfxOTSMozAlloc>
     25 class gfxOTSExpandingMemoryStream : public ots::OTSStream {
     26 public:
     27  // limit output/expansion to 256MB by default
     28  enum { DEFAULT_LIMIT = 256 * 1024 * 1024 };
     29 
     30  explicit gfxOTSExpandingMemoryStream(size_t initial,
     31                                       size_t limit = DEFAULT_LIMIT)
     32      : mLength(initial), mLimit(limit), mOff(0) {
     33    mPtr = mAlloc.Grow(nullptr, mLength);
     34  }
     35 
     36  ~gfxOTSExpandingMemoryStream() { mAlloc.Free(mPtr); }
     37 
     38  size_t size() override { return mLimit; }
     39 
     40  // Return the buffer, resized to fit its contents (as it may have been
     41  // over-allocated during growth), and give up ownership of it so the
     42  // caller becomes responsible to call free() when finished with it.
     43  auto forget() {
     44    auto p = mAlloc.ShrinkToFit(mPtr, mOff);
     45    mPtr = nullptr;
     46    return p;
     47  }
     48 
     49  bool WriteRaw(const void* data, size_t length) override {
     50    if ((mOff + length > mLength) ||
     51        (mLength > std::numeric_limits<size_t>::max() - mOff)) {
     52      if (mLength == mLimit) {
     53        return false;
     54      }
     55      size_t newLength = (mLength + 1) * 2;
     56      if (newLength < mLength) {
     57        return false;
     58      }
     59      if (newLength > mLimit) {
     60        newLength = mLimit;
     61      }
     62      mPtr = mAlloc.Grow(mPtr, newLength);
     63      mLength = newLength;
     64      return WriteRaw(data, length);
     65    }
     66    std::memcpy(static_cast<char*>(mPtr) + mOff, data, length);
     67    mOff += length;
     68    return true;
     69  }
     70 
     71  bool Seek(off_t position) override {
     72    if (position < 0) {
     73      return false;
     74    }
     75    if (static_cast<size_t>(position) > mLength) {
     76      return false;
     77    }
     78    mOff = position;
     79    return true;
     80  }
     81 
     82  off_t Tell() const override { return mOff; }
     83 
     84 private:
     85  AllocT mAlloc;
     86  void* mPtr;
     87  size_t mLength;
     88  const size_t mLimit;
     89  off_t mOff;
     90 };
     91 
     92 class MOZ_STACK_CLASS gfxOTSContext : public ots::OTSContext {
     93 public:
     94  gfxOTSContext() {
     95    using namespace mozilla;
     96 
     97    // Whether to apply OTS validation to OpenType Layout tables
     98    mCheckOTLTables = StaticPrefs::gfx_downloadable_fonts_otl_validation();
     99    // Whether to preserve Variation tables in downloaded fonts
    100    mCheckVariationTables =
    101        StaticPrefs::gfx_downloadable_fonts_validate_variation_tables();
    102    // Whether to preserve color bitmap glyphs
    103    mKeepColorBitmaps =
    104        StaticPrefs::gfx_downloadable_fonts_keep_color_bitmaps();
    105    // Whether to preserve SVG glyphs (which can be expensive in Core Text,
    106    // so better to drop them if we're not going to render them anyhow).
    107    mKeepSVG = StaticPrefs::gfx_font_rendering_opentype_svg_enabled();
    108  }
    109 
    110  virtual ots::TableAction GetTableAction(uint32_t aTag) override {
    111    // Pass through or validate OTL and Variation tables, depending on prefs.
    112    if (aTag == TRUETYPE_TAG('G', 'D', 'E', 'F') ||
    113        aTag == TRUETYPE_TAG('G', 'P', 'O', 'S') ||
    114        aTag == TRUETYPE_TAG('G', 'S', 'U', 'B')) {
    115      switch (mCheckOTLTables) {
    116        case 0:  // no validation
    117          return ots::TABLE_ACTION_PASSTHRU;
    118        case 1:  // validate, logging errors, but do not reject font
    119          return ots::TABLE_ACTION_SANITIZE_SOFT;
    120        case 2:  // validate, and reject font if errors are found
    121        default:
    122          return ots::TABLE_ACTION_SANITIZE;
    123      }
    124    }
    125    auto isVariationTable = [](uint32_t aTag) -> bool {
    126      return aTag == TRUETYPE_TAG('a', 'v', 'a', 'r') ||
    127             aTag == TRUETYPE_TAG('c', 'v', 'a', 'r') ||
    128             aTag == TRUETYPE_TAG('f', 'v', 'a', 'r') ||
    129             aTag == TRUETYPE_TAG('g', 'v', 'a', 'r') ||
    130             aTag == TRUETYPE_TAG('H', 'V', 'A', 'R') ||
    131             aTag == TRUETYPE_TAG('M', 'V', 'A', 'R') ||
    132             aTag == TRUETYPE_TAG('S', 'T', 'A', 'T') ||
    133             aTag == TRUETYPE_TAG('V', 'V', 'A', 'R');
    134    };
    135    if (!mCheckVariationTables && isVariationTable(aTag)) {
    136      return ots::TABLE_ACTION_PASSTHRU;
    137    }
    138    if (!gfxPlatform::HasVariationFontSupport() && isVariationTable(aTag)) {
    139      return ots::TABLE_ACTION_DROP;
    140    }
    141    // Preserve SVG table if OpenType-SVG rendering is enabled.
    142    if (aTag == TRUETYPE_TAG('S', 'V', 'G', ' ')) {
    143      return mKeepSVG ? ots::TABLE_ACTION_PASSTHRU : ots::TABLE_ACTION_DROP;
    144    }
    145    // Preserve BASE table; harfbuzz will sanitize it before using.
    146    if (aTag == TRUETYPE_TAG('B', 'A', 'S', 'E')) {
    147      return ots::TABLE_ACTION_PASSTHRU;
    148    }
    149    if (mKeepColorBitmaps && (aTag == TRUETYPE_TAG('C', 'B', 'D', 'T') ||
    150                              aTag == TRUETYPE_TAG('C', 'B', 'L', 'C'))) {
    151      return ots::TABLE_ACTION_PASSTHRU;
    152    }
    153    return ots::TABLE_ACTION_DEFAULT;
    154  }
    155 
    156  static size_t GuessSanitizedFontSize(size_t aLength,
    157                                       gfxUserFontType aFontType,
    158                                       bool aStrict = true) {
    159    switch (aFontType) {
    160      case GFX_USERFONT_UNKNOWN:
    161        // If being permissive of unknown types, make a reasonable guess
    162        // at how much room the sanitized font may take, if it passes. Just
    163        // enough extra space to accomodate some growth without excessive
    164        // bloat in case of large fonts. 1.5x is a reasonable compromise
    165        // for growable vectors in general.
    166        return aStrict || !aLength ? 0 : (aLength * 3) / 2;
    167      case GFX_USERFONT_WOFF:
    168        return aLength * 2;
    169      case GFX_USERFONT_WOFF2:
    170        return aLength * 3;
    171      default:
    172        return aLength;
    173    }
    174  }
    175 
    176  static size_t GuessSanitizedFontSize(const uint8_t* aData, size_t aLength,
    177                                       bool aStrict = true) {
    178    gfxUserFontType fontType =
    179        gfxFontUtils::DetermineFontDataType(aData, aLength);
    180    return GuessSanitizedFontSize(aLength, fontType, aStrict);
    181  }
    182 
    183 private:
    184  uint8_t mCheckOTLTables;
    185  bool mCheckVariationTables;
    186  bool mKeepColorBitmaps;
    187  bool mKeepSVG;
    188 };
    189 
    190 #endif /* GFX_OTS_UTILS_H */