Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 // Copyright (c) 2012 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.
5 #include "cff.h"
7 #include <cstring>
8 #include <utility>
9 #include <vector>
11 #include "cff_type2_charstring.h"
13 // CFF - PostScript font program (Compact Font Format) table
14 // http://www.microsoft.com/typography/otspec/cff.htm
15 // http://www.microsoft.com/typography/otspec/cffspec.htm
17 #define TABLE_NAME "CFF"
19 namespace {
21 enum DICT_OPERAND_TYPE {
22 DICT_OPERAND_INTEGER,
23 DICT_OPERAND_REAL,
24 DICT_OPERATOR,
25 };
27 enum DICT_DATA_TYPE {
28 DICT_DATA_TOPLEVEL,
29 DICT_DATA_FDARRAY,
30 };
32 enum FONT_FORMAT {
33 FORMAT_UNKNOWN,
34 FORMAT_CID_KEYED,
35 FORMAT_OTHER, // Including synthetic fonts
36 };
38 // see Appendix. A
39 const size_t kNStdString = 390;
41 bool ReadOffset(ots::Buffer *table, uint8_t off_size, uint32_t *offset) {
42 if (off_size > 4) {
43 return OTS_FAILURE();
44 }
46 uint32_t tmp32 = 0;
47 for (unsigned i = 0; i < off_size; ++i) {
48 uint8_t tmp8 = 0;
49 if (!table->ReadU8(&tmp8)) {
50 return OTS_FAILURE();
51 }
52 tmp32 <<= 8;
53 tmp32 += tmp8;
54 }
55 *offset = tmp32;
56 return true;
57 }
59 bool ParseIndex(ots::Buffer *table, ots::CFFIndex *index) {
60 index->off_size = 0;
61 index->offsets.clear();
63 if (!table->ReadU16(&(index->count))) {
64 return OTS_FAILURE();
65 }
66 if (index->count == 0) {
67 // An empty INDEX.
68 index->offset_to_next = table->offset();
69 return true;
70 }
72 if (!table->ReadU8(&(index->off_size))) {
73 return OTS_FAILURE();
74 }
75 if ((index->off_size == 0) ||
76 (index->off_size > 4)) {
77 return OTS_FAILURE();
78 }
80 const size_t array_size = (index->count + 1) * index->off_size;
81 // less than ((64k + 1) * 4), thus does not overflow.
82 const size_t object_data_offset = table->offset() + array_size;
83 // does not overflow too, since offset() <= 1GB.
85 if (object_data_offset >= table->length()) {
86 return OTS_FAILURE();
87 }
89 for (unsigned i = 0; i <= index->count; ++i) { // '<=' is not a typo.
90 uint32_t rel_offset = 0;
91 if (!ReadOffset(table, index->off_size, &rel_offset)) {
92 return OTS_FAILURE();
93 }
94 if (rel_offset < 1) {
95 return OTS_FAILURE();
96 }
97 if (i == 0 && rel_offset != 1) {
98 return OTS_FAILURE();
99 }
101 if (rel_offset > table->length()) {
102 return OTS_FAILURE();
103 }
105 // does not underflow.
106 if (object_data_offset > table->length() - (rel_offset - 1)) {
107 return OTS_FAILURE();
108 }
110 index->offsets.push_back(
111 object_data_offset + (rel_offset - 1)); // less than length(), 1GB.
112 }
114 for (unsigned i = 1; i < index->offsets.size(); ++i) {
115 // We allow consecutive identical offsets here for zero-length strings.
116 // See http://crbug.com/69341 for more details.
117 if (index->offsets[i] < index->offsets[i - 1]) {
118 return OTS_FAILURE();
119 }
120 }
122 index->offset_to_next = index->offsets.back();
123 return true;
124 }
126 bool ParseNameData(
127 ots::Buffer *table, const ots::CFFIndex &index, std::string* out_name) {
128 uint8_t name[256] = {0};
129 if (index.offsets.size() == 0) { // just in case.
130 return OTS_FAILURE();
131 }
132 for (unsigned i = 1; i < index.offsets.size(); ++i) {
133 const size_t length = index.offsets[i] - index.offsets[i - 1];
134 // font names should be no longer than 127 characters.
135 if (length > 127) {
136 return OTS_FAILURE();
137 }
139 table->set_offset(index.offsets[i - 1]);
140 if (!table->Read(name, length)) {
141 return OTS_FAILURE();
142 }
144 for (size_t j = 0; j < length; ++j) {
145 // setting the first byte to NUL is allowed.
146 if (j == 0 && name[j] == 0) continue;
147 // non-ASCII characters are not recommended (except the first character).
148 if (name[j] < 33 || name[j] > 126) {
149 return OTS_FAILURE();
150 }
151 // [, ], ... are not allowed.
152 if (std::strchr("[](){}<>/% ", name[j])) {
153 return OTS_FAILURE();
154 }
155 }
156 }
158 *out_name = reinterpret_cast<char *>(name);
159 return true;
160 }
162 bool CheckOffset(const std::pair<uint32_t, DICT_OPERAND_TYPE>& operand,
163 size_t table_length) {
164 if (operand.second != DICT_OPERAND_INTEGER) {
165 return OTS_FAILURE();
166 }
167 if (operand.first >= table_length) {
168 return OTS_FAILURE();
169 }
170 return true;
171 }
173 bool CheckSid(const std::pair<uint32_t, DICT_OPERAND_TYPE>& operand,
174 size_t sid_max) {
175 if (operand.second != DICT_OPERAND_INTEGER) {
176 return OTS_FAILURE();
177 }
178 if (operand.first > sid_max) {
179 return OTS_FAILURE();
180 }
181 return true;
182 }
184 bool ParseDictDataBcd(
185 ots::Buffer *table,
186 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) {
187 bool read_decimal_point = false;
188 bool read_e = false;
190 uint8_t nibble = 0;
191 size_t count = 0;
192 while (true) {
193 if (!table->ReadU8(&nibble)) {
194 return OTS_FAILURE();
195 }
196 if ((nibble & 0xf0) == 0xf0) {
197 if ((nibble & 0xf) == 0xf) {
198 // TODO(yusukes): would be better to store actual double value,
199 // rather than the dummy integer.
200 operands->push_back(std::make_pair(static_cast<uint32_t>(0),
201 DICT_OPERAND_REAL));
202 return true;
203 }
204 return OTS_FAILURE();
205 }
206 if ((nibble & 0x0f) == 0x0f) {
207 operands->push_back(std::make_pair(static_cast<uint32_t>(0),
208 DICT_OPERAND_REAL));
209 return true;
210 }
212 // check number format
213 uint8_t nibbles[2];
214 nibbles[0] = (nibble & 0xf0) >> 8;
215 nibbles[1] = (nibble & 0x0f);
216 for (unsigned i = 0; i < 2; ++i) {
217 if (nibbles[i] == 0xd) { // reserved number
218 return OTS_FAILURE();
219 }
220 if ((nibbles[i] == 0xe) && // minus
221 ((count > 0) || (i > 0))) {
222 return OTS_FAILURE(); // minus sign should be the first character.
223 }
224 if (nibbles[i] == 0xa) { // decimal point
225 if (!read_decimal_point) {
226 read_decimal_point = true;
227 } else {
228 return OTS_FAILURE(); // two or more points.
229 }
230 }
231 if ((nibbles[i] == 0xb) || // E+
232 (nibbles[i] == 0xc)) { // E-
233 if (!read_e) {
234 read_e = true;
235 } else {
236 return OTS_FAILURE(); // two or more E's.
237 }
238 }
239 }
240 ++count;
241 }
242 }
244 bool ParseDictDataEscapedOperator(
245 ots::Buffer *table,
246 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) {
247 uint8_t op = 0;
248 if (!table->ReadU8(&op)) {
249 return OTS_FAILURE();
250 }
252 if ((op <= 14) ||
253 (op >= 17 && op <= 23) ||
254 (op >= 30 && op <= 38)) {
255 operands->push_back(std::make_pair((12U << 8) + op, DICT_OPERATOR));
256 return true;
257 }
259 // reserved area.
260 return OTS_FAILURE();
261 }
263 bool ParseDictDataNumber(
264 ots::Buffer *table, uint8_t b0,
265 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) {
266 uint8_t b1 = 0;
267 uint8_t b2 = 0;
268 uint8_t b3 = 0;
269 uint8_t b4 = 0;
271 switch (b0) {
272 case 28: // shortint
273 if (!table->ReadU8(&b1) ||
274 !table->ReadU8(&b2)) {
275 return OTS_FAILURE();
276 }
277 operands->push_back(std::make_pair(
278 static_cast<uint32_t>((b1 << 8) + b2), DICT_OPERAND_INTEGER));
279 return true;
281 case 29: // longint
282 if (!table->ReadU8(&b1) ||
283 !table->ReadU8(&b2) ||
284 !table->ReadU8(&b3) ||
285 !table->ReadU8(&b4)) {
286 return OTS_FAILURE();
287 }
288 operands->push_back(std::make_pair(
289 static_cast<uint32_t>((b1 << 24) + (b2 << 16) + (b3 << 8) + b4),
290 DICT_OPERAND_INTEGER));
291 return true;
293 case 30: // binary coded decimal
294 return ParseDictDataBcd(table, operands);
296 default:
297 break;
298 }
300 uint32_t result;
301 if (b0 >=32 && b0 <=246) {
302 result = b0 - 139;
303 } else if (b0 >=247 && b0 <= 250) {
304 if (!table->ReadU8(&b1)) {
305 return OTS_FAILURE();
306 }
307 result = (b0 - 247) * 256 + b1 + 108;
308 } else if (b0 >= 251 && b0 <= 254) {
309 if (!table->ReadU8(&b1)) {
310 return OTS_FAILURE();
311 }
312 result = -(b0 - 251) * 256 + b1 - 108;
313 } else {
314 return OTS_FAILURE();
315 }
317 operands->push_back(std::make_pair(result, DICT_OPERAND_INTEGER));
318 return true;
319 }
321 bool ParseDictDataReadNext(
322 ots::Buffer *table,
323 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) {
324 uint8_t op = 0;
325 if (!table->ReadU8(&op)) {
326 return OTS_FAILURE();
327 }
328 if (op <= 21) {
329 if (op == 12) {
330 return ParseDictDataEscapedOperator(table, operands);
331 }
332 operands->push_back(std::make_pair(
333 static_cast<uint32_t>(op), DICT_OPERATOR));
334 return true;
335 } else if (op <= 27 || op == 31 || op == 255) {
336 // reserved area.
337 return OTS_FAILURE();
338 }
340 return ParseDictDataNumber(table, op, operands);
341 }
343 bool ParsePrivateDictData(
344 const uint8_t *data,
345 size_t table_length, size_t offset, size_t dict_length,
346 DICT_DATA_TYPE type, ots::OpenTypeCFF *out_cff) {
347 ots::Buffer table(data + offset, dict_length);
348 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > operands;
350 // Since a Private DICT for FDArray might not have a Local Subr (e.g. Hiragino
351 // Kaku Gothic Std W8), we create an empty Local Subr here to match the size
352 // of FDArray the size of |local_subrs_per_font|.
353 if (type == DICT_DATA_FDARRAY) {
354 out_cff->local_subrs_per_font.push_back(new ots::CFFIndex);
355 }
357 while (table.offset() < dict_length) {
358 if (!ParseDictDataReadNext(&table, &operands)) {
359 return OTS_FAILURE();
360 }
361 if (operands.empty()) {
362 return OTS_FAILURE();
363 }
364 if (operands.size() > 48) {
365 // An operator may be preceded by up to a maximum of 48 operands.
366 return OTS_FAILURE();
367 }
368 if (operands.back().second != DICT_OPERATOR) {
369 continue;
370 }
372 // got operator
373 const uint32_t op = operands.back().first;
374 operands.pop_back();
376 switch (op) {
377 // array
378 case 6: // BlueValues
379 case 7: // OtherBlues
380 case 8: // FamilyBlues
381 case 9: // FamilyOtherBlues
382 case (12U << 8) + 12: // StemSnapH (delta)
383 case (12U << 8) + 13: // StemSnapV (delta)
384 if (operands.empty()) {
385 return OTS_FAILURE();
386 }
387 break;
389 // number
390 case 10: // StdHW
391 case 11: // StdVW
392 case 20: // defaultWidthX
393 case 21: // nominalWidthX
394 case (12U << 8) + 9: // BlueScale
395 case (12U << 8) + 10: // BlueShift
396 case (12U << 8) + 11: // BlueFuzz
397 case (12U << 8) + 17: // LanguageGroup
398 case (12U << 8) + 18: // ExpansionFactor
399 case (12U << 8) + 19: // initialRandomSeed
400 if (operands.size() != 1) {
401 return OTS_FAILURE();
402 }
403 break;
405 // Local Subrs INDEX, offset(self)
406 case 19: {
407 if (operands.size() != 1) {
408 return OTS_FAILURE();
409 }
410 if (operands.back().second != DICT_OPERAND_INTEGER) {
411 return OTS_FAILURE();
412 }
413 if (operands.back().first >= 1024 * 1024 * 1024) {
414 return OTS_FAILURE();
415 }
416 if (operands.back().first + offset >= table_length) {
417 return OTS_FAILURE();
418 }
419 // parse "16. Local Subrs INDEX"
420 ots::Buffer cff_table(data, table_length);
421 cff_table.set_offset(operands.back().first + offset);
422 ots::CFFIndex *local_subrs_index = NULL;
423 if (type == DICT_DATA_FDARRAY) {
424 if (out_cff->local_subrs_per_font.empty()) {
425 return OTS_FAILURE(); // not reached.
426 }
427 local_subrs_index = out_cff->local_subrs_per_font.back();
428 } else { // type == DICT_DATA_TOPLEVEL
429 if (out_cff->local_subrs) {
430 return OTS_FAILURE(); // two or more local_subrs?
431 }
432 local_subrs_index = new ots::CFFIndex;
433 out_cff->local_subrs = local_subrs_index;
434 }
435 if (!ParseIndex(&cff_table, local_subrs_index)) {
436 return OTS_FAILURE();
437 }
438 break;
439 }
441 // boolean
442 case (12U << 8) + 14: // ForceBold
443 if (operands.size() != 1) {
444 return OTS_FAILURE();
445 }
446 if (operands.back().second != DICT_OPERAND_INTEGER) {
447 return OTS_FAILURE();
448 }
449 if (operands.back().first >= 2) {
450 return OTS_FAILURE();
451 }
452 break;
454 default:
455 return OTS_FAILURE();
456 }
457 operands.clear();
458 }
460 return true;
461 }
463 bool ParseDictData(const uint8_t *data, size_t table_length,
464 const ots::CFFIndex &index, size_t sid_max,
465 DICT_DATA_TYPE type, ots::OpenTypeCFF *out_cff) {
466 for (unsigned i = 1; i < index.offsets.size(); ++i) {
467 if (type == DICT_DATA_TOPLEVEL) {
468 out_cff->char_strings_array.push_back(new ots::CFFIndex);
469 }
470 size_t dict_length = index.offsets[i] - index.offsets[i - 1];
471 ots::Buffer table(data + index.offsets[i - 1], dict_length);
473 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > operands;
475 FONT_FORMAT font_format = FORMAT_UNKNOWN;
476 bool have_ros = false;
477 size_t glyphs = 0;
478 size_t charset_offset = 0;
480 while (table.offset() < dict_length) {
481 if (!ParseDictDataReadNext(&table, &operands)) {
482 return OTS_FAILURE();
483 }
484 if (operands.empty()) {
485 return OTS_FAILURE();
486 }
487 if (operands.size() > 48) {
488 // An operator may be preceded by up to a maximum of 48 operands.
489 return OTS_FAILURE();
490 }
491 if (operands.back().second != DICT_OPERATOR) continue;
493 // got operator
494 const uint32_t op = operands.back().first;
495 operands.pop_back();
497 switch (op) {
498 // SID
499 case 0: // version
500 case 1: // Notice
501 case 2: // Copyright
502 case 3: // FullName
503 case 4: // FamilyName
504 case (12U << 8) + 0: // Copyright
505 case (12U << 8) + 21: // PostScript
506 case (12U << 8) + 22: // BaseFontName
507 case (12U << 8) + 38: // FontName
508 if (operands.size() != 1) {
509 return OTS_FAILURE();
510 }
511 if (!CheckSid(operands.back(), sid_max)) {
512 return OTS_FAILURE();
513 }
514 break;
516 // array
517 case 5: // FontBBox
518 case 14: // XUID
519 case (12U << 8) + 7: // FontMatrix
520 case (12U << 8) + 23: // BaseFontBlend (delta)
521 if (operands.empty()) {
522 return OTS_FAILURE();
523 }
524 break;
526 // number
527 case 13: // UniqueID
528 case (12U << 8) + 2: // ItalicAngle
529 case (12U << 8) + 3: // UnderlinePosition
530 case (12U << 8) + 4: // UnderlineThickness
531 case (12U << 8) + 5: // PaintType
532 case (12U << 8) + 8: // StrokeWidth
533 case (12U << 8) + 20: // SyntheticBase
534 if (operands.size() != 1) {
535 return OTS_FAILURE();
536 }
537 break;
538 case (12U << 8) + 31: // CIDFontVersion
539 case (12U << 8) + 32: // CIDFontRevision
540 case (12U << 8) + 33: // CIDFontType
541 case (12U << 8) + 34: // CIDCount
542 case (12U << 8) + 35: // UIDBase
543 if (operands.size() != 1) {
544 return OTS_FAILURE();
545 }
546 if (font_format != FORMAT_CID_KEYED) {
547 return OTS_FAILURE();
548 }
549 break;
550 case (12U << 8) + 6: // CharstringType
551 if (operands.size() != 1) {
552 return OTS_FAILURE();
553 }
554 if(operands.back().second != DICT_OPERAND_INTEGER) {
555 return OTS_FAILURE();
556 }
557 if (operands.back().first != 2) {
558 // We only support the "Type 2 Charstring Format."
559 // TODO(yusukes): Support Type 1 format? Is that still in use?
560 return OTS_FAILURE();
561 }
562 break;
564 // boolean
565 case (12U << 8) + 1: // isFixedPitch
566 if (operands.size() != 1) {
567 return OTS_FAILURE();
568 }
569 if (operands.back().second != DICT_OPERAND_INTEGER) {
570 return OTS_FAILURE();
571 }
572 if (operands.back().first >= 2) {
573 return OTS_FAILURE();
574 }
575 break;
577 // offset(0)
578 case 15: // charset
579 if (operands.size() != 1) {
580 return OTS_FAILURE();
581 }
582 if (operands.back().first <= 2) {
583 // predefined charset, ISOAdobe, Expert or ExpertSubset, is used.
584 break;
585 }
586 if (!CheckOffset(operands.back(), table_length)) {
587 return OTS_FAILURE();
588 }
589 if (charset_offset) {
590 return OTS_FAILURE(); // multiple charset tables?
591 }
592 charset_offset = operands.back().first;
593 break;
595 case 16: { // Encoding
596 if (operands.size() != 1) {
597 return OTS_FAILURE();
598 }
599 if (operands.back().first <= 1) {
600 break; // predefined encoding, "Standard" or "Expert", is used.
601 }
602 if (!CheckOffset(operands.back(), table_length)) {
603 return OTS_FAILURE();
604 }
606 // parse sub dictionary INDEX.
607 ots::Buffer cff_table(data, table_length);
608 cff_table.set_offset(operands.back().first);
609 uint8_t format = 0;
610 if (!cff_table.ReadU8(&format)) {
611 return OTS_FAILURE();
612 }
613 if (format & 0x80) {
614 // supplemental encoding is not supported at the moment.
615 return OTS_FAILURE();
616 }
617 // TODO(yusukes): support & parse supplemental encoding tables.
618 break;
619 }
621 case 17: { // CharStrings
622 if (type != DICT_DATA_TOPLEVEL) {
623 return OTS_FAILURE();
624 }
625 if (operands.size() != 1) {
626 return OTS_FAILURE();
627 }
628 if (!CheckOffset(operands.back(), table_length)) {
629 return OTS_FAILURE();
630 }
631 // parse "14. CharStrings INDEX"
632 ots::Buffer cff_table(data, table_length);
633 cff_table.set_offset(operands.back().first);
634 ots::CFFIndex *charstring_index = out_cff->char_strings_array.back();
635 if (!ParseIndex(&cff_table, charstring_index)) {
636 return OTS_FAILURE();
637 }
638 if (charstring_index->count < 2) {
639 return OTS_FAILURE();
640 }
641 if (glyphs) {
642 return OTS_FAILURE(); // multiple charstring tables?
643 }
644 glyphs = charstring_index->count;
645 break;
646 }
648 case (12U << 8) + 36: { // FDArray
649 if (type != DICT_DATA_TOPLEVEL) {
650 return OTS_FAILURE();
651 }
652 if (operands.size() != 1) {
653 return OTS_FAILURE();
654 }
655 if (!CheckOffset(operands.back(), table_length)) {
656 return OTS_FAILURE();
657 }
659 // parse sub dictionary INDEX.
660 ots::Buffer cff_table(data, table_length);
661 cff_table.set_offset(operands.back().first);
662 ots::CFFIndex sub_dict_index;
663 if (!ParseIndex(&cff_table, &sub_dict_index)) {
664 return OTS_FAILURE();
665 }
666 if (!ParseDictData(data, table_length,
667 sub_dict_index, sid_max, DICT_DATA_FDARRAY,
668 out_cff)) {
669 return OTS_FAILURE();
670 }
671 if (out_cff->font_dict_length != 0) {
672 return OTS_FAILURE(); // two or more FDArray found.
673 }
674 out_cff->font_dict_length = sub_dict_index.count;
675 break;
676 }
678 case (12U << 8) + 37: { // FDSelect
679 if (type != DICT_DATA_TOPLEVEL) {
680 return OTS_FAILURE();
681 }
682 if (operands.size() != 1) {
683 return OTS_FAILURE();
684 }
685 if (!CheckOffset(operands.back(), table_length)) {
686 return OTS_FAILURE();
687 }
689 // parse FDSelect data structure
690 ots::Buffer cff_table(data, table_length);
691 cff_table.set_offset(operands.back().first);
692 uint8_t format = 0;
693 if (!cff_table.ReadU8(&format)) {
694 return OTS_FAILURE();
695 }
696 if (format == 0) {
697 for (size_t j = 0; j < glyphs; ++j) {
698 uint8_t fd_index = 0;
699 if (!cff_table.ReadU8(&fd_index)) {
700 return OTS_FAILURE();
701 }
702 (out_cff->fd_select)[j] = fd_index;
703 }
704 } else if (format == 3) {
705 uint16_t n_ranges = 0;
706 if (!cff_table.ReadU16(&n_ranges)) {
707 return OTS_FAILURE();
708 }
709 if (n_ranges == 0) {
710 return OTS_FAILURE();
711 }
713 uint16_t last_gid = 0;
714 uint8_t fd_index = 0;
715 for (unsigned j = 0; j < n_ranges; ++j) {
716 uint16_t first = 0; // GID
717 if (!cff_table.ReadU16(&first)) {
718 return OTS_FAILURE();
719 }
721 // Sanity checks.
722 if ((j == 0) && (first != 0)) {
723 return OTS_FAILURE();
724 }
725 if ((j != 0) && (last_gid >= first)) {
726 return OTS_FAILURE(); // not increasing order.
727 }
729 // Copy the mapping to |out_cff->fd_select|.
730 if (j != 0) {
731 for (uint16_t k = last_gid; k < first; ++k) {
732 if (!out_cff->fd_select.insert(
733 std::make_pair(k, fd_index)).second) {
734 return OTS_FAILURE();
735 }
736 }
737 }
739 if (!cff_table.ReadU8(&fd_index)) {
740 return OTS_FAILURE();
741 }
742 last_gid = first;
743 // TODO(yusukes): check GID?
744 }
745 uint16_t sentinel = 0;
746 if (!cff_table.ReadU16(&sentinel)) {
747 return OTS_FAILURE();
748 }
749 if (last_gid >= sentinel) {
750 return OTS_FAILURE();
751 }
752 for (uint16_t k = last_gid; k < sentinel; ++k) {
753 if (!out_cff->fd_select.insert(
754 std::make_pair(k, fd_index)).second) {
755 return OTS_FAILURE();
756 }
757 }
758 } else {
759 // unknown format
760 return OTS_FAILURE();
761 }
762 break;
763 }
765 // Private DICT (2 * number)
766 case 18: {
767 if (operands.size() != 2) {
768 return OTS_FAILURE();
769 }
770 if (operands.back().second != DICT_OPERAND_INTEGER) {
771 return OTS_FAILURE();
772 }
773 const uint32_t private_offset = operands.back().first;
774 operands.pop_back();
775 if (operands.back().second != DICT_OPERAND_INTEGER) {
776 return OTS_FAILURE();
777 }
778 const uint32_t private_length = operands.back().first;
779 if (private_offset > table_length) {
780 return OTS_FAILURE();
781 }
782 if (private_length >= table_length) {
783 return OTS_FAILURE();
784 }
785 if (private_length + private_offset > table_length) {
786 return OTS_FAILURE();
787 }
788 // parse "15. Private DICT Data"
789 if (!ParsePrivateDictData(data, table_length,
790 private_offset, private_length,
791 type, out_cff)) {
792 return OTS_FAILURE();
793 }
794 break;
795 }
797 // ROS
798 case (12U << 8) + 30:
799 if (font_format != FORMAT_UNKNOWN) {
800 return OTS_FAILURE();
801 }
802 font_format = FORMAT_CID_KEYED;
803 if (operands.size() != 3) {
804 return OTS_FAILURE();
805 }
806 // check SIDs
807 operands.pop_back(); // ignore the first number.
808 if (!CheckSid(operands.back(), sid_max)) {
809 return OTS_FAILURE();
810 }
811 operands.pop_back();
812 if (!CheckSid(operands.back(), sid_max)) {
813 return OTS_FAILURE();
814 }
815 if (have_ros) {
816 return OTS_FAILURE(); // multiple ROS tables?
817 }
818 have_ros = true;
819 break;
821 default:
822 return OTS_FAILURE();
823 }
824 operands.clear();
826 if (font_format == FORMAT_UNKNOWN) {
827 font_format = FORMAT_OTHER;
828 }
829 }
831 // parse "13. Charsets"
832 if (charset_offset) {
833 ots::Buffer cff_table(data, table_length);
834 cff_table.set_offset(charset_offset);
835 uint8_t format = 0;
836 if (!cff_table.ReadU8(&format)) {
837 return OTS_FAILURE();
838 }
839 switch (format) {
840 case 0:
841 for (unsigned j = 1 /* .notdef is omitted */; j < glyphs; ++j) {
842 uint16_t sid = 0;
843 if (!cff_table.ReadU16(&sid)) {
844 return OTS_FAILURE();
845 }
846 if (!have_ros && (sid > sid_max)) {
847 return OTS_FAILURE();
848 }
849 // TODO(yusukes): check CIDs when have_ros is true.
850 }
851 break;
853 case 1:
854 case 2: {
855 uint32_t total = 1; // .notdef is omitted.
856 while (total < glyphs) {
857 uint16_t sid = 0;
858 if (!cff_table.ReadU16(&sid)) {
859 return OTS_FAILURE();
860 }
861 if (!have_ros && (sid > sid_max)) {
862 return OTS_FAILURE();
863 }
864 // TODO(yusukes): check CIDs when have_ros is true.
866 if (format == 1) {
867 uint8_t left = 0;
868 if (!cff_table.ReadU8(&left)) {
869 return OTS_FAILURE();
870 }
871 total += (left + 1);
872 } else {
873 uint16_t left = 0;
874 if (!cff_table.ReadU16(&left)) {
875 return OTS_FAILURE();
876 }
877 total += (left + 1);
878 }
879 }
880 break;
881 }
883 default:
884 return OTS_FAILURE();
885 }
886 }
887 }
888 return true;
889 }
891 } // namespace
893 namespace ots {
895 bool ots_cff_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
896 Buffer table(data, length);
898 file->cff = new OpenTypeCFF;
899 file->cff->data = data;
900 file->cff->length = length;
901 file->cff->font_dict_length = 0;
902 file->cff->local_subrs = NULL;
904 // parse "6. Header" in the Adobe Compact Font Format Specification
905 uint8_t major = 0;
906 uint8_t minor = 0;
907 uint8_t hdr_size = 0;
908 uint8_t off_size = 0;
909 if (!table.ReadU8(&major)) {
910 return OTS_FAILURE();
911 }
912 if (!table.ReadU8(&minor)) {
913 return OTS_FAILURE();
914 }
915 if (!table.ReadU8(&hdr_size)) {
916 return OTS_FAILURE();
917 }
918 if (!table.ReadU8(&off_size)) {
919 return OTS_FAILURE();
920 }
921 if ((off_size == 0) || (off_size > 4)) {
922 return OTS_FAILURE();
923 }
925 if ((major != 1) ||
926 (minor != 0) ||
927 (hdr_size != 4)) {
928 return OTS_FAILURE();
929 }
930 if (hdr_size >= length) {
931 return OTS_FAILURE();
932 }
934 // parse "7. Name INDEX"
935 table.set_offset(hdr_size);
936 CFFIndex name_index;
937 if (!ParseIndex(&table, &name_index)) {
938 return OTS_FAILURE();
939 }
940 if (!ParseNameData(&table, name_index, &(file->cff->name))) {
941 return OTS_FAILURE();
942 }
944 // parse "8. Top DICT INDEX"
945 table.set_offset(name_index.offset_to_next);
946 CFFIndex top_dict_index;
947 if (!ParseIndex(&table, &top_dict_index)) {
948 return OTS_FAILURE();
949 }
950 if (name_index.count != top_dict_index.count) {
951 return OTS_FAILURE();
952 }
954 // parse "10. String INDEX"
955 table.set_offset(top_dict_index.offset_to_next);
956 CFFIndex string_index;
957 if (!ParseIndex(&table, &string_index)) {
958 return OTS_FAILURE();
959 }
960 if (string_index.count >= 65000 - kNStdString) {
961 return OTS_FAILURE();
962 }
964 const size_t sid_max = string_index.count + kNStdString;
965 // string_index.count == 0 is allowed.
967 // parse "9. Top DICT Data"
968 if (!ParseDictData(data, length, top_dict_index,
969 sid_max, DICT_DATA_TOPLEVEL, file->cff)) {
970 return OTS_FAILURE();
971 }
973 // parse "16. Global Subrs INDEX"
974 table.set_offset(string_index.offset_to_next);
975 CFFIndex global_subrs_index;
976 if (!ParseIndex(&table, &global_subrs_index)) {
977 return OTS_FAILURE();
978 }
980 // Check if all fd_index in FDSelect are valid.
981 std::map<uint16_t, uint8_t>::const_iterator iter;
982 std::map<uint16_t, uint8_t>::const_iterator end = file->cff->fd_select.end();
983 for (iter = file->cff->fd_select.begin(); iter != end; ++iter) {
984 if (iter->second >= file->cff->font_dict_length) {
985 return OTS_FAILURE();
986 }
987 }
989 // Check if all charstrings (font hinting code for each glyph) are valid.
990 for (size_t i = 0; i < file->cff->char_strings_array.size(); ++i) {
991 if (!ValidateType2CharStringIndex(*(file->cff->char_strings_array.at(i)),
992 global_subrs_index,
993 file->cff->fd_select,
994 file->cff->local_subrs_per_font,
995 file->cff->local_subrs,
996 &table)) {
997 return OTS_FAILURE();
998 }
999 }
1001 return true;
1002 }
1004 bool ots_cff_should_serialise(OpenTypeFile *file) {
1005 return file->cff != NULL;
1006 }
1008 bool ots_cff_serialise(OTSStream *out, OpenTypeFile *file) {
1009 // TODO(yusukes): would be better to transcode the data,
1010 // rather than simple memcpy.
1011 if (!out->Write(file->cff->data, file->cff->length)) {
1012 return OTS_FAILURE();
1013 }
1014 return true;
1015 }
1017 void ots_cff_free(OpenTypeFile *file) {
1018 if (file->cff) {
1019 for (size_t i = 0; i < file->cff->char_strings_array.size(); ++i) {
1020 delete (file->cff->char_strings_array)[i];
1021 }
1022 for (size_t i = 0; i < file->cff->local_subrs_per_font.size(); ++i) {
1023 delete (file->cff->local_subrs_per_font)[i];
1024 }
1025 delete file->cff->local_subrs;
1026 delete file->cff;
1027 }
1028 }
1030 } // namespace ots