Line | Count | Source |
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 | 9.09k | #define OTS_FAILURE() false |
32 | | #else |
33 | | #define OTS_FAILURE() \ |
34 | 1.29M | (\ |
35 | 1.29M | std::fprintf(stderr, "ERROR at %s:%d (%s)\n", \ |
36 | 1.29M | __FILE__, __LINE__, __FUNCTION__) \ |
37 | 1.29M | && false\ |
38 | 1.29M | ) |
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 | 1.23M | OTS_FAILURE(), \ |
51 | 1.23M | (otf_)->context->Message(level,__VA_ARGS__) |
52 | | #endif |
53 | | |
54 | | // Generate a simple message |
55 | | #define OTS_FAILURE_MSG_(otf_,...) \ |
56 | 34.0k | (OTS_MESSAGE_(0,otf_,__VA_ARGS__), false) |
57 | | |
58 | | #define OTS_WARNING_MSG_(otf_,...) \ |
59 | 1.14M | 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 | 23.4k | #define OTS_FAILURE_MSG(...) OTS_FAILURE_MSG_(font->file, TABLE_NAME ": " __VA_ARGS__) |
65 | | |
66 | 65.1k | #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 | 173M | : buffer_(buf), |
79 | 173M | length_(len), |
80 | 173M | offset_(0) { } |
81 | | |
82 | 165M | bool Skip(size_t n_bytes) { |
83 | 165M | return Read(NULL, n_bytes); |
84 | 165M | } |
85 | | |
86 | 165M | bool Read(uint8_t *buf, size_t n_bytes) { |
87 | 165M | if (n_bytes > 1024 * 1024 * 1024) { |
88 | 0 | return OTS_FAILURE(); |
89 | 0 | } |
90 | 165M | if (length_ < n_bytes || offset_ > length_ - n_bytes) { |
91 | 0 | return OTS_FAILURE(); |
92 | 0 | } |
93 | 165M | if (buf) { |
94 | 165M | std::memcpy(buf, buffer_ + offset_, n_bytes); |
95 | 165M | } |
96 | 165M | offset_ += n_bytes; |
97 | 165M | return true; |
98 | 165M | } |
99 | | |
100 | 117M | inline bool ReadU8(uint8_t *value) { |
101 | 117M | if (length_ < 1 || offset_ > length_ - 1) { |
102 | 3.13k | return OTS_FAILURE(); |
103 | 3.13k | } |
104 | 117M | *value = buffer_[offset_]; |
105 | 117M | ++offset_; |
106 | 117M | return true; |
107 | 117M | } |
108 | | |
109 | 318M | bool ReadU16(uint16_t *value) { |
110 | 318M | if (length_ < 2 || offset_ > length_ - 2) { |
111 | 44.1k | return OTS_FAILURE(); |
112 | 44.1k | } |
113 | 318M | std::memcpy(value, buffer_ + offset_, sizeof(uint16_t)); |
114 | 318M | *value = ots_ntohs(*value); |
115 | 318M | offset_ += 2; |
116 | 318M | return true; |
117 | 318M | } |
118 | | |
119 | 36.4M | bool ReadS16(int16_t *value) { |
120 | 36.4M | return ReadU16(reinterpret_cast<uint16_t*>(value)); |
121 | 36.4M | } |
122 | | |
123 | 232k | bool ReadU24(uint32_t *value) { |
124 | 232k | if (length_ < 3 || offset_ > length_ - 3) { |
125 | 27 | return OTS_FAILURE(); |
126 | 27 | } |
127 | 232k | *value = static_cast<uint32_t>(buffer_[offset_]) << 16 | |
128 | 232k | static_cast<uint32_t>(buffer_[offset_ + 1]) << 8 | |
129 | 232k | static_cast<uint32_t>(buffer_[offset_ + 2]); |
130 | 232k | offset_ += 3; |
131 | 232k | return true; |
132 | 232k | } |
133 | | |
134 | 16.3M | bool ReadU32(uint32_t *value) { |
135 | 16.3M | if (length_ < 4 || offset_ > length_ - 4) { |
136 | 9.09k | return OTS_FAILURE(); |
137 | 9.09k | } |
138 | 16.3M | std::memcpy(value, buffer_ + offset_, sizeof(uint32_t)); |
139 | 16.3M | *value = ots_ntohl(*value); |
140 | 16.3M | offset_ += 4; |
141 | 16.3M | return true; |
142 | 16.3M | } |
143 | | |
144 | 248k | bool ReadS32(int32_t *value) { |
145 | 248k | return ReadU32(reinterpret_cast<uint32_t*>(value)); |
146 | 248k | } |
147 | | |
148 | 194k | bool ReadR64(uint64_t *value) { |
149 | 194k | if (length_ < 8 || offset_ > length_ - 8) { |
150 | 110 | return OTS_FAILURE(); |
151 | 110 | } |
152 | 194k | std::memcpy(value, buffer_ + offset_, sizeof(uint64_t)); |
153 | 194k | offset_ += 8; |
154 | 194k | return true; |
155 | 194k | } |
156 | | |
157 | 100M | const uint8_t *buffer() const { return buffer_; } |
158 | 92.6M | size_t offset() const { return offset_; } |
159 | 104M | size_t length() const { return length_; } |
160 | 372k | size_t remaining() const { return length_ - offset_; } |
161 | | |
162 | 27.7M | 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 | 12.5k | template<typename T> T Round4(T value) { |
173 | 12.5k | if (std::numeric_limits<T>::max() - value < 3) { |
174 | 2 | return value; |
175 | 2 | } |
176 | 12.5k | return (value + 3) & ~3; |
177 | 12.5k | } unsigned int ots::Round4<unsigned int>(unsigned int) Line | Count | Source | 172 | 11.1k | template<typename T> T Round4(T value) { | 173 | 11.1k | if (std::numeric_limits<T>::max() - value < 3) { | 174 | 2 | return value; | 175 | 2 | } | 176 | 11.1k | return (value + 3) & ~3; | 177 | 11.1k | } |
unsigned long ots::Round4<unsigned long>(unsigned long) Line | Count | Source | 172 | 1.32k | template<typename T> T Round4(T value) { | 173 | 1.32k | if (std::numeric_limits<T>::max() - value < 3) { | 174 | 0 | return value; | 175 | 0 | } | 176 | 1.32k | return (value + 3) & ~3; | 177 | 1.32k | } |
|
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 | 172k | #define OTS_TAG_CFF OTS_TAG('C','F','F',' ') |
190 | 125k | #define OTS_TAG_CFF2 OTS_TAG('C','F','F','2') |
191 | 94.6k | #define OTS_TAG_CMAP OTS_TAG('c','m','a','p') |
192 | 990 | #define OTS_TAG_COLR OTS_TAG('C','O','L','R') |
193 | 3.84k | #define OTS_TAG_CPAL OTS_TAG('C','P','A','L') |
194 | 1.55k | #define OTS_TAG_CVT OTS_TAG('c','v','t',' ') |
195 | 450k | #define OTS_TAG_FEAT OTS_TAG('F','e','a','t') |
196 | 3.68k | #define OTS_TAG_FPGM OTS_TAG('f','p','g','m') |
197 | 1.56k | #define OTS_TAG_GASP OTS_TAG('g','a','s','p') |
198 | 8.01k | #define OTS_TAG_GDEF OTS_TAG('G','D','E','F') |
199 | 369k | #define OTS_TAG_GLAT OTS_TAG('G','l','a','t') |
200 | 373k | #define OTS_TAG_GLOC OTS_TAG('G','l','o','c') |
201 | 235k | #define OTS_TAG_GLYF OTS_TAG('g','l','y','f') |
202 | 15.9k | #define OTS_TAG_GPOS OTS_TAG('G','P','O','S') |
203 | 8.00k | #define OTS_TAG_GSUB OTS_TAG('G','S','U','B') |
204 | 1.18k | #define OTS_TAG_HDMX OTS_TAG('h','d','m','x') |
205 | 396k | #define OTS_TAG_HEAD OTS_TAG('h','e','a','d') |
206 | 176k | #define OTS_TAG_HHEA OTS_TAG('h','h','e','a') |
207 | 87.7k | #define OTS_TAG_HMTX OTS_TAG('h','m','t','x') |
208 | 11.0k | #define OTS_TAG_KERN OTS_TAG('k','e','r','n') |
209 | 280k | #define OTS_TAG_LOCA OTS_TAG('l','o','c','a') |
210 | 1.22k | #define OTS_TAG_LTSH OTS_TAG('L','T','S','H') |
211 | 4.27k | #define OTS_TAG_MATH OTS_TAG('M','A','T','H') |
212 | 692k | #define OTS_TAG_MAXP OTS_TAG('m','a','x','p') |
213 | 374k | #define OTS_TAG_NAME OTS_TAG('n','a','m','e') |
214 | 175k | #define OTS_TAG_OS2 OTS_TAG('O','S','/','2') |
215 | 85.5k | #define OTS_TAG_POST OTS_TAG('p','o','s','t') |
216 | 3.61k | #define OTS_TAG_PREP OTS_TAG('p','r','e','p') |
217 | 357k | #define OTS_TAG_SILE OTS_TAG('S','i','l','e') |
218 | 361k | #define OTS_TAG_SILF OTS_TAG('S','i','l','f') |
219 | 346k | #define OTS_TAG_SILL OTS_TAG('S','i','l','l') |
220 | 4.03k | #define OTS_TAG_VDMX OTS_TAG('V','D','M','X') |
221 | 618 | #define OTS_TAG_VHEA OTS_TAG('v','h','e','a') |
222 | 46 | #define OTS_TAG_VMTX OTS_TAG('v','m','t','x') |
223 | 2.22k | #define OTS_TAG_VORG OTS_TAG('V','O','R','G') |
224 | | |
225 | 175k | #define OTS_TAG_AVAR OTS_TAG('a','v','a','r') |
226 | 174k | #define OTS_TAG_CVAR OTS_TAG('c','v','a','r') |
227 | 306k | #define OTS_TAG_FVAR OTS_TAG('f','v','a','r') |
228 | 175k | #define OTS_TAG_GVAR OTS_TAG('g','v','a','r') |
229 | 169k | #define OTS_TAG_HVAR OTS_TAG('H','V','A','R') |
230 | 160k | #define OTS_TAG_MVAR OTS_TAG('M','V','A','R') |
231 | 158k | #define OTS_TAG_VVAR OTS_TAG('V','V','A','R') |
232 | 160k | #define OTS_TAG_STAT OTS_TAG('S','T','A','T') |
233 | | |
234 | | // See https://github.com/khaledhosny/ots/issues/219 |
235 | 175k | #define OTS_MAX_DECOMPRESSED_FILE_SIZE 300 * 1024 * 1024 |
236 | 4.87k | #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 | 1.02M | : m_tag(tag), |
247 | 1.02M | m_type(type), |
248 | 1.02M | m_font(font), |
249 | 1.02M | m_shouldSerialize(true) { |
250 | 1.02M | } |
251 | | |
252 | 1.02M | 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 | 1.48M | uint32_t Type() { return m_type; } |
264 | | |
265 | | // Return the tag assigned when this table was constructed. |
266 | 1.97M | uint32_t Tag() { return m_tag; } |
267 | | |
268 | 57.3M | 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 | 0 | : Table(font, tag, 0), |
289 | 0 | m_data(NULL), |
290 | 0 | m_length(0) { |
291 | 0 | } |
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 | 193k | : file(f), |
304 | 193k | version(0), |
305 | 193k | num_tables(0), |
306 | 193k | search_range(0), |
307 | 193k | entry_selector(0), |
308 | 193k | range_shift(0) { |
309 | 193k | } |
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 | 13.3M | bool operator<(const TableEntry& other) const { |
349 | 13.3M | return tag < other.tag; |
350 | 13.3M | } |
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_ |