PageRenderTime 28ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/gfx/ots/src/layout.cc

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