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