tor-browser

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

ots.h (10246B)


      1 // Copyright (c) 2009-2017 The OTS Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef OTS_H_
      6 #define OTS_H_
      7 
      8 #ifdef HAVE_CONFIG_H
      9 #include "config.h"
     10 #endif
     11 
     12 #include <stddef.h>
     13 #include <cstdarg>
     14 #include <cstddef>
     15 #include <cstdio>
     16 #include <cstdlib>
     17 #include <cstring>
     18 #include <limits>
     19 #include <map>
     20 
     21 #include "opentype-sanitiser.h"
     22 
     23 // arraysize borrowed from base/basictypes.h
     24 template <typename T, size_t N>
     25 char (&ArraySizeHelper(T (&array)[N]))[N];
     26 #define arraysize(array) (sizeof(ArraySizeHelper(array)))
     27 
     28 namespace ots {
     29 
     30 #if !defined(OTS_DEBUG)
     31 #define OTS_FAILURE() false
     32 #else
     33 #define OTS_FAILURE() \
     34  (\
     35    std::fprintf(stderr, "ERROR at %s:%d (%s)\n", \
     36                 __FILE__, __LINE__, __FUNCTION__) \
     37    && false\
     38  )
     39 #endif
     40 
     41 // All OTS_FAILURE_* macros ultimately evaluate to 'false', just like the original
     42 // message-less OTS_FAILURE(), so that the current parser will return 'false' as
     43 // its result (indicating a failure).
     44 
     45 #if !defined(OTS_DEBUG)
     46 #define OTS_MESSAGE_(level,otf_,...) \
     47  (otf_)->context->Message(level,__VA_ARGS__)
     48 #else
     49 #define OTS_MESSAGE_(level,otf_,...) \
     50  OTS_FAILURE(), \
     51  (otf_)->context->Message(level,__VA_ARGS__)
     52 #endif
     53 
     54 // Generate a simple message
     55 #define OTS_FAILURE_MSG_(otf_,...) \
     56  (OTS_MESSAGE_(0,otf_,__VA_ARGS__), false)
     57 
     58 #define OTS_WARNING_MSG_(otf_,...) \
     59  OTS_MESSAGE_(1,otf_,__VA_ARGS__)
     60 
     61 // Convenience macros for use in files that only handle a single table tag,
     62 // defined as TABLE_NAME at the top of the file; the 'file' variable is
     63 // expected to be the current FontFile pointer.
     64 #define OTS_FAILURE_MSG(...) OTS_FAILURE_MSG_(font->file, TABLE_NAME ": " __VA_ARGS__)
     65 
     66 #define OTS_WARNING(...) OTS_WARNING_MSG_(font->file, TABLE_NAME ": " __VA_ARGS__)
     67 
     68 // -----------------------------------------------------------------------------
     69 // Buffer helper class
     70 //
     71 // This class perform some trival buffer operations while checking for
     72 // out-of-bounds errors. As a family they return false if anything is amiss,
     73 // updating the current offset otherwise.
     74 // -----------------------------------------------------------------------------
     75 class Buffer {
     76 public:
     77  Buffer(const uint8_t *buf, size_t len)
     78      : buffer_(buf),
     79        length_(len),
     80        offset_(0) { }
     81 
     82  bool Skip(size_t n_bytes) {
     83    return Read(NULL, n_bytes);
     84  }
     85 
     86  bool Read(uint8_t *buf, size_t n_bytes) {
     87    if (n_bytes > 1024 * 1024 * 1024) {
     88      return OTS_FAILURE();
     89    }
     90    if (length_ < n_bytes || offset_ > length_ - n_bytes) {
     91      return OTS_FAILURE();
     92    }
     93    if (buf) {
     94      std::memcpy(buf, buffer_ + offset_, n_bytes);
     95    }
     96    offset_ += n_bytes;
     97    return true;
     98  }
     99 
    100  inline bool ReadU8(uint8_t *value) {
    101    if (length_ < 1 || offset_ > length_ - 1) {
    102      return OTS_FAILURE();
    103    }
    104    *value = buffer_[offset_];
    105    ++offset_;
    106    return true;
    107  }
    108 
    109  bool ReadU16(uint16_t *value) {
    110    if (length_ < 2 || offset_ > length_ - 2) {
    111      return OTS_FAILURE();
    112    }
    113    std::memcpy(value, buffer_ + offset_, sizeof(uint16_t));
    114    *value = ots_ntohs(*value);
    115    offset_ += 2;
    116    return true;
    117  }
    118 
    119  bool ReadS16(int16_t *value) {
    120    return ReadU16(reinterpret_cast<uint16_t*>(value));
    121  }
    122 
    123  bool ReadU24(uint32_t *value) {
    124    if (length_ < 3 || offset_ > length_ - 3) {
    125      return OTS_FAILURE();
    126    }
    127    *value = static_cast<uint32_t>(buffer_[offset_]) << 16 |
    128        static_cast<uint32_t>(buffer_[offset_ + 1]) << 8 |
    129        static_cast<uint32_t>(buffer_[offset_ + 2]);
    130    offset_ += 3;
    131    return true;
    132  }
    133 
    134  bool ReadU32(uint32_t *value) {
    135    if (length_ < 4 || offset_ > length_ - 4) {
    136      return OTS_FAILURE();
    137    }
    138    std::memcpy(value, buffer_ + offset_, sizeof(uint32_t));
    139    *value = ots_ntohl(*value);
    140    offset_ += 4;
    141    return true;
    142  }
    143 
    144  bool ReadS32(int32_t *value) {
    145    return ReadU32(reinterpret_cast<uint32_t*>(value));
    146  }
    147 
    148  bool ReadR64(uint64_t *value) {
    149    if (length_ < 8 || offset_ > length_ - 8) {
    150      return OTS_FAILURE();
    151    }
    152    std::memcpy(value, buffer_ + offset_, sizeof(uint64_t));
    153    offset_ += 8;
    154    return true;
    155  }
    156 
    157  const uint8_t *buffer() const { return buffer_; }
    158  size_t offset() const { return offset_; }
    159  size_t length() const { return length_; }
    160  size_t remaining() const { return length_ - offset_; }
    161 
    162  void set_offset(size_t newoffset) { offset_ = newoffset; }
    163 
    164 private:
    165  const uint8_t * const buffer_;
    166  const size_t length_;
    167  size_t offset_;
    168 };
    169 
    170 // Round a value up to the nearest multiple of 4. Don't round the value in the
    171 // case that rounding up overflows.
    172 template<typename T> T Round4(T value) {
    173  if (std::numeric_limits<T>::max() - value < 3) {
    174    return value;
    175  }
    176  return (value + 3) & ~3;
    177 }
    178 
    179 template<typename T> T Round2(T value) {
    180  if (value == std::numeric_limits<T>::max()) {
    181    return value;
    182  }
    183  return (value + 1) & ~1;
    184 }
    185 
    186 // Check that a tag consists entirely of printable ASCII characters
    187 bool CheckTag(uint32_t tag_value);
    188 
    189 #define OTS_TAG_CFF  OTS_TAG('C','F','F',' ')
    190 #define OTS_TAG_CFF2 OTS_TAG('C','F','F','2')
    191 #define OTS_TAG_CMAP OTS_TAG('c','m','a','p')
    192 #define OTS_TAG_COLR OTS_TAG('C','O','L','R')
    193 #define OTS_TAG_CPAL OTS_TAG('C','P','A','L')
    194 #define OTS_TAG_CVT  OTS_TAG('c','v','t',' ')
    195 #define OTS_TAG_FEAT OTS_TAG('F','e','a','t')
    196 #define OTS_TAG_FPGM OTS_TAG('f','p','g','m')
    197 #define OTS_TAG_GASP OTS_TAG('g','a','s','p')
    198 #define OTS_TAG_GDEF OTS_TAG('G','D','E','F')
    199 #define OTS_TAG_GLAT OTS_TAG('G','l','a','t')
    200 #define OTS_TAG_GLOC OTS_TAG('G','l','o','c')
    201 #define OTS_TAG_GLYF OTS_TAG('g','l','y','f')
    202 #define OTS_TAG_GPOS OTS_TAG('G','P','O','S')
    203 #define OTS_TAG_GSUB OTS_TAG('G','S','U','B')
    204 #define OTS_TAG_HDMX OTS_TAG('h','d','m','x')
    205 #define OTS_TAG_HEAD OTS_TAG('h','e','a','d')
    206 #define OTS_TAG_HHEA OTS_TAG('h','h','e','a')
    207 #define OTS_TAG_HMTX OTS_TAG('h','m','t','x')
    208 #define OTS_TAG_KERN OTS_TAG('k','e','r','n')
    209 #define OTS_TAG_LOCA OTS_TAG('l','o','c','a')
    210 #define OTS_TAG_LTSH OTS_TAG('L','T','S','H')
    211 #define OTS_TAG_MATH OTS_TAG('M','A','T','H')
    212 #define OTS_TAG_MAXP OTS_TAG('m','a','x','p')
    213 #define OTS_TAG_NAME OTS_TAG('n','a','m','e')
    214 #define OTS_TAG_OS2  OTS_TAG('O','S','/','2')
    215 #define OTS_TAG_POST OTS_TAG('p','o','s','t')
    216 #define OTS_TAG_PREP OTS_TAG('p','r','e','p')
    217 #define OTS_TAG_SILE OTS_TAG('S','i','l','e')
    218 #define OTS_TAG_SILF OTS_TAG('S','i','l','f')
    219 #define OTS_TAG_SILL OTS_TAG('S','i','l','l')
    220 #define OTS_TAG_VDMX OTS_TAG('V','D','M','X')
    221 #define OTS_TAG_VHEA OTS_TAG('v','h','e','a')
    222 #define OTS_TAG_VMTX OTS_TAG('v','m','t','x')
    223 #define OTS_TAG_VORG OTS_TAG('V','O','R','G')
    224 
    225 #define OTS_TAG_AVAR OTS_TAG('a','v','a','r')
    226 #define OTS_TAG_CVAR OTS_TAG('c','v','a','r')
    227 #define OTS_TAG_FVAR OTS_TAG('f','v','a','r')
    228 #define OTS_TAG_GVAR OTS_TAG('g','v','a','r')
    229 #define OTS_TAG_HVAR OTS_TAG('H','V','A','R')
    230 #define OTS_TAG_MVAR OTS_TAG('M','V','A','R')
    231 #define OTS_TAG_VVAR OTS_TAG('V','V','A','R')
    232 #define OTS_TAG_STAT OTS_TAG('S','T','A','T')
    233 
    234 // See https://github.com/khaledhosny/ots/issues/219
    235 #define OTS_MAX_DECOMPRESSED_FILE_SIZE 300 * 1024 * 1024
    236 #define OTS_MAX_DECOMPRESSED_TABLE_SIZE 150 * 1024 * 1024
    237 
    238 struct Font;
    239 struct FontFile;
    240 struct TableEntry;
    241 struct Arena;
    242 
    243 class Table {
    244 public:
    245  explicit Table(Font *font, uint32_t tag, uint32_t type)
    246      : m_tag(tag),
    247        m_type(type),
    248        m_font(font),
    249        m_shouldSerialize(true) {
    250  }
    251 
    252  virtual ~Table() { }
    253 
    254  virtual bool Parse(const uint8_t *data, size_t length) = 0;
    255  virtual bool Serialize(OTSStream *out) = 0;
    256  virtual bool ShouldSerialize();
    257 
    258  // Return the tag (table type) this Table was parsed as, to support
    259  // "poor man's RTTI" so that we know if we can safely down-cast to
    260  // a specific Table subclass. The m_type field is initialized to the
    261  // appropriate tag when a subclass is constructed, or to zero for
    262  // TablePassthru (indicating unparsed data).
    263  uint32_t Type() { return m_type; }
    264 
    265  // Return the tag assigned when this table was constructed.
    266  uint32_t Tag() { return m_tag; }
    267 
    268  Font* GetFont() { return m_font; }
    269 
    270  bool Error(const char *format, ...);
    271  bool Warning(const char *format, ...);
    272  bool Drop(const char *format, ...);
    273  bool DropGraphite(const char *format, ...);
    274  bool DropVariations(const char *format, ...);
    275 
    276 private:
    277  void Message(int level, const char *format, va_list va);
    278 
    279  uint32_t m_tag;
    280  uint32_t m_type;
    281  Font *m_font;
    282  bool m_shouldSerialize;
    283 };
    284 
    285 class TablePassthru : public Table {
    286 public:
    287  explicit TablePassthru(Font *font, uint32_t tag)
    288      : Table(font, tag, 0),
    289        m_data(NULL),
    290        m_length(0) {
    291  }
    292 
    293  bool Parse(const uint8_t *data, size_t length);
    294  bool Serialize(OTSStream *out);
    295 
    296 private:
    297  const uint8_t *m_data;
    298  size_t m_length;
    299 };
    300 
    301 struct Font {
    302  explicit Font(FontFile *f)
    303      : file(f),
    304        version(0),
    305        num_tables(0),
    306        search_range(0),
    307        entry_selector(0),
    308        range_shift(0) {
    309  }
    310 
    311  bool ParseTable(const TableEntry& tableinfo, const uint8_t* data,
    312                  Arena &arena);
    313  Table* GetTable(uint32_t tag) const;
    314 
    315  // This checks that the returned Table is actually of the correct subclass
    316  // for |tag|, so it can safely be downcast to the corresponding OpenTypeXXXX;
    317  // if not (i.e. if the table was treated as Passthru), it will return NULL.
    318  Table* GetTypedTable(uint32_t tag) const;
    319 
    320  // Insert a new table. Asserts if a table with the same tag already exists.
    321  void AddTable(TableEntry entry, Table* table);
    322 
    323  // Drop all Graphite tables and don't parse new ones.
    324  void DropGraphite();
    325 
    326  // Drop all Variations tables and don't parse new ones.
    327  void DropVariations();
    328 
    329  FontFile *file;
    330 
    331  uint32_t version;
    332  uint16_t num_tables;
    333  uint16_t search_range;
    334  uint16_t entry_selector;
    335  uint16_t range_shift;
    336 
    337 private:
    338  std::map<uint32_t, Table*> m_tables;
    339 };
    340 
    341 struct TableEntry {
    342  uint32_t tag;
    343  uint32_t offset;
    344  uint32_t length;
    345  uint32_t uncompressed_length;
    346  uint32_t chksum;
    347 
    348  bool operator<(const TableEntry& other) const {
    349    return tag < other.tag;
    350  }
    351 };
    352 
    353 struct FontFile {
    354  ~FontFile();
    355 
    356  OTSContext *context;
    357  std::map<TableEntry, Table*> tables;
    358  std::map<uint32_t, TableEntry> table_entries;
    359 };
    360 
    361 }  // namespace ots
    362 
    363 #endif  // OTS_H_