OLD | NEW |
| (Empty) |
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 | |
16 #include "opentype-sanitiser.h" | |
17 | |
18 // arraysize borrowed from base/basictypes.h | |
19 template <typename T, size_t N> | |
20 char (&ArraySizeHelper(T (&array)[N]))[N]; | |
21 #define arraysize(array) (sizeof(ArraySizeHelper(array))) | |
22 | |
23 namespace ots { | |
24 | |
25 #if !defined(OTS_DEBUG) | |
26 #define OTS_FAILURE() false | |
27 #else | |
28 #define OTS_FAILURE() \ | |
29 (\ | |
30 std::fprintf(stderr, "ERROR at %s:%d (%s)\n", \ | |
31 __FILE__, __LINE__, __FUNCTION__) \ | |
32 && false\ | |
33 ) | |
34 #endif | |
35 | |
36 // All OTS_FAILURE_* macros ultimately evaluate to 'false', just like the origin
al | |
37 // message-less OTS_FAILURE(), so that the current parser will return 'false' as | |
38 // its result (indicating a failure). | |
39 | |
40 #if !defined(OTS_DEBUG) | |
41 #define OTS_MESSAGE_(level,otf_,...) \ | |
42 (otf_)->context->Message(level,__VA_ARGS__) | |
43 #else | |
44 #define OTS_MESSAGE_(level,otf_,...) \ | |
45 OTS_FAILURE(), \ | |
46 (otf_)->context->Message(level,__VA_ARGS__) | |
47 #endif | |
48 | |
49 // Generate a simple message | |
50 #define OTS_FAILURE_MSG_(otf_,...) \ | |
51 (OTS_MESSAGE_(0,otf_,__VA_ARGS__), false) | |
52 | |
53 #define OTS_WARNING_MSG_(otf_,...) \ | |
54 OTS_MESSAGE_(1,otf_,__VA_ARGS__) | |
55 | |
56 // Generate a message with an associated table tag | |
57 #define OTS_FAILURE_MSG_TAG_(otf_,msg_,tag_) \ | |
58 (OTS_MESSAGE_(0,otf_,"%4.4s: %s", tag_, msg_), false) | |
59 | |
60 // Convenience macros for use in files that only handle a single table tag, | |
61 // defined as TABLE_NAME at the top of the file; the 'file' variable is | |
62 // expected to be the current OpenTypeFile pointer. | |
63 #define OTS_FAILURE_MSG(...) OTS_FAILURE_MSG_(file, TABLE_NAME ": " __VA_ARGS__) | |
64 | |
65 #define OTS_WARNING(...) OTS_WARNING_MSG_(file, TABLE_NAME ": " __VA_ARGS__) | |
66 | |
67 // ----------------------------------------------------------------------------- | |
68 // Buffer helper class | |
69 // | |
70 // This class perform some trival buffer operations while checking for | |
71 // out-of-bounds errors. As a family they return false if anything is amiss, | |
72 // updating the current offset otherwise. | |
73 // ----------------------------------------------------------------------------- | |
74 class Buffer { | |
75 public: | |
76 Buffer(const uint8_t *buf, size_t len) | |
77 : buffer_(buf), | |
78 length_(len), | |
79 offset_(0) { } | |
80 | |
81 bool Skip(size_t n_bytes) { | |
82 return Read(NULL, n_bytes); | |
83 } | |
84 | |
85 bool Read(uint8_t *buf, size_t n_bytes) { | |
86 if (n_bytes > 1024 * 1024 * 1024) { | |
87 return OTS_FAILURE(); | |
88 } | |
89 if ((offset_ + n_bytes > length_) || | |
90 (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 (offset_ + 1 > length_) { | |
102 return OTS_FAILURE(); | |
103 } | |
104 *value = buffer_[offset_]; | |
105 ++offset_; | |
106 return true; | |
107 } | |
108 | |
109 bool ReadU16(uint16_t *value) { | |
110 if (offset_ + 2 > length_) { | |
111 return OTS_FAILURE(); | |
112 } | |
113 std::memcpy(value, buffer_ + offset_, sizeof(uint16_t)); | |
114 *value = 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 (offset_ + 3 > length_) { | |
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 (offset_ + 4 > length_) { | |
136 return OTS_FAILURE(); | |
137 } | |
138 std::memcpy(value, buffer_ + offset_, sizeof(uint32_t)); | |
139 *value = 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 ReadTag(uint32_t *value) { | |
149 if (offset_ + 4 > length_) { | |
150 return OTS_FAILURE(); | |
151 } | |
152 std::memcpy(value, buffer_ + offset_, sizeof(uint32_t)); | |
153 offset_ += 4; | |
154 return true; | |
155 } | |
156 | |
157 bool ReadR64(uint64_t *value) { | |
158 if (offset_ + 8 > length_) { | |
159 return OTS_FAILURE(); | |
160 } | |
161 std::memcpy(value, buffer_ + offset_, sizeof(uint64_t)); | |
162 offset_ += 8; | |
163 return true; | |
164 } | |
165 | |
166 const uint8_t *buffer() const { return buffer_; } | |
167 size_t offset() const { return offset_; } | |
168 size_t length() const { return length_; } | |
169 | |
170 void set_offset(size_t newoffset) { offset_ = newoffset; } | |
171 | |
172 private: | |
173 const uint8_t * const buffer_; | |
174 const size_t length_; | |
175 size_t offset_; | |
176 }; | |
177 | |
178 // Round a value up to the nearest multiple of 4. Don't round the value in the | |
179 // case that rounding up overflows. | |
180 template<typename T> T Round4(T value) { | |
181 if (std::numeric_limits<T>::max() - value < 3) { | |
182 return value; | |
183 } | |
184 return (value + 3) & ~3; | |
185 } | |
186 | |
187 template<typename T> T Round2(T value) { | |
188 if (value == std::numeric_limits<T>::max()) { | |
189 return value; | |
190 } | |
191 return (value + 1) & ~1; | |
192 } | |
193 | |
194 bool IsValidVersionTag(uint32_t tag); | |
195 | |
196 #define FOR_EACH_TABLE_TYPE \ | |
197 F(cff, CFF) \ | |
198 F(cmap, CMAP) \ | |
199 F(cvt, CVT) \ | |
200 F(fpgm, FPGM) \ | |
201 F(gasp, GASP) \ | |
202 F(gdef, GDEF) \ | |
203 F(glyf, GLYF) \ | |
204 F(gpos, GPOS) \ | |
205 F(gsub, GSUB) \ | |
206 F(hdmx, HDMX) \ | |
207 F(head, HEAD) \ | |
208 F(hhea, HHEA) \ | |
209 F(hmtx, HMTX) \ | |
210 F(kern, KERN) \ | |
211 F(loca, LOCA) \ | |
212 F(ltsh, LTSH) \ | |
213 F(math, MATH) \ | |
214 F(maxp, MAXP) \ | |
215 F(name, NAME) \ | |
216 F(os2, OS2) \ | |
217 F(post, POST) \ | |
218 F(prep, PREP) \ | |
219 F(vdmx, VDMX) \ | |
220 F(vorg, VORG) \ | |
221 F(vhea, VHEA) \ | |
222 F(vmtx, VMTX) | |
223 | |
224 #define F(name, capname) struct OpenType##capname; | |
225 FOR_EACH_TABLE_TYPE | |
226 #undef F | |
227 | |
228 struct OpenTypeFile { | |
229 OpenTypeFile() { | |
230 #define F(name, capname) name = NULL; | |
231 FOR_EACH_TABLE_TYPE | |
232 #undef F | |
233 } | |
234 | |
235 uint32_t version; | |
236 uint16_t num_tables; | |
237 uint16_t search_range; | |
238 uint16_t entry_selector; | |
239 uint16_t range_shift; | |
240 | |
241 OTSContext *context; | |
242 | |
243 #define F(name, capname) OpenType##capname *name; | |
244 FOR_EACH_TABLE_TYPE | |
245 #undef F | |
246 }; | |
247 | |
248 #define F(name, capname) \ | |
249 bool ots_##name##_parse(OpenTypeFile *f, const uint8_t *d, size_t l); \ | |
250 bool ots_##name##_should_serialise(OpenTypeFile *f); \ | |
251 bool ots_##name##_serialise(OTSStream *s, OpenTypeFile *f); \ | |
252 void ots_##name##_free(OpenTypeFile *f); | |
253 // TODO(yusukes): change these function names to follow Chromium coding rule. | |
254 FOR_EACH_TABLE_TYPE | |
255 #undef F | |
256 | |
257 } // namespace ots | |
258 | |
259 #endif // OTS_H_ | |
OLD | NEW |