Line data Source code
1 : // Copyright (c) 2009 The Chromium 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 : #include <stddef.h>
9 : #include <cstdarg>
10 : #include <cstddef>
11 : #include <cstdio>
12 : #include <cstdlib>
13 : #include <cstring>
14 : #include <limits>
15 : #include <map>
16 :
17 : #include "opentype-sanitiser.h"
18 :
19 : // arraysize borrowed from base/basictypes.h
20 : template <typename T, size_t N>
21 : char (&ArraySizeHelper(T (&array)[N]))[N];
22 : #define arraysize(array) (sizeof(ArraySizeHelper(array)))
23 :
24 : namespace ots {
25 :
26 : #if !defined(OTS_DEBUG)
27 : #define OTS_FAILURE() false
28 : #else
29 : #define OTS_FAILURE() \
30 : (\
31 : std::fprintf(stderr, "ERROR at %s:%d (%s)\n", \
32 : __FILE__, __LINE__, __FUNCTION__) \
33 : && false\
34 : )
35 : #endif
36 :
37 : // All OTS_FAILURE_* macros ultimately evaluate to 'false', just like the original
38 : // message-less OTS_FAILURE(), so that the current parser will return 'false' as
39 : // its result (indicating a failure).
40 :
41 : #if !defined(OTS_DEBUG)
42 : #define OTS_MESSAGE_(level,otf_,...) \
43 : (otf_)->context->Message(level,__VA_ARGS__)
44 : #else
45 : #define OTS_MESSAGE_(level,otf_,...) \
46 : OTS_FAILURE(), \
47 : (otf_)->context->Message(level,__VA_ARGS__)
48 : #endif
49 :
50 : // Generate a simple message
51 : #define OTS_FAILURE_MSG_(otf_,...) \
52 : (OTS_MESSAGE_(0,otf_,__VA_ARGS__), false)
53 :
54 : #define OTS_WARNING_MSG_(otf_,...) \
55 : OTS_MESSAGE_(1,otf_,__VA_ARGS__)
56 :
57 : // Generate a message with an associated table tag
58 : #define OTS_FAILURE_MSG_TAG_(otf_,msg_,tag_) \
59 : (OTS_MESSAGE_(0,otf_,"%c%c%c%c: %s", OTS_UNTAG(tag_), msg_), false)
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 OpenTypeFile 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 0 : Buffer(const uint8_t *buf, size_t len)
78 0 : : buffer_(buf),
79 : length_(len),
80 0 : offset_(0) { }
81 :
82 0 : bool Skip(size_t n_bytes) {
83 0 : return Read(NULL, n_bytes);
84 : }
85 :
86 0 : bool Read(uint8_t *buf, size_t n_bytes) {
87 0 : if (n_bytes > 1024 * 1024 * 1024) {
88 0 : return OTS_FAILURE();
89 : }
90 0 : if ((offset_ + n_bytes > length_) ||
91 0 : (offset_ > length_ - n_bytes)) {
92 0 : return OTS_FAILURE();
93 : }
94 0 : if (buf) {
95 0 : std::memcpy(buf, buffer_ + offset_, n_bytes);
96 : }
97 0 : offset_ += n_bytes;
98 0 : return true;
99 : }
100 :
101 0 : inline bool ReadU8(uint8_t *value) {
102 0 : if (offset_ + 1 > length_) {
103 0 : return OTS_FAILURE();
104 : }
105 0 : *value = buffer_[offset_];
106 0 : ++offset_;
107 0 : return true;
108 : }
109 :
110 0 : bool ReadU16(uint16_t *value) {
111 0 : if (offset_ + 2 > length_) {
112 0 : return OTS_FAILURE();
113 : }
114 0 : std::memcpy(value, buffer_ + offset_, sizeof(uint16_t));
115 0 : *value = ntohs(*value);
116 0 : offset_ += 2;
117 0 : return true;
118 : }
119 :
120 0 : bool ReadS16(int16_t *value) {
121 0 : return ReadU16(reinterpret_cast<uint16_t*>(value));
122 : }
123 :
124 0 : bool ReadU24(uint32_t *value) {
125 0 : if (offset_ + 3 > length_) {
126 0 : return OTS_FAILURE();
127 : }
128 0 : *value = static_cast<uint32_t>(buffer_[offset_]) << 16 |
129 0 : static_cast<uint32_t>(buffer_[offset_ + 1]) << 8 |
130 0 : static_cast<uint32_t>(buffer_[offset_ + 2]);
131 0 : offset_ += 3;
132 0 : return true;
133 : }
134 :
135 0 : bool ReadU32(uint32_t *value) {
136 0 : if (offset_ + 4 > length_) {
137 0 : return OTS_FAILURE();
138 : }
139 0 : std::memcpy(value, buffer_ + offset_, sizeof(uint32_t));
140 0 : *value = ntohl(*value);
141 0 : offset_ += 4;
142 0 : return true;
143 : }
144 :
145 0 : bool ReadS32(int32_t *value) {
146 0 : return ReadU32(reinterpret_cast<uint32_t*>(value));
147 : }
148 :
149 0 : bool ReadR64(uint64_t *value) {
150 0 : if (offset_ + 8 > length_) {
151 0 : return OTS_FAILURE();
152 : }
153 0 : std::memcpy(value, buffer_ + offset_, sizeof(uint64_t));
154 0 : offset_ += 8;
155 0 : return true;
156 : }
157 :
158 0 : const uint8_t *buffer() const { return buffer_; }
159 0 : size_t offset() const { return offset_; }
160 0 : size_t length() const { return length_; }
161 0 : size_t remaining() const { return length_ - offset_; }
162 :
163 0 : void set_offset(size_t newoffset) { offset_ = newoffset; }
164 :
165 : private:
166 : const uint8_t * const buffer_;
167 : const size_t length_;
168 : size_t offset_;
169 : };
170 :
171 : // Round a value up to the nearest multiple of 4. Don't round the value in the
172 : // case that rounding up overflows.
173 0 : template<typename T> T Round4(T value) {
174 0 : if (std::numeric_limits<T>::max() - value < 3) {
175 0 : return value;
176 : }
177 0 : return (value + 3) & ~3;
178 : }
179 :
180 : template<typename T> T Round2(T value) {
181 : if (value == std::numeric_limits<T>::max()) {
182 : return value;
183 : }
184 : return (value + 1) & ~1;
185 : }
186 :
187 : bool IsValidVersionTag(uint32_t tag);
188 :
189 : #define FOR_EACH_TABLE_TYPE \
190 : F(cff, CFF) \
191 : F(cmap, CMAP) \
192 : F(cvt, CVT) \
193 : F(fpgm, FPGM) \
194 : F(gasp, GASP) \
195 : F(gdef, GDEF) \
196 : F(glyf, GLYF) \
197 : F(gpos, GPOS) \
198 : F(gsub, GSUB) \
199 : F(hdmx, HDMX) \
200 : F(head, HEAD) \
201 : F(hhea, HHEA) \
202 : F(hmtx, HMTX) \
203 : F(kern, KERN) \
204 : F(loca, LOCA) \
205 : F(ltsh, LTSH) \
206 : F(math, MATH) \
207 : F(maxp, MAXP) \
208 : F(name, NAME) \
209 : F(os2, OS2) \
210 : F(post, POST) \
211 : F(prep, PREP) \
212 : F(vdmx, VDMX) \
213 : F(vorg, VORG) \
214 : F(vhea, VHEA) \
215 : F(vmtx, VMTX)
216 :
217 : #define F(name, capname) struct OpenType##capname;
218 : FOR_EACH_TABLE_TYPE
219 : #undef F
220 :
221 : struct Font;
222 : struct OpenTypeFile;
223 :
224 : #define F(name, capname) \
225 : bool ots_##name##_parse(Font *f, const uint8_t *d, size_t l); \
226 : bool ots_##name##_should_serialise(Font *f); \
227 : bool ots_##name##_serialise(OTSStream *s, Font *f); \
228 : void ots_##name##_reuse(Font *f, Font *o);\
229 : void ots_##name##_free(Font *f);
230 : FOR_EACH_TABLE_TYPE
231 : #undef F
232 :
233 : struct Font {
234 0 : explicit Font(const OpenTypeFile *f)
235 0 : : file(f),
236 : version(0),
237 : num_tables(0),
238 : search_range(0),
239 : entry_selector(0),
240 0 : range_shift(0) {
241 : #define F(name, capname) \
242 : name = NULL; \
243 : name##_reused = false;
244 0 : FOR_EACH_TABLE_TYPE
245 : #undef F
246 0 : }
247 :
248 0 : ~Font() {
249 : #define F(name, capname) \
250 : if (!name##_reused) {\
251 : ots_##name##_free(this); \
252 : }
253 0 : FOR_EACH_TABLE_TYPE
254 : #undef F
255 0 : }
256 :
257 : const OpenTypeFile *file;
258 :
259 : uint32_t version;
260 : uint16_t num_tables;
261 : uint16_t search_range;
262 : uint16_t entry_selector;
263 : uint16_t range_shift;
264 :
265 : #define F(name, capname) \
266 : OpenType##capname *name; \
267 : bool name##_reused;
268 : FOR_EACH_TABLE_TYPE
269 : #undef F
270 : };
271 :
272 : struct OutputTable {
273 : uint32_t tag;
274 : size_t offset;
275 : size_t length;
276 : uint32_t chksum;
277 :
278 0 : bool operator<(const OutputTable& other) const {
279 0 : return tag < other.tag;
280 : }
281 : };
282 :
283 : typedef std::map<uint32_t, std::pair<Font*, OutputTable> > TableMap;
284 :
285 0 : struct OpenTypeFile {
286 : OTSContext *context;
287 : TableMap tables;
288 : };
289 :
290 : } // namespace ots
291 :
292 : #undef FOR_EACH_TABLE_TYPE
293 :
294 : #endif // OTS_H_
|