OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "layout.h" | 5 #include "layout.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "gdef.h" | 10 #include "gdef.h" |
11 | 11 |
12 // OpenType Layout Common Table Formats | 12 // OpenType Layout Common Table Formats |
13 // http://www.microsoft.com/typography/otspec/chapter2.htm | 13 // http://www.microsoft.com/typography/otspec/chapter2.htm |
14 | 14 |
| 15 #define TABLE_NAME "Layout" // XXX: use individual table names |
| 16 |
15 namespace { | 17 namespace { |
16 | 18 |
17 // The 'DFLT' tag of script table. | 19 // The 'DFLT' tag of script table. |
18 const uint32_t kScriptTableTagDflt = 0x44464c54; | 20 const uint32_t kScriptTableTagDflt = 0x44464c54; |
19 // The value which represents there is no required feature index. | 21 // The value which represents there is no required feature index. |
20 const uint16_t kNoRequiredFeatureIndexDefined = 0xFFFF; | 22 const uint16_t kNoRequiredFeatureIndexDefined = 0xFFFF; |
21 // The lookup flag bit which indicates existence of MarkFilteringSet. | 23 // The lookup flag bit which indicates existence of MarkFilteringSet. |
22 const uint16_t kUseMarkFilteringSetBit = 0x0010; | 24 const uint16_t kUseMarkFilteringSetBit = 0x0010; |
23 // The lookup flags which require GDEF table. | 25 // The lookup flags which require GDEF table. |
24 const uint16_t kGdefRequiredFlags = 0x0002 | 0x0004 | 0x0008; | 26 const uint16_t kGdefRequiredFlags = 0x0002 | 0x0004 | 0x0008; |
(...skipping 12 matching lines...) Loading... |
37 struct LangSysRecord { | 39 struct LangSysRecord { |
38 uint32_t tag; | 40 uint32_t tag; |
39 uint16_t offset; | 41 uint16_t offset; |
40 }; | 42 }; |
41 | 43 |
42 struct FeatureRecord { | 44 struct FeatureRecord { |
43 uint32_t tag; | 45 uint32_t tag; |
44 uint16_t offset; | 46 uint16_t offset; |
45 }; | 47 }; |
46 | 48 |
47 bool ParseLangSysTable(ots::Buffer *subtable, const uint32_t tag, | 49 bool ParseLangSysTable(const ots::OpenTypeFile *file, |
| 50 ots::Buffer *subtable, const uint32_t tag, |
48 const uint16_t num_features) { | 51 const uint16_t num_features) { |
49 uint16_t offset_lookup_order = 0; | 52 uint16_t offset_lookup_order = 0; |
50 uint16_t req_feature_index = 0; | 53 uint16_t req_feature_index = 0; |
51 uint16_t feature_count = 0; | 54 uint16_t feature_count = 0; |
52 if (!subtable->ReadU16(&offset_lookup_order) || | 55 if (!subtable->ReadU16(&offset_lookup_order) || |
53 !subtable->ReadU16(&req_feature_index) || | 56 !subtable->ReadU16(&req_feature_index) || |
54 !subtable->ReadU16(&feature_count)) { | 57 !subtable->ReadU16(&feature_count)) { |
55 return OTS_FAILURE(); | 58 return OTS_FAILURE_MSG("Failed to read langsys header for tag %4.4s", (char
*)&tag); |
56 } | 59 } |
57 // |offset_lookup_order| is reserved and should be NULL. | 60 // |offset_lookup_order| is reserved and should be NULL. |
58 if (offset_lookup_order != 0) { | 61 if (offset_lookup_order != 0) { |
59 return OTS_FAILURE(); | 62 return OTS_FAILURE_MSG("Bad lookup offset order %d for langsys tag %4.4s", o
ffset_lookup_order, (char *)&tag); |
60 } | 63 } |
61 if (req_feature_index != kNoRequiredFeatureIndexDefined && | 64 if (req_feature_index != kNoRequiredFeatureIndexDefined && |
62 req_feature_index >= num_features) { | 65 req_feature_index >= num_features) { |
63 return OTS_FAILURE(); | 66 return OTS_FAILURE_MSG("Bad required features index %d for langsys tag %4.4s
", req_feature_index, (char *)&tag); |
64 } | 67 } |
65 if (feature_count > num_features) { | 68 if (feature_count > num_features) { |
66 return OTS_FAILURE(); | 69 return OTS_FAILURE_MSG("Bad feature count %d for langsys tag %4.4s", feature
_count, (char *)&tag); |
67 } | 70 } |
68 | 71 |
69 for (unsigned i = 0; i < feature_count; ++i) { | 72 for (unsigned i = 0; i < feature_count; ++i) { |
70 uint16_t feature_index = 0; | 73 uint16_t feature_index = 0; |
71 if (!subtable->ReadU16(&feature_index)) { | 74 if (!subtable->ReadU16(&feature_index)) { |
72 return OTS_FAILURE(); | 75 return OTS_FAILURE_MSG("Failed to read feature index %d for langsys tag %4
.4s", i, (char *)&tag); |
73 } | 76 } |
74 if (feature_index >= num_features) { | 77 if (feature_index >= num_features) { |
75 return OTS_FAILURE(); | 78 return OTS_FAILURE_MSG("Bad feature index %d for feature %d for langsys ta
g %4.4s", feature_index, i, (char *)&tag); |
76 } | 79 } |
77 } | 80 } |
78 return true; | 81 return true; |
79 } | 82 } |
80 | 83 |
81 bool ParseScriptTable(const uint8_t *data, const size_t length, | 84 bool ParseScriptTable(const ots::OpenTypeFile *file, |
| 85 const uint8_t *data, const size_t length, |
82 const uint32_t tag, const uint16_t num_features) { | 86 const uint32_t tag, const uint16_t num_features) { |
83 ots::Buffer subtable(data, length); | 87 ots::Buffer subtable(data, length); |
84 | 88 |
85 uint16_t offset_default_lang_sys = 0; | 89 uint16_t offset_default_lang_sys = 0; |
86 uint16_t lang_sys_count = 0; | 90 uint16_t lang_sys_count = 0; |
87 if (!subtable.ReadU16(&offset_default_lang_sys) || | 91 if (!subtable.ReadU16(&offset_default_lang_sys) || |
88 !subtable.ReadU16(&lang_sys_count)) { | 92 !subtable.ReadU16(&lang_sys_count)) { |
89 return OTS_FAILURE(); | 93 return OTS_FAILURE_MSG("Failed to read script header for script tag %4.4s",
(char *)&tag); |
90 } | 94 } |
91 | 95 |
92 // The spec requires a script table for 'DFLT' tag must contain non-NULL | 96 // The spec requires a script table for 'DFLT' tag must contain non-NULL |
93 // |offset_default_lang_sys| and |lang_sys_count| == 0 | 97 // |offset_default_lang_sys| and |lang_sys_count| == 0 |
94 if (tag == kScriptTableTagDflt && | 98 if (tag == kScriptTableTagDflt && |
95 (offset_default_lang_sys == 0 || lang_sys_count != 0)) { | 99 (offset_default_lang_sys == 0 || lang_sys_count != 0)) { |
96 OTS_WARNING("DFLT table doesn't satisfy the spec."); | 100 return OTS_FAILURE_MSG("DFLT table doesn't satisfy the spec. for script tag
%4.4s", (char *)&tag); |
97 return OTS_FAILURE(); | |
98 } | 101 } |
99 | 102 |
100 const unsigned lang_sys_record_end = | 103 const unsigned lang_sys_record_end = |
101 6 * static_cast<unsigned>(lang_sys_count) + 4; | 104 6 * static_cast<unsigned>(lang_sys_count) + 4; |
102 if (lang_sys_record_end > std::numeric_limits<uint16_t>::max()) { | 105 if (lang_sys_record_end > std::numeric_limits<uint16_t>::max()) { |
103 return OTS_FAILURE(); | 106 return OTS_FAILURE_MSG("Bad end of langsys record %d for script tag %4.4s",
lang_sys_record_end, (char *)&tag); |
104 } | 107 } |
105 | 108 |
106 std::vector<LangSysRecord> lang_sys_records; | 109 std::vector<LangSysRecord> lang_sys_records; |
107 lang_sys_records.resize(lang_sys_count); | 110 lang_sys_records.resize(lang_sys_count); |
108 uint32_t last_tag = 0; | 111 uint32_t last_tag = 0; |
109 for (unsigned i = 0; i < lang_sys_count; ++i) { | 112 for (unsigned i = 0; i < lang_sys_count; ++i) { |
110 if (!subtable.ReadU32(&lang_sys_records[i].tag) || | 113 if (!subtable.ReadU32(&lang_sys_records[i].tag) || |
111 !subtable.ReadU16(&lang_sys_records[i].offset)) { | 114 !subtable.ReadU16(&lang_sys_records[i].offset)) { |
112 return OTS_FAILURE(); | 115 return OTS_FAILURE_MSG("Failed to read langsys record header %d for script
tag %4.4s", i, (char *)&tag); |
113 } | 116 } |
114 // The record array must store the records alphabetically by tag | 117 // The record array must store the records alphabetically by tag |
115 if (last_tag != 0 && last_tag > lang_sys_records[i].tag) { | 118 if (last_tag != 0 && last_tag > lang_sys_records[i].tag) { |
116 return OTS_FAILURE(); | 119 return OTS_FAILURE_MSG("Bad last tag %d for langsys record %d for script t
ag %4.4s", last_tag, i, (char *)&tag); |
117 } | 120 } |
118 if (lang_sys_records[i].offset < lang_sys_record_end || | 121 if (lang_sys_records[i].offset < lang_sys_record_end || |
119 lang_sys_records[i].offset >= length) { | 122 lang_sys_records[i].offset >= length) { |
120 OTS_WARNING("bad offset to lang sys table: %x", | 123 return OTS_FAILURE_MSG("bad offset to lang sys table: %x", |
121 lang_sys_records[i].offset); | 124 lang_sys_records[i].offset); |
122 return OTS_FAILURE(); | |
123 } | 125 } |
124 last_tag = lang_sys_records[i].tag; | 126 last_tag = lang_sys_records[i].tag; |
125 } | 127 } |
126 | 128 |
127 // Check lang sys tables | 129 // Check lang sys tables |
128 for (unsigned i = 0; i < lang_sys_count; ++i) { | 130 for (unsigned i = 0; i < lang_sys_count; ++i) { |
129 subtable.set_offset(lang_sys_records[i].offset); | 131 subtable.set_offset(lang_sys_records[i].offset); |
130 if (!ParseLangSysTable(&subtable, lang_sys_records[i].tag, num_features)) { | 132 if (!ParseLangSysTable(file, &subtable, lang_sys_records[i].tag, num_feature
s)) { |
131 return OTS_FAILURE(); | 133 return OTS_FAILURE_MSG("Failed to parse langsys table %d (%4.4s) for scrip
t tag %4.4s", i, (char *)&lang_sys_records[i].tag, (char *)&tag); |
132 } | 134 } |
133 } | 135 } |
134 | 136 |
135 return true; | 137 return true; |
136 } | 138 } |
137 | 139 |
138 bool ParseFeatureTable(const uint8_t *data, const size_t length, | 140 bool ParseFeatureTable(const ots::OpenTypeFile *file, |
| 141 const uint8_t *data, const size_t length, |
139 const uint16_t num_lookups) { | 142 const uint16_t num_lookups) { |
140 ots::Buffer subtable(data, length); | 143 ots::Buffer subtable(data, length); |
141 | 144 |
142 uint16_t offset_feature_params = 0; | 145 uint16_t offset_feature_params = 0; |
143 uint16_t lookup_count = 0; | 146 uint16_t lookup_count = 0; |
144 if (!subtable.ReadU16(&offset_feature_params) || | 147 if (!subtable.ReadU16(&offset_feature_params) || |
145 !subtable.ReadU16(&lookup_count)) { | 148 !subtable.ReadU16(&lookup_count)) { |
146 return OTS_FAILURE(); | 149 return OTS_FAILURE_MSG("Failed to read feature table header"); |
147 } | 150 } |
148 | 151 |
149 const unsigned feature_table_end = | 152 const unsigned feature_table_end = |
150 2 * static_cast<unsigned>(lookup_count) + 4; | 153 2 * static_cast<unsigned>(lookup_count) + 4; |
151 if (feature_table_end > std::numeric_limits<uint16_t>::max()) { | 154 if (feature_table_end > std::numeric_limits<uint16_t>::max()) { |
152 return OTS_FAILURE(); | 155 return OTS_FAILURE_MSG("Bad end of feature table %d", feature_table_end); |
153 } | 156 } |
154 // |offset_feature_params| is generally set to NULL. | 157 // |offset_feature_params| is generally set to NULL. |
155 if (offset_feature_params != 0 && | 158 if (offset_feature_params != 0 && |
156 (offset_feature_params < feature_table_end || | 159 (offset_feature_params < feature_table_end || |
157 offset_feature_params >= length)) { | 160 offset_feature_params >= length)) { |
158 return OTS_FAILURE(); | 161 return OTS_FAILURE_MSG("Bad feature params offset %d", offset_feature_params
); |
159 } | 162 } |
160 | 163 |
161 for (unsigned i = 0; i < lookup_count; ++i) { | 164 for (unsigned i = 0; i < lookup_count; ++i) { |
162 uint16_t lookup_index = 0; | 165 uint16_t lookup_index = 0; |
163 if (!subtable.ReadU16(&lookup_index)) { | 166 if (!subtable.ReadU16(&lookup_index)) { |
164 return OTS_FAILURE(); | 167 return OTS_FAILURE_MSG("Failed to read lookup index for lookup %d", i); |
165 } | 168 } |
166 // lookup index starts with 0. | 169 // lookup index starts with 0. |
167 if (lookup_index >= num_lookups) { | 170 if (lookup_index >= num_lookups) { |
168 return OTS_FAILURE(); | 171 return OTS_FAILURE_MSG("Bad lookup index %d for lookup %d", lookup_index,
i); |
169 } | 172 } |
170 } | 173 } |
171 return true; | 174 return true; |
172 } | 175 } |
173 | 176 |
174 bool ParseLookupTable(ots::OpenTypeFile *file, const uint8_t *data, | 177 bool ParseLookupTable(ots::OpenTypeFile *file, const uint8_t *data, |
175 const size_t length, | 178 const size_t length, |
176 const ots::LookupSubtableParser* parser) { | 179 const ots::LookupSubtableParser* parser) { |
177 ots::Buffer subtable(data, length); | 180 ots::Buffer subtable(data, length); |
178 | 181 |
179 uint16_t lookup_type = 0; | 182 uint16_t lookup_type = 0; |
180 uint16_t lookup_flag = 0; | 183 uint16_t lookup_flag = 0; |
181 uint16_t subtable_count = 0; | 184 uint16_t subtable_count = 0; |
182 if (!subtable.ReadU16(&lookup_type) || | 185 if (!subtable.ReadU16(&lookup_type) || |
183 !subtable.ReadU16(&lookup_flag) || | 186 !subtable.ReadU16(&lookup_flag) || |
184 !subtable.ReadU16(&subtable_count)) { | 187 !subtable.ReadU16(&subtable_count)) { |
185 return OTS_FAILURE(); | 188 return OTS_FAILURE_MSG("Failed to read lookup table header"); |
186 } | 189 } |
187 | 190 |
188 if (lookup_type == 0 || lookup_type > parser->num_types) { | 191 if (lookup_type == 0 || lookup_type > parser->num_types) { |
189 return OTS_FAILURE(); | 192 return OTS_FAILURE_MSG("Bad lookup type %d", lookup_type); |
190 } | 193 } |
191 | 194 |
192 // Check lookup flags. | 195 // Check lookup flags. |
193 if ((lookup_flag & kGdefRequiredFlags) && | 196 if ((lookup_flag & kGdefRequiredFlags) && |
194 (!file->gdef || !file->gdef->has_glyph_class_def)) { | 197 (!file->gdef || !file->gdef->has_glyph_class_def)) { |
195 return OTS_FAILURE(); | 198 return OTS_FAILURE_MSG("Bad lookup flags %d", lookup_flag); |
196 } | 199 } |
197 if ((lookup_flag & kMarkAttachmentTypeMask) && | 200 if ((lookup_flag & kMarkAttachmentTypeMask) && |
198 (!file->gdef || !file->gdef->has_mark_attachment_class_def)) { | 201 (!file->gdef || !file->gdef->has_mark_attachment_class_def)) { |
199 return OTS_FAILURE(); | 202 return OTS_FAILURE_MSG("lookup flag asks for mark attachment that is bad %d"
, lookup_flag); |
200 } | 203 } |
201 bool use_mark_filtering_set = false; | 204 bool use_mark_filtering_set = false; |
202 if (lookup_flag & kUseMarkFilteringSetBit) { | 205 if (lookup_flag & kUseMarkFilteringSetBit) { |
203 if (!file->gdef || !file->gdef->has_mark_glyph_sets_def) { | 206 if (!file->gdef || !file->gdef->has_mark_glyph_sets_def) { |
204 return OTS_FAILURE(); | 207 return OTS_FAILURE_MSG("lookup flag asks for mark filtering that is bad %d
", lookup_flag); |
205 } | 208 } |
206 use_mark_filtering_set = true; | 209 use_mark_filtering_set = true; |
207 } | 210 } |
208 | 211 |
209 std::vector<uint16_t> subtables; | 212 std::vector<uint16_t> subtables; |
210 subtables.reserve(subtable_count); | 213 subtables.reserve(subtable_count); |
211 // If the |kUseMarkFilteringSetBit| of |lookup_flag| is set, | 214 // If the |kUseMarkFilteringSetBit| of |lookup_flag| is set, |
212 // extra 2 bytes will follow after subtable offset array. | 215 // extra 2 bytes will follow after subtable offset array. |
213 const unsigned lookup_table_end = 2 * static_cast<unsigned>(subtable_count) + | 216 const unsigned lookup_table_end = 2 * static_cast<unsigned>(subtable_count) + |
214 (use_mark_filtering_set ? 8 : 6); | 217 (use_mark_filtering_set ? 8 : 6); |
215 if (lookup_table_end > std::numeric_limits<uint16_t>::max()) { | 218 if (lookup_table_end > std::numeric_limits<uint16_t>::max()) { |
216 return OTS_FAILURE(); | 219 return OTS_FAILURE_MSG("Bad end of lookup %d", lookup_table_end); |
217 } | 220 } |
218 for (unsigned i = 0; i < subtable_count; ++i) { | 221 for (unsigned i = 0; i < subtable_count; ++i) { |
219 uint16_t offset_subtable = 0; | 222 uint16_t offset_subtable = 0; |
220 if (!subtable.ReadU16(&offset_subtable)) { | 223 if (!subtable.ReadU16(&offset_subtable)) { |
221 return OTS_FAILURE(); | 224 return OTS_FAILURE_MSG("Failed to read subtable offset %d", i); |
222 } | 225 } |
223 if (offset_subtable < lookup_table_end || | 226 if (offset_subtable < lookup_table_end || |
224 offset_subtable >= length) { | 227 offset_subtable >= length) { |
225 return OTS_FAILURE(); | 228 return OTS_FAILURE_MSG("Bad subtable offset %d for subtable %d", offset_su
btable, i); |
226 } | 229 } |
227 subtables.push_back(offset_subtable); | 230 subtables.push_back(offset_subtable); |
228 } | 231 } |
229 if (subtables.size() != subtable_count) { | 232 if (subtables.size() != subtable_count) { |
230 return OTS_FAILURE(); | 233 return OTS_FAILURE_MSG("Bad subtable size %ld", subtables.size()); |
231 } | 234 } |
232 | 235 |
233 if (use_mark_filtering_set) { | 236 if (use_mark_filtering_set) { |
234 uint16_t mark_filtering_set = 0; | 237 uint16_t mark_filtering_set = 0; |
235 if (!subtable.ReadU16(&mark_filtering_set)) { | 238 if (!subtable.ReadU16(&mark_filtering_set)) { |
236 return OTS_FAILURE(); | 239 return OTS_FAILURE_MSG("Failed to read mark filtering set"); |
237 } | 240 } |
238 if (file->gdef->num_mark_glyph_sets == 0 || | 241 if (file->gdef->num_mark_glyph_sets == 0 || |
239 mark_filtering_set >= file->gdef->num_mark_glyph_sets) { | 242 mark_filtering_set >= file->gdef->num_mark_glyph_sets) { |
240 return OTS_FAILURE(); | 243 return OTS_FAILURE_MSG("Bad mark filtering set %d", mark_filtering_set); |
241 } | 244 } |
242 } | 245 } |
243 | 246 |
244 // Parse lookup subtables for this lookup type. | 247 // Parse lookup subtables for this lookup type. |
245 for (unsigned i = 0; i < subtable_count; ++i) { | 248 for (unsigned i = 0; i < subtable_count; ++i) { |
246 if (!parser->Parse(file, data + subtables[i], length - subtables[i], | 249 if (!parser->Parse(file, data + subtables[i], length - subtables[i], |
247 lookup_type)) { | 250 lookup_type)) { |
248 return OTS_FAILURE(); | 251 return OTS_FAILURE_MSG("Failed to parse subtable %d", i); |
249 } | 252 } |
250 } | 253 } |
251 return true; | 254 return true; |
252 } | 255 } |
253 | 256 |
254 bool ParseClassDefFormat1(const uint8_t *data, size_t length, | 257 bool ParseClassDefFormat1(const ots::OpenTypeFile *file, |
| 258 const uint8_t *data, size_t length, |
255 const uint16_t num_glyphs, | 259 const uint16_t num_glyphs, |
256 const uint16_t num_classes) { | 260 const uint16_t num_classes) { |
257 ots::Buffer subtable(data, length); | 261 ots::Buffer subtable(data, length); |
258 | 262 |
259 // Skip format field. | 263 // Skip format field. |
260 if (!subtable.Skip(2)) { | 264 if (!subtable.Skip(2)) { |
261 return OTS_FAILURE(); | 265 return OTS_FAILURE_MSG("Failed to skip class definition header"); |
262 } | 266 } |
263 | 267 |
264 uint16_t start_glyph = 0; | 268 uint16_t start_glyph = 0; |
265 if (!subtable.ReadU16(&start_glyph)) { | 269 if (!subtable.ReadU16(&start_glyph)) { |
266 return OTS_FAILURE(); | 270 return OTS_FAILURE_MSG("Failed to read starting glyph of class definition"); |
267 } | 271 } |
268 if (start_glyph > num_glyphs) { | 272 if (start_glyph > num_glyphs) { |
269 OTS_WARNING("bad start glyph ID: %u", start_glyph); | 273 return OTS_FAILURE_MSG("Bad starting glyph %d in class definition", start_gl
yph); |
270 return OTS_FAILURE(); | |
271 } | 274 } |
272 | 275 |
273 uint16_t glyph_count = 0; | 276 uint16_t glyph_count = 0; |
274 if (!subtable.ReadU16(&glyph_count)) { | 277 if (!subtable.ReadU16(&glyph_count)) { |
275 return OTS_FAILURE(); | 278 return OTS_FAILURE_MSG("Failed to read glyph count in class definition"); |
276 } | 279 } |
277 if (glyph_count > num_glyphs) { | 280 if (glyph_count > num_glyphs) { |
278 OTS_WARNING("bad glyph count: %u", glyph_count); | 281 return OTS_FAILURE_MSG("bad glyph count: %u", glyph_count); |
279 return OTS_FAILURE(); | |
280 } | 282 } |
281 for (unsigned i = 0; i < glyph_count; ++i) { | 283 for (unsigned i = 0; i < glyph_count; ++i) { |
282 uint16_t class_value = 0; | 284 uint16_t class_value = 0; |
283 if (!subtable.ReadU16(&class_value)) { | 285 if (!subtable.ReadU16(&class_value)) { |
284 return OTS_FAILURE(); | 286 return OTS_FAILURE_MSG("Failed to read class value for glyph %d in class d
efinition", i); |
285 } | 287 } |
286 if (class_value > num_classes) { | 288 if (class_value > num_classes) { |
287 OTS_WARNING("bad class value: %u", class_value); | 289 return OTS_FAILURE_MSG("Bad class value %d for glyph %d in class definitio
n", class_value, i); |
288 return OTS_FAILURE(); | |
289 } | 290 } |
290 } | 291 } |
291 | 292 |
292 return true; | 293 return true; |
293 } | 294 } |
294 | 295 |
295 bool ParseClassDefFormat2(const uint8_t *data, size_t length, | 296 bool ParseClassDefFormat2(const ots::OpenTypeFile *file, |
| 297 const uint8_t *data, size_t length, |
296 const uint16_t num_glyphs, | 298 const uint16_t num_glyphs, |
297 const uint16_t num_classes) { | 299 const uint16_t num_classes) { |
298 ots::Buffer subtable(data, length); | 300 ots::Buffer subtable(data, length); |
299 | 301 |
300 // Skip format field. | 302 // Skip format field. |
301 if (!subtable.Skip(2)) { | 303 if (!subtable.Skip(2)) { |
302 return OTS_FAILURE(); | 304 return OTS_FAILURE_MSG("Failed to skip format of class defintion header"); |
303 } | 305 } |
304 | 306 |
305 uint16_t range_count = 0; | 307 uint16_t range_count = 0; |
306 if (!subtable.ReadU16(&range_count)) { | 308 if (!subtable.ReadU16(&range_count)) { |
307 return OTS_FAILURE(); | 309 return OTS_FAILURE_MSG("Failed to read range count in class definition"); |
308 } | 310 } |
309 if (range_count > num_glyphs) { | 311 if (range_count > num_glyphs) { |
310 OTS_WARNING("bad range count: %u", range_count); | 312 return OTS_FAILURE_MSG("bad range count: %u", range_count); |
311 return OTS_FAILURE(); | |
312 } | 313 } |
313 | 314 |
314 uint16_t last_end = 0; | 315 uint16_t last_end = 0; |
315 for (unsigned i = 0; i < range_count; ++i) { | 316 for (unsigned i = 0; i < range_count; ++i) { |
316 uint16_t start = 0; | 317 uint16_t start = 0; |
317 uint16_t end = 0; | 318 uint16_t end = 0; |
318 uint16_t class_value = 0; | 319 uint16_t class_value = 0; |
319 if (!subtable.ReadU16(&start) || | 320 if (!subtable.ReadU16(&start) || |
320 !subtable.ReadU16(&end) || | 321 !subtable.ReadU16(&end) || |
321 !subtable.ReadU16(&class_value)) { | 322 !subtable.ReadU16(&class_value)) { |
322 return OTS_FAILURE(); | 323 return OTS_FAILURE_MSG("Failed to read class definition reange %d", i); |
323 } | 324 } |
324 if (start > end || (last_end && start <= last_end)) { | 325 if (start > end || (last_end && start <= last_end)) { |
325 OTS_WARNING("glyph range is overlapping."); | 326 return OTS_FAILURE_MSG("glyph range is overlapping.in range %d", i); |
326 return OTS_FAILURE(); | |
327 } | 327 } |
328 if (class_value > num_classes) { | 328 if (class_value > num_classes) { |
329 OTS_WARNING("bad class value: %u", class_value); | 329 return OTS_FAILURE_MSG("bad class value: %u", class_value); |
330 return OTS_FAILURE(); | |
331 } | 330 } |
332 last_end = end; | 331 last_end = end; |
333 } | 332 } |
334 | 333 |
335 return true; | 334 return true; |
336 } | 335 } |
337 | 336 |
338 bool ParseCoverageFormat1(const uint8_t *data, size_t length, | 337 bool ParseCoverageFormat1(const ots::OpenTypeFile *file, |
| 338 const uint8_t *data, size_t length, |
339 const uint16_t num_glyphs, | 339 const uint16_t num_glyphs, |
340 const uint16_t expected_num_glyphs) { | 340 const uint16_t expected_num_glyphs) { |
341 ots::Buffer subtable(data, length); | 341 ots::Buffer subtable(data, length); |
342 | 342 |
343 // Skip format field. | 343 // Skip format field. |
344 if (!subtable.Skip(2)) { | 344 if (!subtable.Skip(2)) { |
345 return OTS_FAILURE(); | 345 return OTS_FAILURE_MSG("Failed to skip coverage format"); |
346 } | 346 } |
347 | 347 |
348 uint16_t glyph_count = 0; | 348 uint16_t glyph_count = 0; |
349 if (!subtable.ReadU16(&glyph_count)) { | 349 if (!subtable.ReadU16(&glyph_count)) { |
350 return OTS_FAILURE(); | 350 return OTS_FAILURE_MSG("Failed to read glyph count in coverage"); |
351 } | 351 } |
352 if (glyph_count > num_glyphs) { | 352 if (glyph_count > num_glyphs) { |
353 OTS_WARNING("bad glyph count: %u", glyph_count); | 353 return OTS_FAILURE_MSG("bad glyph count: %u", glyph_count); |
354 return OTS_FAILURE(); | |
355 } | 354 } |
356 for (unsigned i = 0; i < glyph_count; ++i) { | 355 for (unsigned i = 0; i < glyph_count; ++i) { |
357 uint16_t glyph = 0; | 356 uint16_t glyph = 0; |
358 if (!subtable.ReadU16(&glyph)) { | 357 if (!subtable.ReadU16(&glyph)) { |
359 return OTS_FAILURE(); | 358 return OTS_FAILURE_MSG("Failed to read glyph %d in coverage", i); |
360 } | 359 } |
361 if (glyph > num_glyphs) { | 360 if (glyph > num_glyphs) { |
362 OTS_WARNING("bad glyph ID: %u", glyph); | 361 return OTS_FAILURE_MSG("bad glyph ID: %u", glyph); |
363 return OTS_FAILURE(); | |
364 } | 362 } |
365 } | 363 } |
366 | 364 |
367 if (expected_num_glyphs && expected_num_glyphs != glyph_count) { | 365 if (expected_num_glyphs && expected_num_glyphs != glyph_count) { |
368 OTS_WARNING("unexpected number of glyphs: %u", glyph_count); | 366 return OTS_FAILURE_MSG("unexpected number of glyphs: %u", glyph_count); |
369 return OTS_FAILURE(); | |
370 } | 367 } |
371 | 368 |
372 return true; | 369 return true; |
373 } | 370 } |
374 | 371 |
375 bool ParseCoverageFormat2(const uint8_t *data, size_t length, | 372 bool ParseCoverageFormat2(const ots::OpenTypeFile *file, |
| 373 const uint8_t *data, size_t length, |
376 const uint16_t num_glyphs, | 374 const uint16_t num_glyphs, |
377 const uint16_t expected_num_glyphs) { | 375 const uint16_t expected_num_glyphs) { |
378 ots::Buffer subtable(data, length); | 376 ots::Buffer subtable(data, length); |
379 | 377 |
380 // Skip format field. | 378 // Skip format field. |
381 if (!subtable.Skip(2)) { | 379 if (!subtable.Skip(2)) { |
382 return OTS_FAILURE(); | 380 return OTS_FAILURE_MSG("Failed to skip format of coverage type 2"); |
383 } | 381 } |
384 | 382 |
385 uint16_t range_count = 0; | 383 uint16_t range_count = 0; |
386 if (!subtable.ReadU16(&range_count)) { | 384 if (!subtable.ReadU16(&range_count)) { |
387 return OTS_FAILURE(); | 385 return OTS_FAILURE_MSG("Failed to read range count in coverage"); |
388 } | 386 } |
389 if (range_count > num_glyphs) { | 387 if (range_count > num_glyphs) { |
390 OTS_WARNING("bad range count: %u", range_count); | 388 return OTS_FAILURE_MSG("bad range count: %u", range_count); |
391 return OTS_FAILURE(); | |
392 } | 389 } |
393 uint16_t last_end = 0; | 390 uint16_t last_end = 0; |
394 uint16_t last_start_coverage_index = 0; | 391 uint16_t last_start_coverage_index = 0; |
395 for (unsigned i = 0; i < range_count; ++i) { | 392 for (unsigned i = 0; i < range_count; ++i) { |
396 uint16_t start = 0; | 393 uint16_t start = 0; |
397 uint16_t end = 0; | 394 uint16_t end = 0; |
398 uint16_t start_coverage_index = 0; | 395 uint16_t start_coverage_index = 0; |
399 if (!subtable.ReadU16(&start) || | 396 if (!subtable.ReadU16(&start) || |
400 !subtable.ReadU16(&end) || | 397 !subtable.ReadU16(&end) || |
401 !subtable.ReadU16(&start_coverage_index)) { | 398 !subtable.ReadU16(&start_coverage_index)) { |
402 return OTS_FAILURE(); | 399 return OTS_FAILURE_MSG("Failed to read range %d in coverage", i); |
403 } | 400 } |
404 | 401 |
405 // Some of the Adobe Pro fonts have ranges that overlap by one element: the | 402 // Some of the Adobe Pro fonts have ranges that overlap by one element: the |
406 // start of one range is equal to the end of the previous range. Therefore | 403 // start of one range is equal to the end of the previous range. Therefore |
407 // the < in the following condition should be <= were it not for this. | 404 // the < in the following condition should be <= were it not for this. |
408 // See crbug.com/134135. | 405 // See crbug.com/134135. |
409 if (start > end || (last_end && start < last_end)) { | 406 if (start > end || (last_end && start < last_end)) { |
410 OTS_WARNING("glyph range is overlapping."); | 407 return OTS_FAILURE_MSG("glyph range is overlapping."); |
411 return OTS_FAILURE(); | |
412 } | 408 } |
413 if (start_coverage_index != last_start_coverage_index) { | 409 if (start_coverage_index != last_start_coverage_index) { |
414 OTS_WARNING("bad start coverage index."); | 410 return OTS_FAILURE_MSG("bad start coverage index."); |
415 return OTS_FAILURE(); | |
416 } | 411 } |
417 last_end = end; | 412 last_end = end; |
418 last_start_coverage_index += end - start + 1; | 413 last_start_coverage_index += end - start + 1; |
419 } | 414 } |
420 | 415 |
421 if (expected_num_glyphs && | 416 if (expected_num_glyphs && |
422 expected_num_glyphs != last_start_coverage_index) { | 417 expected_num_glyphs != last_start_coverage_index) { |
423 OTS_WARNING("unexpected number of glyphs: %u", last_start_coverage_index); | 418 return OTS_FAILURE_MSG("unexpected number of glyphs: %u", last_start_cover
age_index); |
424 return OTS_FAILURE(); | |
425 } | 419 } |
426 | 420 |
427 return true; | 421 return true; |
428 } | 422 } |
429 | 423 |
430 // Parsers for Contextual subtables in GSUB/GPOS tables. | 424 // Parsers for Contextual subtables in GSUB/GPOS tables. |
431 | 425 |
432 bool ParseLookupRecord(ots::Buffer *subtable, const uint16_t num_glyphs, | 426 bool ParseLookupRecord(const ots::OpenTypeFile *file, |
| 427 ots::Buffer *subtable, const uint16_t num_glyphs, |
433 const uint16_t num_lookups) { | 428 const uint16_t num_lookups) { |
434 uint16_t sequence_index = 0; | 429 uint16_t sequence_index = 0; |
435 uint16_t lookup_list_index = 0; | 430 uint16_t lookup_list_index = 0; |
436 if (!subtable->ReadU16(&sequence_index) || | 431 if (!subtable->ReadU16(&sequence_index) || |
437 !subtable->ReadU16(&lookup_list_index)) { | 432 !subtable->ReadU16(&lookup_list_index)) { |
438 return OTS_FAILURE(); | 433 return OTS_FAILURE_MSG("Failed to read header for lookup record"); |
439 } | 434 } |
440 if (sequence_index >= num_glyphs) { | 435 if (sequence_index >= num_glyphs) { |
441 return OTS_FAILURE(); | 436 return OTS_FAILURE_MSG("Bad sequence index %d in lookup record", sequence_in
dex); |
442 } | 437 } |
443 if (lookup_list_index >= num_lookups) { | 438 if (lookup_list_index >= num_lookups) { |
444 return OTS_FAILURE(); | 439 return OTS_FAILURE_MSG("Bad lookup list index %d in lookup record", lookup_l
ist_index); |
445 } | 440 } |
446 return true; | 441 return true; |
447 } | 442 } |
448 | 443 |
449 bool ParseRuleSubtable(const uint8_t *data, const size_t length, | 444 bool ParseRuleSubtable(const ots::OpenTypeFile *file, |
| 445 const uint8_t *data, const size_t length, |
450 const uint16_t num_glyphs, | 446 const uint16_t num_glyphs, |
451 const uint16_t num_lookups) { | 447 const uint16_t num_lookups) { |
452 ots::Buffer subtable(data, length); | 448 ots::Buffer subtable(data, length); |
453 | 449 |
454 uint16_t glyph_count = 0; | 450 uint16_t glyph_count = 0; |
455 uint16_t lookup_count = 0; | 451 uint16_t lookup_count = 0; |
456 if (!subtable.ReadU16(&glyph_count) || | 452 if (!subtable.ReadU16(&glyph_count) || |
457 !subtable.ReadU16(&lookup_count)) { | 453 !subtable.ReadU16(&lookup_count)) { |
458 return OTS_FAILURE(); | 454 return OTS_FAILURE_MSG("Failed to read rule subtable header"); |
459 } | 455 } |
460 | 456 |
461 if (glyph_count == 0 || glyph_count >= num_glyphs) { | 457 if (glyph_count == 0 || glyph_count >= num_glyphs) { |
462 return OTS_FAILURE(); | 458 return OTS_FAILURE_MSG("Bad glyph count %d in rule subtable", glyph_count); |
463 } | 459 } |
464 for (unsigned i = 0; i < glyph_count - static_cast<unsigned>(1); ++i) { | 460 for (unsigned i = 0; i < glyph_count - static_cast<unsigned>(1); ++i) { |
465 uint16_t glyph_id = 0; | 461 uint16_t glyph_id = 0; |
466 if (!subtable.ReadU16(&glyph_id)) { | 462 if (!subtable.ReadU16(&glyph_id)) { |
467 return OTS_FAILURE(); | 463 return OTS_FAILURE_MSG("Failed to read glyph %d", i); |
468 } | 464 } |
469 if (glyph_id > num_glyphs) { | 465 if (glyph_id > num_glyphs) { |
470 return OTS_FAILURE(); | 466 return OTS_FAILURE_MSG("Bad glyph %d for entry %d", glyph_id, i); |
471 } | 467 } |
472 } | 468 } |
473 | 469 |
474 for (unsigned i = 0; i < lookup_count; ++i) { | 470 for (unsigned i = 0; i < lookup_count; ++i) { |
475 if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) { | 471 if (!ParseLookupRecord(file, &subtable, num_glyphs, num_lookups)) { |
476 return OTS_FAILURE(); | 472 return OTS_FAILURE_MSG("Failed to parse lookup record %d", i); |
477 } | 473 } |
478 } | 474 } |
479 return true; | 475 return true; |
480 } | 476 } |
481 | 477 |
482 bool ParseRuleSetTable(const uint8_t *data, const size_t length, | 478 bool ParseRuleSetTable(const ots::OpenTypeFile *file, |
| 479 const uint8_t *data, const size_t length, |
483 const uint16_t num_glyphs, | 480 const uint16_t num_glyphs, |
484 const uint16_t num_lookups) { | 481 const uint16_t num_lookups) { |
485 ots::Buffer subtable(data, length); | 482 ots::Buffer subtable(data, length); |
486 | 483 |
487 uint16_t rule_count = 0; | 484 uint16_t rule_count = 0; |
488 if (!subtable.ReadU16(&rule_count)) { | 485 if (!subtable.ReadU16(&rule_count)) { |
489 return OTS_FAILURE(); | 486 return OTS_FAILURE_MSG("Failed to read rule count in rule set"); |
490 } | 487 } |
491 const unsigned rule_end = 2 * static_cast<unsigned>(rule_count) + 2; | 488 const unsigned rule_end = 2 * static_cast<unsigned>(rule_count) + 2; |
492 if (rule_end > std::numeric_limits<uint16_t>::max()) { | 489 if (rule_end > std::numeric_limits<uint16_t>::max()) { |
493 return OTS_FAILURE(); | 490 return OTS_FAILURE_MSG("Bad end of rule %d in rule set", rule_end); |
494 } | 491 } |
495 | 492 |
496 for (unsigned i = 0; i < rule_count; ++i) { | 493 for (unsigned i = 0; i < rule_count; ++i) { |
497 uint16_t offset_rule = 0; | 494 uint16_t offset_rule = 0; |
498 if (!subtable.ReadU16(&offset_rule)) { | 495 if (!subtable.ReadU16(&offset_rule)) { |
499 return OTS_FAILURE(); | 496 return OTS_FAILURE_MSG("Failed to read rule offset for rule set %d", i); |
500 } | 497 } |
501 if (offset_rule < rule_end || offset_rule >= length) { | 498 if (offset_rule < rule_end || offset_rule >= length) { |
502 return OTS_FAILURE(); | 499 return OTS_FAILURE_MSG("Bad rule offset %d in set %d", offset_rule, i); |
503 } | 500 } |
504 if (!ParseRuleSubtable(data + offset_rule, length - offset_rule, | 501 if (!ParseRuleSubtable(file, data + offset_rule, length - offset_rule, |
505 num_glyphs, num_lookups)) { | 502 num_glyphs, num_lookups)) { |
506 return OTS_FAILURE(); | 503 return OTS_FAILURE_MSG("Failed to parse rule set %d", i); |
507 } | 504 } |
508 } | 505 } |
509 | 506 |
510 return true; | 507 return true; |
511 } | 508 } |
512 | 509 |
513 bool ParseContextFormat1(const uint8_t *data, const size_t length, | 510 bool ParseContextFormat1(const ots::OpenTypeFile *file, |
| 511 const uint8_t *data, const size_t length, |
514 const uint16_t num_glyphs, | 512 const uint16_t num_glyphs, |
515 const uint16_t num_lookups) { | 513 const uint16_t num_lookups) { |
516 ots::Buffer subtable(data, length); | 514 ots::Buffer subtable(data, length); |
517 | 515 |
518 uint16_t offset_coverage = 0; | 516 uint16_t offset_coverage = 0; |
519 uint16_t rule_set_count = 0; | 517 uint16_t rule_set_count = 0; |
520 // Skip format field. | 518 // Skip format field. |
521 if (!subtable.Skip(2) || | 519 if (!subtable.Skip(2) || |
522 !subtable.ReadU16(&offset_coverage) || | 520 !subtable.ReadU16(&offset_coverage) || |
523 !subtable.ReadU16(&rule_set_count)) { | 521 !subtable.ReadU16(&rule_set_count)) { |
524 return OTS_FAILURE(); | 522 return OTS_FAILURE_MSG("Failed to read header of context format 1"); |
525 } | 523 } |
526 | 524 |
527 const unsigned rule_set_end = static_cast<unsigned>(6) + | 525 const unsigned rule_set_end = static_cast<unsigned>(6) + |
528 rule_set_count * 2; | 526 rule_set_count * 2; |
529 if (rule_set_end > std::numeric_limits<uint16_t>::max()) { | 527 if (rule_set_end > std::numeric_limits<uint16_t>::max()) { |
530 return OTS_FAILURE(); | 528 return OTS_FAILURE_MSG("Bad end of rule set %d of context format 1", rule_se
t_end); |
531 } | 529 } |
532 if (offset_coverage < rule_set_end || offset_coverage >= length) { | 530 if (offset_coverage < rule_set_end || offset_coverage >= length) { |
533 return OTS_FAILURE(); | 531 return OTS_FAILURE_MSG("Bad coverage offset %d in context format 1", offset_
coverage); |
534 } | 532 } |
535 if (!ots::ParseCoverageTable(data + offset_coverage, | 533 if (!ots::ParseCoverageTable(file, data + offset_coverage, |
536 length - offset_coverage, num_glyphs)) { | 534 length - offset_coverage, num_glyphs)) { |
537 return OTS_FAILURE(); | 535 return OTS_FAILURE_MSG("Failed to parse coverage table in context format 1")
; |
538 } | 536 } |
539 | 537 |
540 for (unsigned i = 0; i < rule_set_count; ++i) { | 538 for (unsigned i = 0; i < rule_set_count; ++i) { |
541 uint16_t offset_rule = 0; | 539 uint16_t offset_rule = 0; |
542 if (!subtable.ReadU16(&offset_rule)) { | 540 if (!subtable.ReadU16(&offset_rule)) { |
543 return OTS_FAILURE(); | 541 return OTS_FAILURE_MSG("Failed to read rule offset %d in context format 1"
, i); |
544 } | 542 } |
545 if (offset_rule < rule_set_end || offset_rule >= length) { | 543 if (offset_rule < rule_set_end || offset_rule >= length) { |
546 return OTS_FAILURE(); | 544 return OTS_FAILURE_MSG("Bad rule offset %d in rule %d in context format 1"
, offset_rule, i); |
547 } | 545 } |
548 if (!ParseRuleSetTable(data + offset_rule, length - offset_rule, | 546 if (!ParseRuleSetTable(file, data + offset_rule, length - offset_rule, |
549 num_glyphs, num_lookups)) { | 547 num_glyphs, num_lookups)) { |
550 return OTS_FAILURE(); | 548 return OTS_FAILURE_MSG("Failed to parse rule set %d in context format 1",
i); |
551 } | 549 } |
552 } | 550 } |
553 | 551 |
554 return true; | 552 return true; |
555 } | 553 } |
556 | 554 |
557 bool ParseClassRuleTable(const uint8_t *data, const size_t length, | 555 bool ParseClassRuleTable(const ots::OpenTypeFile *file, |
| 556 const uint8_t *data, const size_t length, |
558 const uint16_t num_glyphs, | 557 const uint16_t num_glyphs, |
559 const uint16_t num_lookups) { | 558 const uint16_t num_lookups) { |
560 ots::Buffer subtable(data, length); | 559 ots::Buffer subtable(data, length); |
561 | 560 |
562 uint16_t glyph_count = 0; | 561 uint16_t glyph_count = 0; |
563 uint16_t lookup_count = 0; | 562 uint16_t lookup_count = 0; |
564 if (!subtable.ReadU16(&glyph_count) || | 563 if (!subtable.ReadU16(&glyph_count) || |
565 !subtable.ReadU16(&lookup_count)) { | 564 !subtable.ReadU16(&lookup_count)) { |
566 return OTS_FAILURE(); | 565 return OTS_FAILURE_MSG("Failed to read header of class rule table"); |
567 } | 566 } |
568 | 567 |
569 if (glyph_count == 0 || glyph_count >= num_glyphs) { | 568 if (glyph_count == 0 || glyph_count >= num_glyphs) { |
570 return OTS_FAILURE(); | 569 return OTS_FAILURE_MSG("Bad glyph count %d in class rule table", glyph_count
); |
571 } | 570 } |
572 | 571 |
573 // ClassRule table contains an array of classes. Each value of classes | 572 // ClassRule table contains an array of classes. Each value of classes |
574 // could take arbitrary values including zero so we don't check these value. | 573 // could take arbitrary values including zero so we don't check these value. |
575 const unsigned num_classes = glyph_count - static_cast<unsigned>(1); | 574 const unsigned num_classes = glyph_count - static_cast<unsigned>(1); |
576 if (!subtable.Skip(2 * num_classes)) { | 575 if (!subtable.Skip(2 * num_classes)) { |
577 return OTS_FAILURE(); | 576 return OTS_FAILURE_MSG("Failed to skip classes in class rule table"); |
578 } | 577 } |
579 | 578 |
580 for (unsigned i = 0; i < lookup_count; ++i) { | 579 for (unsigned i = 0; i < lookup_count; ++i) { |
581 if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) { | 580 if (!ParseLookupRecord(file, &subtable, num_glyphs, num_lookups)) { |
582 return OTS_FAILURE(); | 581 return OTS_FAILURE_MSG("Failed to parse lookup record %d in class rule tab
le", i); |
583 } | 582 } |
584 } | 583 } |
585 return true; | 584 return true; |
586 } | 585 } |
587 | 586 |
588 bool ParseClassSetTable(const uint8_t *data, const size_t length, | 587 bool ParseClassSetTable(const ots::OpenTypeFile *file, |
| 588 const uint8_t *data, const size_t length, |
589 const uint16_t num_glyphs, | 589 const uint16_t num_glyphs, |
590 const uint16_t num_lookups) { | 590 const uint16_t num_lookups) { |
591 ots::Buffer subtable(data, length); | 591 ots::Buffer subtable(data, length); |
592 | 592 |
593 uint16_t class_rule_count = 0; | 593 uint16_t class_rule_count = 0; |
594 if (!subtable.ReadU16(&class_rule_count)) { | 594 if (!subtable.ReadU16(&class_rule_count)) { |
595 return OTS_FAILURE(); | 595 return OTS_FAILURE_MSG("Failed to read class rule count in class set table")
; |
596 } | 596 } |
597 const unsigned class_rule_end = | 597 const unsigned class_rule_end = |
598 2 * static_cast<unsigned>(class_rule_count) + 2; | 598 2 * static_cast<unsigned>(class_rule_count) + 2; |
599 if (class_rule_end > std::numeric_limits<uint16_t>::max()) { | 599 if (class_rule_end > std::numeric_limits<uint16_t>::max()) { |
600 return OTS_FAILURE(); | 600 return OTS_FAILURE_MSG("bad class rule end %d in class set table", class_rul
e_end); |
601 } | 601 } |
602 for (unsigned i = 0; i < class_rule_count; ++i) { | 602 for (unsigned i = 0; i < class_rule_count; ++i) { |
603 uint16_t offset_class_rule = 0; | 603 uint16_t offset_class_rule = 0; |
604 if (!subtable.ReadU16(&offset_class_rule)) { | 604 if (!subtable.ReadU16(&offset_class_rule)) { |
605 return OTS_FAILURE(); | 605 return OTS_FAILURE_MSG("Failed to read class rule offset %d in class set t
able", i); |
606 } | 606 } |
607 if (offset_class_rule < class_rule_end || offset_class_rule >= length) { | 607 if (offset_class_rule < class_rule_end || offset_class_rule >= length) { |
608 return OTS_FAILURE(); | 608 return OTS_FAILURE_MSG("Bad class rule offset %d in class %d", offset_clas
s_rule, i); |
609 } | 609 } |
610 if (!ParseClassRuleTable(data + offset_class_rule, | 610 if (!ParseClassRuleTable(file, data + offset_class_rule, |
611 length - offset_class_rule, num_glyphs, | 611 length - offset_class_rule, num_glyphs, |
612 num_lookups)) { | 612 num_lookups)) { |
613 return OTS_FAILURE(); | 613 return OTS_FAILURE_MSG("Failed to parse class rule table %d", i); |
614 } | 614 } |
615 } | 615 } |
616 | 616 |
617 return true; | 617 return true; |
618 } | 618 } |
619 | 619 |
620 bool ParseContextFormat2(const uint8_t *data, const size_t length, | 620 bool ParseContextFormat2(const ots::OpenTypeFile *file, |
621 const uint16_t num_glyphs, | 621 const uint8_t *data, const size_t length, |
622 const uint16_t num_lookups) { | 622 const uint16_t num_glyphs, |
| 623 const uint16_t num_lookups) { |
623 ots::Buffer subtable(data, length); | 624 ots::Buffer subtable(data, length); |
624 | 625 |
625 uint16_t offset_coverage = 0; | 626 uint16_t offset_coverage = 0; |
626 uint16_t offset_class_def = 0; | 627 uint16_t offset_class_def = 0; |
627 uint16_t class_set_cnt = 0; | 628 uint16_t class_set_cnt = 0; |
628 // Skip format field. | 629 // Skip format field. |
629 if (!subtable.Skip(2) || | 630 if (!subtable.Skip(2) || |
630 !subtable.ReadU16(&offset_coverage) || | 631 !subtable.ReadU16(&offset_coverage) || |
631 !subtable.ReadU16(&offset_class_def) || | 632 !subtable.ReadU16(&offset_class_def) || |
632 !subtable.ReadU16(&class_set_cnt)) { | 633 !subtable.ReadU16(&class_set_cnt)) { |
633 return OTS_FAILURE(); | 634 return OTS_FAILURE_MSG("Failed to read header for context format 2"); |
634 } | 635 } |
635 | 636 |
636 const unsigned class_set_end = 2 * static_cast<unsigned>(class_set_cnt) + 8; | 637 const unsigned class_set_end = 2 * static_cast<unsigned>(class_set_cnt) + 8; |
637 if (class_set_end > std::numeric_limits<uint16_t>::max()) { | 638 if (class_set_end > std::numeric_limits<uint16_t>::max()) { |
638 return OTS_FAILURE(); | 639 return OTS_FAILURE_MSG("Bad end of class set %d for context format 2", class
_set_end); |
639 } | 640 } |
640 if (offset_coverage < class_set_end || offset_coverage >= length) { | 641 if (offset_coverage < class_set_end || offset_coverage >= length) { |
641 return OTS_FAILURE(); | 642 return OTS_FAILURE_MSG("Bad coverage offset %d in context format 2", offset_
coverage); |
642 } | 643 } |
643 if (!ots::ParseCoverageTable(data + offset_coverage, | 644 if (!ots::ParseCoverageTable(file, data + offset_coverage, |
644 length - offset_coverage, num_glyphs)) { | 645 length - offset_coverage, num_glyphs)) { |
645 return OTS_FAILURE(); | 646 return OTS_FAILURE_MSG("Failed to parse coverage table in context format 2")
; |
646 } | 647 } |
647 | 648 |
648 if (offset_class_def < class_set_end || offset_class_def >= length) { | 649 if (offset_class_def < class_set_end || offset_class_def >= length) { |
649 return OTS_FAILURE(); | 650 return OTS_FAILURE_MSG("bad class definition offset %d in context format 2",
offset_class_def); |
650 } | 651 } |
651 if (!ots::ParseClassDefTable(data + offset_class_def, | 652 if (!ots::ParseClassDefTable(file, data + offset_class_def, |
652 length - offset_class_def, | 653 length - offset_class_def, |
653 num_glyphs, kMaxClassDefValue)) { | 654 num_glyphs, kMaxClassDefValue)) { |
654 return OTS_FAILURE(); | 655 return OTS_FAILURE_MSG("Failed to parse class definition table in context fo
rmat 2"); |
655 } | 656 } |
656 | 657 |
657 for (unsigned i = 0; i < class_set_cnt; ++i) { | 658 for (unsigned i = 0; i < class_set_cnt; ++i) { |
658 uint16_t offset_class_rule = 0; | 659 uint16_t offset_class_rule = 0; |
659 if (!subtable.ReadU16(&offset_class_rule)) { | 660 if (!subtable.ReadU16(&offset_class_rule)) { |
660 return OTS_FAILURE(); | 661 return OTS_FAILURE_MSG("Failed to read class rule offset %d in context for
mat 2", i); |
661 } | 662 } |
662 if (offset_class_rule) { | 663 if (offset_class_rule) { |
663 if (offset_class_rule < class_set_end || offset_class_rule >= length) { | 664 if (offset_class_rule < class_set_end || offset_class_rule >= length) { |
664 return OTS_FAILURE(); | 665 return OTS_FAILURE_MSG("Bad class rule offset %d for rule %d in context
format 2", offset_class_rule, i); |
665 } | 666 } |
666 if (!ParseClassSetTable(data + offset_class_rule, | 667 if (!ParseClassSetTable(file, data + offset_class_rule, |
667 length - offset_class_rule, num_glyphs, | 668 length - offset_class_rule, num_glyphs, |
668 num_lookups)) { | 669 num_lookups)) { |
669 return OTS_FAILURE(); | 670 return OTS_FAILURE_MSG("Failed to parse class set %d in context format 2
", i); |
670 } | 671 } |
671 } | 672 } |
672 } | 673 } |
673 | 674 |
674 return true; | 675 return true; |
675 } | 676 } |
676 | 677 |
677 bool ParseContextFormat3(const uint8_t *data, const size_t length, | 678 bool ParseContextFormat3(const ots::OpenTypeFile *file, |
| 679 const uint8_t *data, const size_t length, |
678 const uint16_t num_glyphs, | 680 const uint16_t num_glyphs, |
679 const uint16_t num_lookups) { | 681 const uint16_t num_lookups) { |
680 ots::Buffer subtable(data, length); | 682 ots::Buffer subtable(data, length); |
681 | 683 |
682 uint16_t glyph_count = 0; | 684 uint16_t glyph_count = 0; |
683 uint16_t lookup_count = 0; | 685 uint16_t lookup_count = 0; |
684 // Skip format field. | 686 // Skip format field. |
685 if (!subtable.Skip(2) || | 687 if (!subtable.Skip(2) || |
686 !subtable.ReadU16(&glyph_count) || | 688 !subtable.ReadU16(&glyph_count) || |
687 !subtable.ReadU16(&lookup_count)) { | 689 !subtable.ReadU16(&lookup_count)) { |
688 return OTS_FAILURE(); | 690 return OTS_FAILURE_MSG("Failed to read header in context format 3"); |
689 } | 691 } |
690 | 692 |
691 if (glyph_count >= num_glyphs) { | 693 if (glyph_count >= num_glyphs) { |
692 return OTS_FAILURE(); | 694 return OTS_FAILURE_MSG("Bad glyph count %d in context format 3", glyph_count
); |
693 } | 695 } |
694 const unsigned lookup_record_end = 2 * static_cast<unsigned>(glyph_count) + | 696 const unsigned lookup_record_end = 2 * static_cast<unsigned>(glyph_count) + |
695 4 * static_cast<unsigned>(lookup_count) + 6; | 697 4 * static_cast<unsigned>(lookup_count) + 6; |
696 if (lookup_record_end > std::numeric_limits<uint16_t>::max()) { | 698 if (lookup_record_end > std::numeric_limits<uint16_t>::max()) { |
697 return OTS_FAILURE(); | 699 return OTS_FAILURE_MSG("Bad end of lookup %d in context format 3", lookup_re
cord_end); |
698 } | 700 } |
699 for (unsigned i = 0; i < glyph_count; ++i) { | 701 for (unsigned i = 0; i < glyph_count; ++i) { |
700 uint16_t offset_coverage = 0; | 702 uint16_t offset_coverage = 0; |
701 if (!subtable.ReadU16(&offset_coverage)) { | 703 if (!subtable.ReadU16(&offset_coverage)) { |
702 return OTS_FAILURE(); | 704 return OTS_FAILURE_MSG("Failed to read coverage offset %d in conxtext form
at 3", i); |
703 } | 705 } |
704 if (offset_coverage < lookup_record_end || offset_coverage >= length) { | 706 if (offset_coverage < lookup_record_end || offset_coverage >= length) { |
705 return OTS_FAILURE(); | 707 return OTS_FAILURE_MSG("Bad coverage offset %d for glyph %d in context for
mat 3", offset_coverage, i); |
706 } | 708 } |
707 if (!ots::ParseCoverageTable(data + offset_coverage, | 709 if (!ots::ParseCoverageTable(file, data + offset_coverage, |
708 length - offset_coverage, num_glyphs)) { | 710 length - offset_coverage, num_glyphs)) { |
709 return OTS_FAILURE(); | 711 return OTS_FAILURE_MSG("Failed to parse coverage table for glyph %d in con
text format 3", i); |
710 } | 712 } |
711 } | 713 } |
712 | 714 |
713 for (unsigned i = 0; i < lookup_count; ++i) { | 715 for (unsigned i = 0; i < lookup_count; ++i) { |
714 if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) { | 716 if (!ParseLookupRecord(file, &subtable, num_glyphs, num_lookups)) { |
715 return OTS_FAILURE(); | 717 return OTS_FAILURE_MSG("Failed to parse lookup record %d in context format
3", i); |
716 } | 718 } |
717 } | 719 } |
718 | 720 |
719 return true; | 721 return true; |
720 } | 722 } |
721 | 723 |
722 // Parsers for Chaning Contextual subtables in GSUB/GPOS tables. | 724 // Parsers for Chaning Contextual subtables in GSUB/GPOS tables. |
723 | 725 |
724 bool ParseChainRuleSubtable(const uint8_t *data, const size_t length, | 726 bool ParseChainRuleSubtable(const ots::OpenTypeFile *file, |
| 727 const uint8_t *data, const size_t length, |
725 const uint16_t num_glyphs, | 728 const uint16_t num_glyphs, |
726 const uint16_t num_lookups) { | 729 const uint16_t num_lookups) { |
727 ots::Buffer subtable(data, length); | 730 ots::Buffer subtable(data, length); |
728 | 731 |
729 uint16_t backtrack_count = 0; | 732 uint16_t backtrack_count = 0; |
730 if (!subtable.ReadU16(&backtrack_count)) { | 733 if (!subtable.ReadU16(&backtrack_count)) { |
731 return OTS_FAILURE(); | 734 return OTS_FAILURE_MSG("Failed to read backtrack count in chain rule subtabl
e"); |
732 } | 735 } |
733 if (backtrack_count >= num_glyphs) { | 736 if (backtrack_count >= num_glyphs) { |
734 return OTS_FAILURE(); | 737 return OTS_FAILURE_MSG("Bad backtrack count %d in chain rule subtable", back
track_count); |
735 } | 738 } |
736 for (unsigned i = 0; i < backtrack_count; ++i) { | 739 for (unsigned i = 0; i < backtrack_count; ++i) { |
737 uint16_t glyph_id = 0; | 740 uint16_t glyph_id = 0; |
738 if (!subtable.ReadU16(&glyph_id)) { | 741 if (!subtable.ReadU16(&glyph_id)) { |
739 return OTS_FAILURE(); | 742 return OTS_FAILURE_MSG("Failed to read backtrack glyph %d in chain rule su
btable", i); |
740 } | 743 } |
741 if (glyph_id > num_glyphs) { | 744 if (glyph_id > num_glyphs) { |
742 return OTS_FAILURE(); | 745 return OTS_FAILURE_MSG("Bad glyph id %d for bactrack glyph %d in chain rul
e subtable", glyph_id, i); |
743 } | 746 } |
744 } | 747 } |
745 | 748 |
746 uint16_t input_count = 0; | 749 uint16_t input_count = 0; |
747 if (!subtable.ReadU16(&input_count)) { | 750 if (!subtable.ReadU16(&input_count)) { |
748 return OTS_FAILURE(); | 751 return OTS_FAILURE_MSG("Failed to read input count in chain rule subtable"); |
749 } | 752 } |
750 if (input_count == 0 || input_count >= num_glyphs) { | 753 if (input_count == 0 || input_count >= num_glyphs) { |
751 return OTS_FAILURE(); | 754 return OTS_FAILURE_MSG("Bad input count %d in chain rule subtable", input_co
unt); |
752 } | 755 } |
753 for (unsigned i = 0; i < input_count - static_cast<unsigned>(1); ++i) { | 756 for (unsigned i = 0; i < input_count - static_cast<unsigned>(1); ++i) { |
754 uint16_t glyph_id = 0; | 757 uint16_t glyph_id = 0; |
755 if (!subtable.ReadU16(&glyph_id)) { | 758 if (!subtable.ReadU16(&glyph_id)) { |
756 return OTS_FAILURE(); | 759 return OTS_FAILURE_MSG("Failed to read input glyph %d in chain rule subtab
le", i); |
757 } | 760 } |
758 if (glyph_id > num_glyphs) { | 761 if (glyph_id > num_glyphs) { |
759 return OTS_FAILURE(); | 762 return OTS_FAILURE_MSG("Bad glyph id %d for input glyph %d in chain rule s
ubtable", glyph_id, i); |
760 } | 763 } |
761 } | 764 } |
762 | 765 |
763 uint16_t lookahead_count = 0; | 766 uint16_t lookahead_count = 0; |
764 if (!subtable.ReadU16(&lookahead_count)) { | 767 if (!subtable.ReadU16(&lookahead_count)) { |
765 return OTS_FAILURE(); | 768 return OTS_FAILURE_MSG("Failed to read lookahead count in chain rule subtabl
e"); |
766 } | 769 } |
767 if (lookahead_count >= num_glyphs) { | 770 if (lookahead_count >= num_glyphs) { |
768 return OTS_FAILURE(); | 771 return OTS_FAILURE_MSG("Bad lookahead count %d in chain rule subtable", look
ahead_count); |
769 } | 772 } |
770 for (unsigned i = 0; i < lookahead_count; ++i) { | 773 for (unsigned i = 0; i < lookahead_count; ++i) { |
771 uint16_t glyph_id = 0; | 774 uint16_t glyph_id = 0; |
772 if (!subtable.ReadU16(&glyph_id)) { | 775 if (!subtable.ReadU16(&glyph_id)) { |
773 return OTS_FAILURE(); | 776 return OTS_FAILURE_MSG("Failed to read lookahead glyph %d in chain rule su
btable", i); |
774 } | 777 } |
775 if (glyph_id > num_glyphs) { | 778 if (glyph_id > num_glyphs) { |
776 return OTS_FAILURE(); | 779 return OTS_FAILURE_MSG("Bad glyph id %d for lookadhead glyph %d in chain r
ule subtable", glyph_id, i); |
777 } | 780 } |
778 } | 781 } |
779 | 782 |
780 uint16_t lookup_count = 0; | 783 uint16_t lookup_count = 0; |
781 if (!subtable.ReadU16(&lookup_count)) { | 784 if (!subtable.ReadU16(&lookup_count)) { |
782 return OTS_FAILURE(); | 785 return OTS_FAILURE_MSG("Failed to read lookup count in chain rule subtable")
; |
783 } | 786 } |
784 for (unsigned i = 0; i < lookup_count; ++i) { | 787 for (unsigned i = 0; i < lookup_count; ++i) { |
785 if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) { | 788 if (!ParseLookupRecord(file, &subtable, num_glyphs, num_lookups)) { |
786 return OTS_FAILURE(); | 789 return OTS_FAILURE_MSG("Failed to parse lookup record %d in chain rule sub
table", i); |
787 } | 790 } |
788 } | 791 } |
789 | 792 |
790 return true; | 793 return true; |
791 } | 794 } |
792 | 795 |
793 bool ParseChainRuleSetTable(const uint8_t *data, const size_t length, | 796 bool ParseChainRuleSetTable(const ots::OpenTypeFile *file, |
| 797 const uint8_t *data, const size_t length, |
794 const uint16_t num_glyphs, | 798 const uint16_t num_glyphs, |
795 const uint16_t num_lookups) { | 799 const uint16_t num_lookups) { |
796 ots::Buffer subtable(data, length); | 800 ots::Buffer subtable(data, length); |
797 | 801 |
798 uint16_t chain_rule_count = 0; | 802 uint16_t chain_rule_count = 0; |
799 if (!subtable.ReadU16(&chain_rule_count)) { | 803 if (!subtable.ReadU16(&chain_rule_count)) { |
800 return OTS_FAILURE(); | 804 return OTS_FAILURE_MSG("Failed to read rule count in chain rule set"); |
801 } | 805 } |
802 const unsigned chain_rule_end = | 806 const unsigned chain_rule_end = |
803 2 * static_cast<unsigned>(chain_rule_count) + 2; | 807 2 * static_cast<unsigned>(chain_rule_count) + 2; |
804 if (chain_rule_end > std::numeric_limits<uint16_t>::max()) { | 808 if (chain_rule_end > std::numeric_limits<uint16_t>::max()) { |
805 return OTS_FAILURE(); | 809 return OTS_FAILURE_MSG("Bad end of chain rule %d in chain rule set", chain_r
ule_end); |
806 } | 810 } |
807 for (unsigned i = 0; i < chain_rule_count; ++i) { | 811 for (unsigned i = 0; i < chain_rule_count; ++i) { |
808 uint16_t offset_chain_rule = 0; | 812 uint16_t offset_chain_rule = 0; |
809 if (!subtable.ReadU16(&offset_chain_rule)) { | 813 if (!subtable.ReadU16(&offset_chain_rule)) { |
810 return OTS_FAILURE(); | 814 return OTS_FAILURE_MSG("Failed to read chain rule offset %d in chain rule
set", i); |
811 } | 815 } |
812 if (offset_chain_rule < chain_rule_end || offset_chain_rule >= length) { | 816 if (offset_chain_rule < chain_rule_end || offset_chain_rule >= length) { |
813 return OTS_FAILURE(); | 817 return OTS_FAILURE_MSG("Bad chain rule offset %d for chain rule %d in chai
n rule set", offset_chain_rule, i); |
814 } | 818 } |
815 if (!ParseChainRuleSubtable(data + offset_chain_rule, | 819 if (!ParseChainRuleSubtable(file, data + offset_chain_rule, |
816 length - offset_chain_rule, | 820 length - offset_chain_rule, |
817 num_glyphs, num_lookups)) { | 821 num_glyphs, num_lookups)) { |
818 return OTS_FAILURE(); | 822 return OTS_FAILURE_MSG("Failed to parse chain rule %d in chain rule set",
i); |
819 } | 823 } |
820 } | 824 } |
821 | 825 |
822 return true; | 826 return true; |
823 } | 827 } |
824 | 828 |
825 bool ParseChainContextFormat1(const uint8_t *data, const size_t length, | 829 bool ParseChainContextFormat1(const ots::OpenTypeFile *file, |
| 830 const uint8_t *data, const size_t length, |
826 const uint16_t num_glyphs, | 831 const uint16_t num_glyphs, |
827 const uint16_t num_lookups) { | 832 const uint16_t num_lookups) { |
828 ots::Buffer subtable(data, length); | 833 ots::Buffer subtable(data, length); |
829 | 834 |
830 uint16_t offset_coverage = 0; | 835 uint16_t offset_coverage = 0; |
831 uint16_t chain_rule_set_count = 0; | 836 uint16_t chain_rule_set_count = 0; |
832 // Skip format field. | 837 // Skip format field. |
833 if (!subtable.Skip(2) || | 838 if (!subtable.Skip(2) || |
834 !subtable.ReadU16(&offset_coverage) || | 839 !subtable.ReadU16(&offset_coverage) || |
835 !subtable.ReadU16(&chain_rule_set_count)) { | 840 !subtable.ReadU16(&chain_rule_set_count)) { |
836 return OTS_FAILURE(); | 841 return OTS_FAILURE_MSG("Failed to read header of chain context format 1"); |
837 } | 842 } |
838 | 843 |
839 const unsigned chain_rule_set_end = | 844 const unsigned chain_rule_set_end = |
840 2 * static_cast<unsigned>(chain_rule_set_count) + 6; | 845 2 * static_cast<unsigned>(chain_rule_set_count) + 6; |
841 if (chain_rule_set_end > std::numeric_limits<uint16_t>::max()) { | 846 if (chain_rule_set_end > std::numeric_limits<uint16_t>::max()) { |
842 return OTS_FAILURE(); | 847 return OTS_FAILURE_MSG("Bad chain rule end %d in chain context format 1", ch
ain_rule_set_end); |
843 } | 848 } |
844 if (offset_coverage < chain_rule_set_end || offset_coverage >= length) { | 849 if (offset_coverage < chain_rule_set_end || offset_coverage >= length) { |
845 return OTS_FAILURE(); | 850 return OTS_FAILURE_MSG("Bad coverage offset %d in chain context format 1", c
hain_rule_set_end); |
846 } | 851 } |
847 if (!ots::ParseCoverageTable(data + offset_coverage, | 852 if (!ots::ParseCoverageTable(file, data + offset_coverage, |
848 length - offset_coverage, num_glyphs)) { | 853 length - offset_coverage, num_glyphs)) { |
849 return OTS_FAILURE(); | 854 return OTS_FAILURE_MSG("Failed to parse coverage table for chain context for
mat 1"); |
850 } | 855 } |
851 | 856 |
852 for (unsigned i = 0; i < chain_rule_set_count; ++i) { | 857 for (unsigned i = 0; i < chain_rule_set_count; ++i) { |
853 uint16_t offset_chain_rule_set = 0; | 858 uint16_t offset_chain_rule_set = 0; |
854 if (!subtable.ReadU16(&offset_chain_rule_set)) { | 859 if (!subtable.ReadU16(&offset_chain_rule_set)) { |
855 return OTS_FAILURE(); | 860 return OTS_FAILURE_MSG("Failed to read chain rule offset %d in chain conte
xt format 1", i); |
856 } | 861 } |
857 if (offset_chain_rule_set < chain_rule_set_end || | 862 if (offset_chain_rule_set < chain_rule_set_end || |
858 offset_chain_rule_set >= length) { | 863 offset_chain_rule_set >= length) { |
859 return OTS_FAILURE(); | 864 return OTS_FAILURE_MSG("Bad chain rule set offset %d for chain rule set %d
in chain context format 1", offset_chain_rule_set, i); |
860 } | 865 } |
861 if (!ParseChainRuleSetTable(data + offset_chain_rule_set, | 866 if (!ParseChainRuleSetTable(file, data + offset_chain_rule_set, |
862 length - offset_chain_rule_set, | 867 length - offset_chain_rule_set, |
863 num_glyphs, num_lookups)) { | 868 num_glyphs, num_lookups)) { |
864 return OTS_FAILURE(); | 869 return OTS_FAILURE_MSG("Failed to parse chain rule set %d in chain context
format 1", i); |
865 } | 870 } |
866 } | 871 } |
867 | 872 |
868 return true; | 873 return true; |
869 } | 874 } |
870 | 875 |
871 bool ParseChainClassRuleSubtable(const uint8_t *data, const size_t length, | 876 bool ParseChainClassRuleSubtable(const ots::OpenTypeFile *file, |
| 877 const uint8_t *data, const size_t length, |
872 const uint16_t num_glyphs, | 878 const uint16_t num_glyphs, |
873 const uint16_t num_lookups) { | 879 const uint16_t num_lookups) { |
874 ots::Buffer subtable(data, length); | 880 ots::Buffer subtable(data, length); |
875 | 881 |
876 // In this subtable, we don't check the value of classes for now since | 882 // In this subtable, we don't check the value of classes for now since |
877 // these could take arbitrary values. | 883 // these could take arbitrary values. |
878 | 884 |
879 uint16_t backtrack_count = 0; | 885 uint16_t backtrack_count = 0; |
880 if (!subtable.ReadU16(&backtrack_count)) { | 886 if (!subtable.ReadU16(&backtrack_count)) { |
881 return OTS_FAILURE(); | 887 return OTS_FAILURE_MSG("Failed to read backtrack count in chain class rule s
ubtable"); |
882 } | 888 } |
883 if (backtrack_count >= num_glyphs) { | 889 if (backtrack_count >= num_glyphs) { |
884 return OTS_FAILURE(); | 890 return OTS_FAILURE_MSG("Bad backtrack count %d in chain class rule subtable"
, backtrack_count); |
885 } | 891 } |
886 if (!subtable.Skip(2 * backtrack_count)) { | 892 if (!subtable.Skip(2 * backtrack_count)) { |
887 return OTS_FAILURE(); | 893 return OTS_FAILURE_MSG("Failed to skip backtrack offsets in chain class rule
subtable"); |
888 } | 894 } |
889 | 895 |
890 uint16_t input_count = 0; | 896 uint16_t input_count = 0; |
891 if (!subtable.ReadU16(&input_count)) { | 897 if (!subtable.ReadU16(&input_count)) { |
892 return OTS_FAILURE(); | 898 return OTS_FAILURE_MSG("Failed to read input count in chain class rule subta
ble"); |
893 } | 899 } |
894 if (input_count == 0 || input_count >= num_glyphs) { | 900 if (input_count == 0 || input_count >= num_glyphs) { |
895 return OTS_FAILURE(); | 901 return OTS_FAILURE_MSG("Bad input count %d in chain class rule subtable", in
put_count); |
896 } | 902 } |
897 if (!subtable.Skip(2 * (input_count - 1))) { | 903 if (!subtable.Skip(2 * (input_count - 1))) { |
898 return OTS_FAILURE(); | 904 return OTS_FAILURE_MSG("Failed to skip input offsets in chain class rule sub
table"); |
899 } | 905 } |
900 | 906 |
901 uint16_t lookahead_count = 0; | 907 uint16_t lookahead_count = 0; |
902 if (!subtable.ReadU16(&lookahead_count)) { | 908 if (!subtable.ReadU16(&lookahead_count)) { |
903 return OTS_FAILURE(); | 909 return OTS_FAILURE_MSG("Failed to read lookahead count in chain class rule s
ubtable"); |
904 } | 910 } |
905 if (lookahead_count >= num_glyphs) { | 911 if (lookahead_count >= num_glyphs) { |
906 return OTS_FAILURE(); | 912 return OTS_FAILURE_MSG("Bad lookahead count %d in chain class rule subtable"
, lookahead_count); |
907 } | 913 } |
908 if (!subtable.Skip(2 * lookahead_count)) { | 914 if (!subtable.Skip(2 * lookahead_count)) { |
909 return OTS_FAILURE(); | 915 return OTS_FAILURE_MSG("Failed to skip lookahead offsets in chain class rule
subtable"); |
910 } | 916 } |
911 | 917 |
912 uint16_t lookup_count = 0; | 918 uint16_t lookup_count = 0; |
913 if (!subtable.ReadU16(&lookup_count)) { | 919 if (!subtable.ReadU16(&lookup_count)) { |
914 return OTS_FAILURE(); | 920 return OTS_FAILURE_MSG("Failed to read lookup count in chain class rule subt
able"); |
915 } | 921 } |
916 for (unsigned i = 0; i < lookup_count; ++i) { | 922 for (unsigned i = 0; i < lookup_count; ++i) { |
917 if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) { | 923 if (!ParseLookupRecord(file, &subtable, num_glyphs, num_lookups)) { |
918 return OTS_FAILURE(); | 924 return OTS_FAILURE_MSG("Failed to parse lookup record %d in chain class ru
le subtable", i); |
919 } | 925 } |
920 } | 926 } |
921 | 927 |
922 return true; | 928 return true; |
923 } | 929 } |
924 | 930 |
925 bool ParseChainClassSetTable(const uint8_t *data, const size_t length, | 931 bool ParseChainClassSetTable(const ots::OpenTypeFile *file, |
| 932 const uint8_t *data, const size_t length, |
926 const uint16_t num_glyphs, | 933 const uint16_t num_glyphs, |
927 const uint16_t num_lookups) { | 934 const uint16_t num_lookups) { |
928 ots::Buffer subtable(data, length); | 935 ots::Buffer subtable(data, length); |
929 | 936 |
930 uint16_t chain_class_rule_count = 0; | 937 uint16_t chain_class_rule_count = 0; |
931 if (!subtable.ReadU16(&chain_class_rule_count)) { | 938 if (!subtable.ReadU16(&chain_class_rule_count)) { |
932 return OTS_FAILURE(); | 939 return OTS_FAILURE_MSG("Failed to read rule count in chain class set"); |
933 } | 940 } |
934 const unsigned chain_class_rule_end = | 941 const unsigned chain_class_rule_end = |
935 2 * static_cast<unsigned>(chain_class_rule_count) + 2; | 942 2 * static_cast<unsigned>(chain_class_rule_count) + 2; |
936 if (chain_class_rule_end > std::numeric_limits<uint16_t>::max()) { | 943 if (chain_class_rule_end > std::numeric_limits<uint16_t>::max()) { |
937 return OTS_FAILURE(); | 944 return OTS_FAILURE_MSG("Bad end of chain class set %d in chain class set", c
hain_class_rule_end); |
938 } | 945 } |
939 for (unsigned i = 0; i < chain_class_rule_count; ++i) { | 946 for (unsigned i = 0; i < chain_class_rule_count; ++i) { |
940 uint16_t offset_chain_class_rule = 0; | 947 uint16_t offset_chain_class_rule = 0; |
941 if (!subtable.ReadU16(&offset_chain_class_rule)) { | 948 if (!subtable.ReadU16(&offset_chain_class_rule)) { |
942 return OTS_FAILURE(); | 949 return OTS_FAILURE_MSG("Failed to read chain class rule offset %d in chain
class set", i); |
943 } | 950 } |
944 if (offset_chain_class_rule < chain_class_rule_end || | 951 if (offset_chain_class_rule < chain_class_rule_end || |
945 offset_chain_class_rule >= length) { | 952 offset_chain_class_rule >= length) { |
946 return OTS_FAILURE(); | 953 return OTS_FAILURE_MSG("Bad chain class rule offset %d for chain class %d
in chain class set", offset_chain_class_rule, i); |
947 } | 954 } |
948 if (!ParseChainClassRuleSubtable(data + offset_chain_class_rule, | 955 if (!ParseChainClassRuleSubtable(file, data + offset_chain_class_rule, |
949 length - offset_chain_class_rule, | 956 length - offset_chain_class_rule, |
950 num_glyphs, num_lookups)) { | 957 num_glyphs, num_lookups)) { |
951 return OTS_FAILURE(); | 958 return OTS_FAILURE_MSG("Failed to parse chain class rule %d in chain class
set", i); |
952 } | 959 } |
953 } | 960 } |
954 | 961 |
955 return true; | 962 return true; |
956 } | 963 } |
957 | 964 |
958 bool ParseChainContextFormat2(const uint8_t *data, const size_t length, | 965 bool ParseChainContextFormat2(const ots::OpenTypeFile *file, |
| 966 const uint8_t *data, const size_t length, |
959 const uint16_t num_glyphs, | 967 const uint16_t num_glyphs, |
960 const uint16_t num_lookups) { | 968 const uint16_t num_lookups) { |
961 ots::Buffer subtable(data, length); | 969 ots::Buffer subtable(data, length); |
962 | 970 |
963 uint16_t offset_coverage = 0; | 971 uint16_t offset_coverage = 0; |
964 uint16_t offset_backtrack_class_def = 0; | 972 uint16_t offset_backtrack_class_def = 0; |
965 uint16_t offset_input_class_def = 0; | 973 uint16_t offset_input_class_def = 0; |
966 uint16_t offset_lookahead_class_def = 0; | 974 uint16_t offset_lookahead_class_def = 0; |
967 uint16_t chain_class_set_count = 0; | 975 uint16_t chain_class_set_count = 0; |
968 // Skip format field. | 976 // Skip format field. |
969 if (!subtable.Skip(2) || | 977 if (!subtable.Skip(2) || |
970 !subtable.ReadU16(&offset_coverage) || | 978 !subtable.ReadU16(&offset_coverage) || |
971 !subtable.ReadU16(&offset_backtrack_class_def) || | 979 !subtable.ReadU16(&offset_backtrack_class_def) || |
972 !subtable.ReadU16(&offset_input_class_def) || | 980 !subtable.ReadU16(&offset_input_class_def) || |
973 !subtable.ReadU16(&offset_lookahead_class_def) || | 981 !subtable.ReadU16(&offset_lookahead_class_def) || |
974 !subtable.ReadU16(&chain_class_set_count)) { | 982 !subtable.ReadU16(&chain_class_set_count)) { |
975 return OTS_FAILURE(); | 983 return OTS_FAILURE_MSG("Failed to read header of chain context format 2"); |
976 } | 984 } |
977 | 985 |
978 const unsigned chain_class_set_end = | 986 const unsigned chain_class_set_end = |
979 2 * static_cast<unsigned>(chain_class_set_count) + 12; | 987 2 * static_cast<unsigned>(chain_class_set_count) + 12; |
980 if (chain_class_set_end > std::numeric_limits<uint16_t>::max()) { | 988 if (chain_class_set_end > std::numeric_limits<uint16_t>::max()) { |
981 return OTS_FAILURE(); | 989 return OTS_FAILURE_MSG("Bad chain class set end %d in chain context format 2
", chain_class_set_end); |
982 } | 990 } |
983 if (offset_coverage < chain_class_set_end || offset_coverage >= length) { | 991 if (offset_coverage < chain_class_set_end || offset_coverage >= length) { |
984 return OTS_FAILURE(); | 992 return OTS_FAILURE_MSG("Bad coverage offset %d in chain context format 2", o
ffset_coverage); |
985 } | 993 } |
986 if (!ots::ParseCoverageTable(data + offset_coverage, | 994 if (!ots::ParseCoverageTable(file, data + offset_coverage, |
987 length - offset_coverage, num_glyphs)) { | 995 length - offset_coverage, num_glyphs)) { |
988 return OTS_FAILURE(); | 996 return OTS_FAILURE_MSG("Failed to parse coverage table in chain context form
at 2"); |
989 } | 997 } |
990 | 998 |
991 // Classes for backtrack/lookahead sequences might not be defined. | 999 // Classes for backtrack/lookahead sequences might not be defined. |
992 if (offset_backtrack_class_def) { | 1000 if (offset_backtrack_class_def) { |
993 if (offset_backtrack_class_def < chain_class_set_end || | 1001 if (offset_backtrack_class_def < chain_class_set_end || |
994 offset_backtrack_class_def >= length) { | 1002 offset_backtrack_class_def >= length) { |
995 return OTS_FAILURE(); | 1003 return OTS_FAILURE_MSG("Bad backtrack class offset %d in chain context for
mat 2", offset_backtrack_class_def); |
996 } | 1004 } |
997 if (!ots::ParseClassDefTable(data + offset_backtrack_class_def, | 1005 if (!ots::ParseClassDefTable(file, data + offset_backtrack_class_def, |
998 length - offset_backtrack_class_def, | 1006 length - offset_backtrack_class_def, |
999 num_glyphs, kMaxClassDefValue)) { | 1007 num_glyphs, kMaxClassDefValue)) { |
1000 return OTS_FAILURE(); | 1008 return OTS_FAILURE_MSG("Failed to parse backtrack class defn table in chai
n context format 2"); |
1001 } | 1009 } |
1002 } | 1010 } |
1003 | 1011 |
1004 if (offset_input_class_def < chain_class_set_end || | 1012 if (offset_input_class_def < chain_class_set_end || |
1005 offset_input_class_def >= length) { | 1013 offset_input_class_def >= length) { |
1006 return OTS_FAILURE(); | 1014 return OTS_FAILURE_MSG("Bad input class defn offset %d in chain context form
at 2", offset_input_class_def); |
1007 } | 1015 } |
1008 if (!ots::ParseClassDefTable(data + offset_input_class_def, | 1016 if (!ots::ParseClassDefTable(file, data + offset_input_class_def, |
1009 length - offset_input_class_def, | 1017 length - offset_input_class_def, |
1010 num_glyphs, kMaxClassDefValue)) { | 1018 num_glyphs, kMaxClassDefValue)) { |
1011 return OTS_FAILURE(); | 1019 return OTS_FAILURE_MSG("Failed to parse input class defn in chain context fo
rmat 2"); |
1012 } | 1020 } |
1013 | 1021 |
1014 if (offset_lookahead_class_def) { | 1022 if (offset_lookahead_class_def) { |
1015 if (offset_lookahead_class_def < chain_class_set_end || | 1023 if (offset_lookahead_class_def < chain_class_set_end || |
1016 offset_lookahead_class_def >= length) { | 1024 offset_lookahead_class_def >= length) { |
1017 return OTS_FAILURE(); | 1025 return OTS_FAILURE_MSG("Bad lookahead class defn offset %d in chain contex
t format 2", offset_lookahead_class_def); |
1018 } | 1026 } |
1019 if (!ots::ParseClassDefTable(data + offset_lookahead_class_def, | 1027 if (!ots::ParseClassDefTable(file, data + offset_lookahead_class_def, |
1020 length - offset_lookahead_class_def, | 1028 length - offset_lookahead_class_def, |
1021 num_glyphs, kMaxClassDefValue)) { | 1029 num_glyphs, kMaxClassDefValue)) { |
1022 return OTS_FAILURE(); | 1030 return OTS_FAILURE_MSG("Failed to parse lookahead class defn in chain cont
ext format 2"); |
1023 } | 1031 } |
1024 } | 1032 } |
1025 | 1033 |
1026 for (unsigned i = 0; i < chain_class_set_count; ++i) { | 1034 for (unsigned i = 0; i < chain_class_set_count; ++i) { |
1027 uint16_t offset_chain_class_set = 0; | 1035 uint16_t offset_chain_class_set = 0; |
1028 if (!subtable.ReadU16(&offset_chain_class_set)) { | 1036 if (!subtable.ReadU16(&offset_chain_class_set)) { |
1029 return OTS_FAILURE(); | 1037 return OTS_FAILURE_MSG("Failed to read chain class set offset %d", i); |
1030 } | 1038 } |
1031 // |offset_chain_class_set| could be NULL. | 1039 // |offset_chain_class_set| could be NULL. |
1032 if (offset_chain_class_set) { | 1040 if (offset_chain_class_set) { |
1033 if (offset_chain_class_set < chain_class_set_end || | 1041 if (offset_chain_class_set < chain_class_set_end || |
1034 offset_chain_class_set >= length) { | 1042 offset_chain_class_set >= length) { |
1035 return OTS_FAILURE(); | 1043 return OTS_FAILURE_MSG("Bad chain set class offset %d for chain set %d i
n chain context format 2", offset_chain_class_set, i); |
1036 } | 1044 } |
1037 if (!ParseChainClassSetTable(data + offset_chain_class_set, | 1045 if (!ParseChainClassSetTable(file, data + offset_chain_class_set, |
1038 length - offset_chain_class_set, | 1046 length - offset_chain_class_set, |
1039 num_glyphs, num_lookups)) { | 1047 num_glyphs, num_lookups)) { |
1040 return OTS_FAILURE(); | 1048 return OTS_FAILURE_MSG("Failed to parse chain class set table %d in chai
n context format 2", i); |
1041 } | 1049 } |
1042 } | 1050 } |
1043 } | 1051 } |
1044 | 1052 |
1045 return true; | 1053 return true; |
1046 } | 1054 } |
1047 | 1055 |
1048 bool ParseChainContextFormat3(const uint8_t *data, const size_t length, | 1056 bool ParseChainContextFormat3(const ots::OpenTypeFile *file, |
| 1057 const uint8_t *data, const size_t length, |
1049 const uint16_t num_glyphs, | 1058 const uint16_t num_glyphs, |
1050 const uint16_t num_lookups) { | 1059 const uint16_t num_lookups) { |
1051 ots::Buffer subtable(data, length); | 1060 ots::Buffer subtable(data, length); |
1052 | 1061 |
1053 uint16_t backtrack_count = 0; | 1062 uint16_t backtrack_count = 0; |
1054 // Skip format field. | 1063 // Skip format field. |
1055 if (!subtable.Skip(2) || | 1064 if (!subtable.Skip(2) || |
1056 !subtable.ReadU16(&backtrack_count)) { | 1065 !subtable.ReadU16(&backtrack_count)) { |
1057 return OTS_FAILURE(); | 1066 return OTS_FAILURE_MSG("Failed to read backtrack count in chain context form
at 3"); |
1058 } | 1067 } |
1059 | 1068 |
1060 if (backtrack_count >= num_glyphs) { | 1069 if (backtrack_count >= num_glyphs) { |
1061 return OTS_FAILURE(); | 1070 return OTS_FAILURE_MSG("Bad backtrack count %d in chain context format 3", b
acktrack_count); |
1062 } | 1071 } |
1063 std::vector<uint16_t> offsets_backtrack; | 1072 std::vector<uint16_t> offsets_backtrack; |
1064 offsets_backtrack.reserve(backtrack_count); | 1073 offsets_backtrack.reserve(backtrack_count); |
1065 for (unsigned i = 0; i < backtrack_count; ++i) { | 1074 for (unsigned i = 0; i < backtrack_count; ++i) { |
1066 uint16_t offset = 0; | 1075 uint16_t offset = 0; |
1067 if (!subtable.ReadU16(&offset)) { | 1076 if (!subtable.ReadU16(&offset)) { |
1068 return OTS_FAILURE(); | 1077 return OTS_FAILURE_MSG("Failed to read backtrack offset %d in chain contex
t format 3", i); |
1069 } | 1078 } |
1070 offsets_backtrack.push_back(offset); | 1079 offsets_backtrack.push_back(offset); |
1071 } | 1080 } |
1072 if (offsets_backtrack.size() != backtrack_count) { | 1081 if (offsets_backtrack.size() != backtrack_count) { |
1073 return OTS_FAILURE(); | 1082 return OTS_FAILURE_MSG("Bad backtrack offsets size %ld in chain context form
at 3", offsets_backtrack.size()); |
1074 } | 1083 } |
1075 | 1084 |
1076 uint16_t input_count = 0; | 1085 uint16_t input_count = 0; |
1077 if (!subtable.ReadU16(&input_count)) { | 1086 if (!subtable.ReadU16(&input_count)) { |
1078 return OTS_FAILURE(); | 1087 return OTS_FAILURE_MSG("Failed to read input count in chain context format 3
"); |
1079 } | 1088 } |
1080 if (input_count >= num_glyphs) { | 1089 if (input_count >= num_glyphs) { |
1081 return OTS_FAILURE(); | 1090 return OTS_FAILURE_MSG("Bad input count %d in chain context format 3", input
_count); |
1082 } | 1091 } |
1083 std::vector<uint16_t> offsets_input; | 1092 std::vector<uint16_t> offsets_input; |
1084 offsets_input.reserve(input_count); | 1093 offsets_input.reserve(input_count); |
1085 for (unsigned i = 0; i < input_count; ++i) { | 1094 for (unsigned i = 0; i < input_count; ++i) { |
1086 uint16_t offset = 0; | 1095 uint16_t offset = 0; |
1087 if (!subtable.ReadU16(&offset)) { | 1096 if (!subtable.ReadU16(&offset)) { |
1088 return OTS_FAILURE(); | 1097 return OTS_FAILURE_MSG("Failed to read input offset %d in chain context fo
rmat 3", i); |
1089 } | 1098 } |
1090 offsets_input.push_back(offset); | 1099 offsets_input.push_back(offset); |
1091 } | 1100 } |
1092 if (offsets_input.size() != input_count) { | 1101 if (offsets_input.size() != input_count) { |
1093 return OTS_FAILURE(); | 1102 return OTS_FAILURE_MSG("Bad input offsets size %ld in chain context format 3
", offsets_input.size()); |
1094 } | 1103 } |
1095 | 1104 |
1096 uint16_t lookahead_count = 0; | 1105 uint16_t lookahead_count = 0; |
1097 if (!subtable.ReadU16(&lookahead_count)) { | 1106 if (!subtable.ReadU16(&lookahead_count)) { |
1098 return OTS_FAILURE(); | 1107 return OTS_FAILURE_MSG("Failed ot read lookahead count in chain context form
at 3"); |
1099 } | 1108 } |
1100 if (lookahead_count >= num_glyphs) { | 1109 if (lookahead_count >= num_glyphs) { |
1101 return OTS_FAILURE(); | 1110 return OTS_FAILURE_MSG("Bad lookahead count %d in chain context format 3", l
ookahead_count); |
1102 } | 1111 } |
1103 std::vector<uint16_t> offsets_lookahead; | 1112 std::vector<uint16_t> offsets_lookahead; |
1104 offsets_lookahead.reserve(lookahead_count); | 1113 offsets_lookahead.reserve(lookahead_count); |
1105 for (unsigned i = 0; i < lookahead_count; ++i) { | 1114 for (unsigned i = 0; i < lookahead_count; ++i) { |
1106 uint16_t offset = 0; | 1115 uint16_t offset = 0; |
1107 if (!subtable.ReadU16(&offset)) { | 1116 if (!subtable.ReadU16(&offset)) { |
1108 return OTS_FAILURE(); | 1117 return OTS_FAILURE_MSG("Failed to read lookahead offset %d in chain contex
t format 3", i); |
1109 } | 1118 } |
1110 offsets_lookahead.push_back(offset); | 1119 offsets_lookahead.push_back(offset); |
1111 } | 1120 } |
1112 if (offsets_lookahead.size() != lookahead_count) { | 1121 if (offsets_lookahead.size() != lookahead_count) { |
1113 return OTS_FAILURE(); | 1122 return OTS_FAILURE_MSG("Bad lookahead offsets size %ld in chain context form
at 3", offsets_lookahead.size()); |
1114 } | 1123 } |
1115 | 1124 |
1116 uint16_t lookup_count = 0; | 1125 uint16_t lookup_count = 0; |
1117 if (!subtable.ReadU16(&lookup_count)) { | 1126 if (!subtable.ReadU16(&lookup_count)) { |
1118 return OTS_FAILURE(); | 1127 return OTS_FAILURE_MSG("Failed to read lookup count in chain context format
3"); |
1119 } | 1128 } |
1120 for (unsigned i = 0; i < lookup_count; ++i) { | 1129 for (unsigned i = 0; i < lookup_count; ++i) { |
1121 if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) { | 1130 if (!ParseLookupRecord(file, &subtable, num_glyphs, num_lookups)) { |
1122 return OTS_FAILURE(); | 1131 return OTS_FAILURE_MSG("Failed to parse lookup %d in chain context format
3", i); |
1123 } | 1132 } |
1124 } | 1133 } |
1125 | 1134 |
1126 const unsigned lookup_record_end = | 1135 const unsigned lookup_record_end = |
1127 2 * (static_cast<unsigned>(backtrack_count) + | 1136 2 * (static_cast<unsigned>(backtrack_count) + |
1128 static_cast<unsigned>(input_count) + | 1137 static_cast<unsigned>(input_count) + |
1129 static_cast<unsigned>(lookahead_count)) + | 1138 static_cast<unsigned>(lookahead_count)) + |
1130 4 * static_cast<unsigned>(lookup_count) + 10; | 1139 4 * static_cast<unsigned>(lookup_count) + 10; |
1131 if (lookup_record_end > std::numeric_limits<uint16_t>::max()) { | 1140 if (lookup_record_end > std::numeric_limits<uint16_t>::max()) { |
1132 return OTS_FAILURE(); | 1141 return OTS_FAILURE_MSG("Bad end of lookup record %d in chain context format
3", lookup_record_end); |
1133 } | 1142 } |
1134 for (unsigned i = 0; i < backtrack_count; ++i) { | 1143 for (unsigned i = 0; i < backtrack_count; ++i) { |
1135 if (offsets_backtrack[i] < lookup_record_end || | 1144 if (offsets_backtrack[i] < lookup_record_end || |
1136 offsets_backtrack[i] >= length) { | 1145 offsets_backtrack[i] >= length) { |
1137 return OTS_FAILURE(); | 1146 return OTS_FAILURE_MSG("Bad backtrack offset of %d for backtrack %d in cha
in context format 3", offsets_backtrack[i], i); |
1138 } | 1147 } |
1139 if (!ots::ParseCoverageTable(data + offsets_backtrack[i], | 1148 if (!ots::ParseCoverageTable(file, data + offsets_backtrack[i], |
1140 length - offsets_backtrack[i], num_glyphs)) { | 1149 length - offsets_backtrack[i], num_glyphs)) { |
1141 return OTS_FAILURE(); | 1150 return OTS_FAILURE_MSG("Failed to parse backtrack coverage %d in chain con
text format 3", i); |
1142 } | 1151 } |
1143 } | 1152 } |
1144 for (unsigned i = 0; i < input_count; ++i) { | 1153 for (unsigned i = 0; i < input_count; ++i) { |
1145 if (offsets_input[i] < lookup_record_end || offsets_input[i] >= length) { | 1154 if (offsets_input[i] < lookup_record_end || offsets_input[i] >= length) { |
1146 return OTS_FAILURE(); | 1155 return OTS_FAILURE_MSG("Bad input offset %d for input %d in chain context
format 3", offsets_input[i], i); |
1147 } | 1156 } |
1148 if (!ots::ParseCoverageTable(data + offsets_input[i], | 1157 if (!ots::ParseCoverageTable(file, data + offsets_input[i], |
1149 length - offsets_input[i], num_glyphs)) { | 1158 length - offsets_input[i], num_glyphs)) { |
1150 return OTS_FAILURE(); | 1159 return OTS_FAILURE_MSG("Failed to parse input coverage table %d in chain c
ontext format 3", i); |
1151 } | 1160 } |
1152 } | 1161 } |
1153 for (unsigned i = 0; i < lookahead_count; ++i) { | 1162 for (unsigned i = 0; i < lookahead_count; ++i) { |
1154 if (offsets_lookahead[i] < lookup_record_end || | 1163 if (offsets_lookahead[i] < lookup_record_end || |
1155 offsets_lookahead[i] >= length) { | 1164 offsets_lookahead[i] >= length) { |
1156 return OTS_FAILURE(); | 1165 return OTS_FAILURE_MSG("Bad lookadhead offset %d for lookahead %d in chain
context format 3", offsets_lookahead[i], i); |
1157 } | 1166 } |
1158 if (!ots::ParseCoverageTable(data + offsets_lookahead[i], | 1167 if (!ots::ParseCoverageTable(file, data + offsets_lookahead[i], |
1159 length - offsets_lookahead[i], num_glyphs)) { | 1168 length - offsets_lookahead[i], num_glyphs)) { |
1160 return OTS_FAILURE(); | 1169 return OTS_FAILURE_MSG("Failed to parse lookahead coverage table %d in cha
in context format 3", i); |
1161 } | 1170 } |
1162 } | 1171 } |
1163 | 1172 |
1164 return true; | 1173 return true; |
1165 } | 1174 } |
1166 | 1175 |
1167 } // namespace | 1176 } // namespace |
1168 | 1177 |
1169 namespace ots { | 1178 namespace ots { |
1170 | 1179 |
1171 bool LookupSubtableParser::Parse(const OpenTypeFile *file, const uint8_t *data, | 1180 bool LookupSubtableParser::Parse(const OpenTypeFile *file, const uint8_t *data, |
1172 const size_t length, | 1181 const size_t length, |
1173 const uint16_t lookup_type) const { | 1182 const uint16_t lookup_type) const { |
1174 for (unsigned i = 0; i < num_types; ++i) { | 1183 for (unsigned i = 0; i < num_types; ++i) { |
1175 if (parsers[i].type == lookup_type && parsers[i].parse) { | 1184 if (parsers[i].type == lookup_type && parsers[i].parse) { |
1176 if (!parsers[i].parse(file, data, length)) { | 1185 if (!parsers[i].parse(file, data, length)) { |
1177 return OTS_FAILURE(); | 1186 return OTS_FAILURE_MSG("Failed to parse lookup subtable %d", i); |
1178 } | 1187 } |
1179 return true; | 1188 return true; |
1180 } | 1189 } |
1181 } | 1190 } |
1182 return OTS_FAILURE(); | 1191 return OTS_FAILURE_MSG("No lookup subtables to parse"); |
1183 } | 1192 } |
1184 | 1193 |
1185 // Parsing ScriptListTable requires number of features so we need to | 1194 // Parsing ScriptListTable requires number of features so we need to |
1186 // parse FeatureListTable before calling this function. | 1195 // parse FeatureListTable before calling this function. |
1187 bool ParseScriptListTable(const uint8_t *data, const size_t length, | 1196 bool ParseScriptListTable(const ots::OpenTypeFile *file, |
| 1197 const uint8_t *data, const size_t length, |
1188 const uint16_t num_features) { | 1198 const uint16_t num_features) { |
1189 Buffer subtable(data, length); | 1199 Buffer subtable(data, length); |
1190 | 1200 |
1191 uint16_t script_count = 0; | 1201 uint16_t script_count = 0; |
1192 if (!subtable.ReadU16(&script_count)) { | 1202 if (!subtable.ReadU16(&script_count)) { |
1193 return OTS_FAILURE(); | 1203 return OTS_FAILURE_MSG("Failed to read script count in script list table"); |
1194 } | 1204 } |
1195 | 1205 |
1196 const unsigned script_record_end = | 1206 const unsigned script_record_end = |
1197 6 * static_cast<unsigned>(script_count) + 2; | 1207 6 * static_cast<unsigned>(script_count) + 2; |
1198 if (script_record_end > std::numeric_limits<uint16_t>::max()) { | 1208 if (script_record_end > std::numeric_limits<uint16_t>::max()) { |
1199 return OTS_FAILURE(); | 1209 return OTS_FAILURE_MSG("Bad end of script record %d in script list table", s
cript_record_end); |
1200 } | 1210 } |
1201 std::vector<ScriptRecord> script_list; | 1211 std::vector<ScriptRecord> script_list; |
1202 script_list.reserve(script_count); | 1212 script_list.reserve(script_count); |
1203 uint32_t last_tag = 0; | 1213 uint32_t last_tag = 0; |
1204 for (unsigned i = 0; i < script_count; ++i) { | 1214 for (unsigned i = 0; i < script_count; ++i) { |
1205 ScriptRecord record; | 1215 ScriptRecord record; |
1206 if (!subtable.ReadU32(&record.tag) || | 1216 if (!subtable.ReadU32(&record.tag) || |
1207 !subtable.ReadU16(&record.offset)) { | 1217 !subtable.ReadU16(&record.offset)) { |
1208 return OTS_FAILURE(); | 1218 return OTS_FAILURE_MSG("Failed to read script record %d in script list tab
le", i); |
1209 } | 1219 } |
1210 // Script tags should be arranged alphabetically by tag | 1220 // Script tags should be arranged alphabetically by tag |
1211 if (last_tag != 0 && last_tag > record.tag) { | 1221 if (last_tag != 0 && last_tag > record.tag) { |
1212 // Several fonts don't arrange tags alphabetically. | 1222 // Several fonts don't arrange tags alphabetically. |
1213 // It seems that the order of tags might not be a security issue | 1223 // It seems that the order of tags might not be a security issue |
1214 // so we just warn it. | 1224 // so we just warn it. |
1215 OTS_WARNING("tags aren't arranged alphabetically."); | 1225 OTS_WARNING("tags aren't arranged alphabetically."); |
1216 } | 1226 } |
1217 last_tag = record.tag; | 1227 last_tag = record.tag; |
1218 if (record.offset < script_record_end || record.offset >= length) { | 1228 if (record.offset < script_record_end || record.offset >= length) { |
1219 return OTS_FAILURE(); | 1229 return OTS_FAILURE_MSG("Bad record offset %d for script %4.4s entry %d in
script list table", record.offset, (char *)&record.tag, i); |
1220 } | 1230 } |
1221 script_list.push_back(record); | 1231 script_list.push_back(record); |
1222 } | 1232 } |
1223 if (script_list.size() != script_count) { | 1233 if (script_list.size() != script_count) { |
1224 return OTS_FAILURE(); | 1234 return OTS_FAILURE_MSG("Bad script list size %ld in script list table", scri
pt_list.size()); |
1225 } | 1235 } |
1226 | 1236 |
1227 // Check script records. | 1237 // Check script records. |
1228 for (unsigned i = 0; i < script_count; ++i) { | 1238 for (unsigned i = 0; i < script_count; ++i) { |
1229 if (!ParseScriptTable(data + script_list[i].offset, | 1239 if (!ParseScriptTable(file, data + script_list[i].offset, |
1230 length - script_list[i].offset, | 1240 length - script_list[i].offset, |
1231 script_list[i].tag, num_features)) { | 1241 script_list[i].tag, num_features)) { |
1232 return OTS_FAILURE(); | 1242 return OTS_FAILURE_MSG("Failed to parse script table %d", i); |
1233 } | 1243 } |
1234 } | 1244 } |
1235 | 1245 |
1236 return true; | 1246 return true; |
1237 } | 1247 } |
1238 | 1248 |
1239 // Parsing FeatureListTable requires number of lookups so we need to parse | 1249 // Parsing FeatureListTable requires number of lookups so we need to parse |
1240 // LookupListTable before calling this function. | 1250 // LookupListTable before calling this function. |
1241 bool ParseFeatureListTable(const uint8_t *data, const size_t length, | 1251 bool ParseFeatureListTable(const ots::OpenTypeFile *file, |
| 1252 const uint8_t *data, const size_t length, |
1242 const uint16_t num_lookups, | 1253 const uint16_t num_lookups, |
1243 uint16_t* num_features) { | 1254 uint16_t* num_features) { |
1244 Buffer subtable(data, length); | 1255 Buffer subtable(data, length); |
1245 | 1256 |
1246 uint16_t feature_count = 0; | 1257 uint16_t feature_count = 0; |
1247 if (!subtable.ReadU16(&feature_count)) { | 1258 if (!subtable.ReadU16(&feature_count)) { |
1248 return OTS_FAILURE(); | 1259 return OTS_FAILURE_MSG("Failed to read feature count"); |
1249 } | 1260 } |
1250 | 1261 |
1251 std::vector<FeatureRecord> feature_records; | 1262 std::vector<FeatureRecord> feature_records; |
1252 feature_records.resize(feature_count); | 1263 feature_records.resize(feature_count); |
1253 const unsigned feature_record_end = | 1264 const unsigned feature_record_end = |
1254 6 * static_cast<unsigned>(feature_count) + 2; | 1265 6 * static_cast<unsigned>(feature_count) + 2; |
1255 if (feature_record_end > std::numeric_limits<uint16_t>::max()) { | 1266 if (feature_record_end > std::numeric_limits<uint16_t>::max()) { |
1256 return OTS_FAILURE(); | 1267 return OTS_FAILURE_MSG("Bad end of feature record %d", feature_record_end); |
1257 } | 1268 } |
1258 uint32_t last_tag = 0; | 1269 uint32_t last_tag = 0; |
1259 for (unsigned i = 0; i < feature_count; ++i) { | 1270 for (unsigned i = 0; i < feature_count; ++i) { |
1260 if (!subtable.ReadU32(&feature_records[i].tag) || | 1271 if (!subtable.ReadU32(&feature_records[i].tag) || |
1261 !subtable.ReadU16(&feature_records[i].offset)) { | 1272 !subtable.ReadU16(&feature_records[i].offset)) { |
1262 return OTS_FAILURE(); | 1273 return OTS_FAILURE_MSG("Failed to read feature header %d", i); |
1263 } | 1274 } |
1264 // Feature record array should be arranged alphabetically by tag | 1275 // Feature record array should be arranged alphabetically by tag |
1265 if (last_tag != 0 && last_tag > feature_records[i].tag) { | 1276 if (last_tag != 0 && last_tag > feature_records[i].tag) { |
1266 // Several fonts don't arrange tags alphabetically. | 1277 // Several fonts don't arrange tags alphabetically. |
1267 // It seems that the order of tags might not be a security issue | 1278 // It seems that the order of tags might not be a security issue |
1268 // so we just warn it. | 1279 // so we just warn it. |
1269 OTS_WARNING("tags aren't arranged alphabetically."); | 1280 OTS_WARNING("tags aren't arranged alphabetically."); |
1270 } | 1281 } |
1271 last_tag = feature_records[i].tag; | 1282 last_tag = feature_records[i].tag; |
1272 if (feature_records[i].offset < feature_record_end || | 1283 if (feature_records[i].offset < feature_record_end || |
1273 feature_records[i].offset >= length) { | 1284 feature_records[i].offset >= length) { |
1274 return OTS_FAILURE(); | 1285 return OTS_FAILURE_MSG("Bad feature offset %d for feature %d %4.4s", featu
re_records[i].offset, i, (char *)&feature_records[i].tag); |
1275 } | 1286 } |
1276 } | 1287 } |
1277 | 1288 |
1278 for (unsigned i = 0; i < feature_count; ++i) { | 1289 for (unsigned i = 0; i < feature_count; ++i) { |
1279 if (!ParseFeatureTable(data + feature_records[i].offset, | 1290 if (!ParseFeatureTable(file, data + feature_records[i].offset, |
1280 length - feature_records[i].offset, num_lookups)) { | 1291 length - feature_records[i].offset, num_lookups)) { |
1281 return OTS_FAILURE(); | 1292 return OTS_FAILURE_MSG("Failed to parse feature table %d", i); |
1282 } | 1293 } |
1283 } | 1294 } |
1284 *num_features = feature_count; | 1295 *num_features = feature_count; |
1285 return true; | 1296 return true; |
1286 } | 1297 } |
1287 | 1298 |
1288 // For parsing GPOS/GSUB tables, this function should be called at first to | 1299 // For parsing GPOS/GSUB tables, this function should be called at first to |
1289 // obtain the number of lookups because parsing FeatureTableList requires | 1300 // obtain the number of lookups because parsing FeatureTableList requires |
1290 // the number. | 1301 // the number. |
1291 bool ParseLookupListTable(OpenTypeFile *file, const uint8_t *data, | 1302 bool ParseLookupListTable(OpenTypeFile *file, const uint8_t *data, |
1292 const size_t length, | 1303 const size_t length, |
1293 const LookupSubtableParser* parser, | 1304 const LookupSubtableParser* parser, |
1294 uint16_t *num_lookups) { | 1305 uint16_t *num_lookups) { |
1295 Buffer subtable(data, length); | 1306 Buffer subtable(data, length); |
1296 | 1307 |
1297 if (!subtable.ReadU16(num_lookups)) { | 1308 if (!subtable.ReadU16(num_lookups)) { |
1298 return OTS_FAILURE(); | 1309 return OTS_FAILURE_MSG("Failed to read number of lookups"); |
1299 } | 1310 } |
1300 | 1311 |
1301 std::vector<uint16_t> lookups; | 1312 std::vector<uint16_t> lookups; |
1302 lookups.reserve(*num_lookups); | 1313 lookups.reserve(*num_lookups); |
1303 const unsigned lookup_end = | 1314 const unsigned lookup_end = |
1304 2 * static_cast<unsigned>(*num_lookups) + 2; | 1315 2 * static_cast<unsigned>(*num_lookups) + 2; |
1305 if (lookup_end > std::numeric_limits<uint16_t>::max()) { | 1316 if (lookup_end > std::numeric_limits<uint16_t>::max()) { |
1306 return OTS_FAILURE(); | 1317 return OTS_FAILURE_MSG("Bad end of lookups %d", lookup_end); |
1307 } | 1318 } |
1308 for (unsigned i = 0; i < *num_lookups; ++i) { | 1319 for (unsigned i = 0; i < *num_lookups; ++i) { |
1309 uint16_t offset = 0; | 1320 uint16_t offset = 0; |
1310 if (!subtable.ReadU16(&offset)) { | 1321 if (!subtable.ReadU16(&offset)) { |
1311 return OTS_FAILURE(); | 1322 return OTS_FAILURE_MSG("Failed to read lookup offset %d", i); |
1312 } | 1323 } |
1313 if (offset < lookup_end || offset >= length) { | 1324 if (offset < lookup_end || offset >= length) { |
1314 return OTS_FAILURE(); | 1325 return OTS_FAILURE_MSG("Bad lookup offset %d for lookup %d", offset, i); |
1315 } | 1326 } |
1316 lookups.push_back(offset); | 1327 lookups.push_back(offset); |
1317 } | 1328 } |
1318 if (lookups.size() != *num_lookups) { | 1329 if (lookups.size() != *num_lookups) { |
1319 return OTS_FAILURE(); | 1330 return OTS_FAILURE_MSG("Bad lookup offsets list size %ld", lookups.size()); |
1320 } | 1331 } |
1321 | 1332 |
1322 for (unsigned i = 0; i < *num_lookups; ++i) { | 1333 for (unsigned i = 0; i < *num_lookups; ++i) { |
1323 if (!ParseLookupTable(file, data + lookups[i], length - lookups[i], | 1334 if (!ParseLookupTable(file, data + lookups[i], length - lookups[i], |
1324 parser)) { | 1335 parser)) { |
1325 return OTS_FAILURE(); | 1336 return OTS_FAILURE_MSG("Failed to parse lookup %d", i); |
1326 } | 1337 } |
1327 } | 1338 } |
1328 | 1339 |
1329 return true; | 1340 return true; |
1330 } | 1341 } |
1331 | 1342 |
1332 bool ParseClassDefTable(const uint8_t *data, size_t length, | 1343 bool ParseClassDefTable(const ots::OpenTypeFile *file, |
| 1344 const uint8_t *data, size_t length, |
1333 const uint16_t num_glyphs, | 1345 const uint16_t num_glyphs, |
1334 const uint16_t num_classes) { | 1346 const uint16_t num_classes) { |
1335 Buffer subtable(data, length); | 1347 Buffer subtable(data, length); |
1336 | 1348 |
1337 uint16_t format = 0; | 1349 uint16_t format = 0; |
1338 if (!subtable.ReadU16(&format)) { | 1350 if (!subtable.ReadU16(&format)) { |
1339 return OTS_FAILURE(); | 1351 return OTS_FAILURE_MSG("Failed to read class defn format"); |
1340 } | 1352 } |
1341 if (format == 1) { | 1353 if (format == 1) { |
1342 return ParseClassDefFormat1(data, length, num_glyphs, num_classes); | 1354 return ParseClassDefFormat1(file, data, length, num_glyphs, num_classes); |
1343 } else if (format == 2) { | 1355 } else if (format == 2) { |
1344 return ParseClassDefFormat2(data, length, num_glyphs, num_classes); | 1356 return ParseClassDefFormat2(file, data, length, num_glyphs, num_classes); |
1345 } | 1357 } |
1346 | 1358 |
1347 return OTS_FAILURE(); | 1359 return OTS_FAILURE_MSG("Bad class defn format %d", format); |
1348 } | 1360 } |
1349 | 1361 |
1350 bool ParseCoverageTable(const uint8_t *data, size_t length, | 1362 bool ParseCoverageTable(const ots::OpenTypeFile *file, |
| 1363 const uint8_t *data, size_t length, |
1351 const uint16_t num_glyphs, | 1364 const uint16_t num_glyphs, |
1352 const uint16_t expected_num_glyphs) { | 1365 const uint16_t expected_num_glyphs) { |
1353 Buffer subtable(data, length); | 1366 Buffer subtable(data, length); |
1354 | 1367 |
1355 uint16_t format = 0; | 1368 uint16_t format = 0; |
1356 if (!subtable.ReadU16(&format)) { | 1369 if (!subtable.ReadU16(&format)) { |
1357 return OTS_FAILURE(); | 1370 return OTS_FAILURE_MSG("Failed to read coverage table format"); |
1358 } | 1371 } |
1359 if (format == 1) { | 1372 if (format == 1) { |
1360 return ParseCoverageFormat1(data, length, num_glyphs, expected_num_glyphs); | 1373 return ParseCoverageFormat1(file, data, length, num_glyphs, expected_num_gly
phs); |
1361 } else if (format == 2) { | 1374 } else if (format == 2) { |
1362 return ParseCoverageFormat2(data, length, num_glyphs, expected_num_glyphs); | 1375 return ParseCoverageFormat2(file, data, length, num_glyphs, expected_num_gly
phs); |
1363 } | 1376 } |
1364 | 1377 |
1365 return OTS_FAILURE(); | 1378 return OTS_FAILURE_MSG("Bad coverage table format %d", format); |
1366 } | 1379 } |
1367 | 1380 |
1368 bool ParseDeviceTable(const uint8_t *data, size_t length) { | 1381 bool ParseDeviceTable(const ots::OpenTypeFile *file, |
| 1382 const uint8_t *data, size_t length) { |
1369 Buffer subtable(data, length); | 1383 Buffer subtable(data, length); |
1370 | 1384 |
1371 uint16_t start_size = 0; | 1385 uint16_t start_size = 0; |
1372 uint16_t end_size = 0; | 1386 uint16_t end_size = 0; |
1373 uint16_t delta_format = 0; | 1387 uint16_t delta_format = 0; |
1374 if (!subtable.ReadU16(&start_size) || | 1388 if (!subtable.ReadU16(&start_size) || |
1375 !subtable.ReadU16(&end_size) || | 1389 !subtable.ReadU16(&end_size) || |
1376 !subtable.ReadU16(&delta_format)) { | 1390 !subtable.ReadU16(&delta_format)) { |
1377 return OTS_FAILURE(); | 1391 return OTS_FAILURE_MSG("Failed to read device table header"); |
1378 } | 1392 } |
1379 if (start_size > end_size) { | 1393 if (start_size > end_size) { |
1380 OTS_WARNING("bad size range: %u > %u", start_size, end_size); | 1394 return OTS_FAILURE_MSG("bad size range: %u > %u", start_size, end_size); |
1381 return OTS_FAILURE(); | |
1382 } | 1395 } |
1383 if (delta_format == 0 || delta_format > kMaxDeltaFormatType) { | 1396 if (delta_format == 0 || delta_format > kMaxDeltaFormatType) { |
1384 OTS_WARNING("bad delta format: %u", delta_format); | 1397 return OTS_FAILURE_MSG("bad delta format: %u", delta_format); |
1385 return OTS_FAILURE(); | |
1386 } | 1398 } |
1387 // The number of delta values per uint16. The device table should contain | 1399 // The number of delta values per uint16. The device table should contain |
1388 // at least |num_units| * 2 bytes compressed data. | 1400 // at least |num_units| * 2 bytes compressed data. |
1389 const unsigned num_units = (end_size - start_size) / | 1401 const unsigned num_units = (end_size - start_size) / |
1390 (1 << (4 - delta_format)) + 1; | 1402 (1 << (4 - delta_format)) + 1; |
1391 // Just skip |num_units| * 2 bytes since the compressed data could take | 1403 // Just skip |num_units| * 2 bytes since the compressed data could take |
1392 // arbitrary values. | 1404 // arbitrary values. |
1393 if (!subtable.Skip(num_units * 2)) { | 1405 if (!subtable.Skip(num_units * 2)) { |
1394 return OTS_FAILURE(); | 1406 return OTS_FAILURE_MSG("Failed to skip data in device table"); |
1395 } | 1407 } |
1396 return true; | 1408 return true; |
1397 } | 1409 } |
1398 | 1410 |
1399 bool ParseContextSubtable(const uint8_t *data, const size_t length, | 1411 bool ParseContextSubtable(const ots::OpenTypeFile *file, |
| 1412 const uint8_t *data, const size_t length, |
1400 const uint16_t num_glyphs, | 1413 const uint16_t num_glyphs, |
1401 const uint16_t num_lookups) { | 1414 const uint16_t num_lookups) { |
1402 Buffer subtable(data, length); | 1415 Buffer subtable(data, length); |
1403 | 1416 |
1404 uint16_t format = 0; | 1417 uint16_t format = 0; |
1405 if (!subtable.ReadU16(&format)) { | 1418 if (!subtable.ReadU16(&format)) { |
1406 return OTS_FAILURE(); | 1419 return OTS_FAILURE_MSG("Failed to read context subtable format"); |
1407 } | 1420 } |
1408 | 1421 |
1409 if (format == 1) { | 1422 if (format == 1) { |
1410 if (!ParseContextFormat1(data, length, num_glyphs, num_lookups)) { | 1423 if (!ParseContextFormat1(file, data, length, num_glyphs, num_lookups)) { |
1411 return OTS_FAILURE(); | 1424 return OTS_FAILURE_MSG("Failed to parse context format 1 subtable"); |
1412 } | 1425 } |
1413 } else if (format == 2) { | 1426 } else if (format == 2) { |
1414 if (!ParseContextFormat2(data, length, num_glyphs, num_lookups)) { | 1427 if (!ParseContextFormat2(file, data, length, num_glyphs, num_lookups)) { |
1415 return OTS_FAILURE(); | 1428 return OTS_FAILURE_MSG("Failed to parse context format 2 subtable"); |
1416 } | 1429 } |
1417 } else if (format == 3) { | 1430 } else if (format == 3) { |
1418 if (!ParseContextFormat3(data, length, num_glyphs, num_lookups)) { | 1431 if (!ParseContextFormat3(file, data, length, num_glyphs, num_lookups)) { |
1419 return OTS_FAILURE(); | 1432 return OTS_FAILURE_MSG("Failed to parse context format 3 subtable"); |
1420 } | 1433 } |
1421 } else { | 1434 } else { |
1422 return OTS_FAILURE(); | 1435 return OTS_FAILURE_MSG("Bad context subtable format %d", format); |
1423 } | 1436 } |
1424 | 1437 |
1425 return true; | 1438 return true; |
1426 } | 1439 } |
1427 | 1440 |
1428 bool ParseChainingContextSubtable(const uint8_t *data, const size_t length, | 1441 bool ParseChainingContextSubtable(const ots::OpenTypeFile *file, |
| 1442 const uint8_t *data, const size_t length, |
1429 const uint16_t num_glyphs, | 1443 const uint16_t num_glyphs, |
1430 const uint16_t num_lookups) { | 1444 const uint16_t num_lookups) { |
1431 Buffer subtable(data, length); | 1445 Buffer subtable(data, length); |
1432 | 1446 |
1433 uint16_t format = 0; | 1447 uint16_t format = 0; |
1434 if (!subtable.ReadU16(&format)) { | 1448 if (!subtable.ReadU16(&format)) { |
1435 return OTS_FAILURE(); | 1449 return OTS_FAILURE_MSG("Failed to read chaining context subtable format"); |
1436 } | 1450 } |
1437 | 1451 |
1438 if (format == 1) { | 1452 if (format == 1) { |
1439 if (!ParseChainContextFormat1(data, length, num_glyphs, num_lookups)) { | 1453 if (!ParseChainContextFormat1(file, data, length, num_glyphs, num_lookups))
{ |
1440 return OTS_FAILURE(); | 1454 return OTS_FAILURE_MSG("Failed to parse chaining context format 1 subtable
"); |
1441 } | 1455 } |
1442 } else if (format == 2) { | 1456 } else if (format == 2) { |
1443 if (!ParseChainContextFormat2(data, length, num_glyphs, num_lookups)) { | 1457 if (!ParseChainContextFormat2(file, data, length, num_glyphs, num_lookups))
{ |
1444 return OTS_FAILURE(); | 1458 return OTS_FAILURE_MSG("Failed to parse chaining context format 2 subtable
"); |
1445 } | 1459 } |
1446 } else if (format == 3) { | 1460 } else if (format == 3) { |
1447 if (!ParseChainContextFormat3(data, length, num_glyphs, num_lookups)) { | 1461 if (!ParseChainContextFormat3(file, data, length, num_glyphs, num_lookups))
{ |
1448 return OTS_FAILURE(); | 1462 return OTS_FAILURE_MSG("Failed to parse chaining context format 3 subtable
"); |
1449 } | 1463 } |
1450 } else { | 1464 } else { |
1451 return OTS_FAILURE(); | 1465 return OTS_FAILURE_MSG("Bad chaining context subtable format %d", format); |
1452 } | 1466 } |
1453 | 1467 |
1454 return true; | 1468 return true; |
1455 } | 1469 } |
1456 | 1470 |
1457 bool ParseExtensionSubtable(const OpenTypeFile *file, | 1471 bool ParseExtensionSubtable(const OpenTypeFile *file, |
1458 const uint8_t *data, const size_t length, | 1472 const uint8_t *data, const size_t length, |
1459 const LookupSubtableParser* parser) { | 1473 const LookupSubtableParser* parser) { |
1460 Buffer subtable(data, length); | 1474 Buffer subtable(data, length); |
1461 | 1475 |
1462 uint16_t format = 0; | 1476 uint16_t format = 0; |
1463 uint16_t lookup_type = 0; | 1477 uint16_t lookup_type = 0; |
1464 uint32_t offset_extension = 0; | 1478 uint32_t offset_extension = 0; |
1465 if (!subtable.ReadU16(&format) || | 1479 if (!subtable.ReadU16(&format) || |
1466 !subtable.ReadU16(&lookup_type) || | 1480 !subtable.ReadU16(&lookup_type) || |
1467 !subtable.ReadU32(&offset_extension)) { | 1481 !subtable.ReadU32(&offset_extension)) { |
1468 return OTS_FAILURE(); | 1482 return OTS_FAILURE_MSG("Failed to read extension table header"); |
1469 } | 1483 } |
1470 | 1484 |
1471 if (format != 1) { | 1485 if (format != 1) { |
1472 return OTS_FAILURE(); | 1486 return OTS_FAILURE_MSG("Bad extension table format %d", format); |
1473 } | 1487 } |
1474 // |lookup_type| should be other than |parser->extension_type|. | 1488 // |lookup_type| should be other than |parser->extension_type|. |
1475 if (lookup_type < 1 || lookup_type > parser->num_types || | 1489 if (lookup_type < 1 || lookup_type > parser->num_types || |
1476 lookup_type == parser->extension_type) { | 1490 lookup_type == parser->extension_type) { |
1477 return OTS_FAILURE(); | 1491 return OTS_FAILURE_MSG("Bad lookup type %d in extension table", lookup_type)
; |
1478 } | 1492 } |
1479 | 1493 |
1480 const unsigned format_end = static_cast<unsigned>(8); | 1494 const unsigned format_end = static_cast<unsigned>(8); |
1481 if (offset_extension < format_end || | 1495 if (offset_extension < format_end || |
1482 offset_extension >= length) { | 1496 offset_extension >= length) { |
1483 return OTS_FAILURE(); | 1497 return OTS_FAILURE_MSG("Bad extension offset %d", offset_extension); |
1484 } | 1498 } |
1485 | 1499 |
1486 // Parse the extension subtable of |lookup_type|. | 1500 // Parse the extension subtable of |lookup_type|. |
1487 if (!parser->Parse(file, data + offset_extension, length - offset_extension, | 1501 if (!parser->Parse(file, data + offset_extension, length - offset_extension, |
1488 lookup_type)) { | 1502 lookup_type)) { |
1489 return OTS_FAILURE(); | 1503 return OTS_FAILURE_MSG("Failed to parse lookup from extension lookup"); |
1490 } | 1504 } |
1491 | 1505 |
1492 return true; | 1506 return true; |
1493 } | 1507 } |
1494 | 1508 |
1495 } // namespace ots | 1509 } // namespace ots |
1496 | 1510 |
| 1511 #undef TABLE_NAME |
OLD | NEW |