Chromium Code Reviews

Side by Side Diff: src/layout.cc

Issue 658573004: Updating to new OTS repo from https://github.com/khaledhosny/ots.git (Closed) Base URL: https://chromium.googlesource.com/external/ots@master
Patch Set: Adding Colored Emoji changes from external/git repo Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
« .gitmodules ('K') | « src/layout.h ('k') | src/loca.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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...)
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
OLDNEW
« .gitmodules ('K') | « src/layout.h ('k') | src/loca.cc » ('j') | no next file with comments »

Powered by Google App Engine