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_