1 // Copyright (c) 2009-2017 The OTS 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 "glyf.h"
6 
7 #include <algorithm>
8 #include <limits>
9 
10 #include "head.h"
11 #include "loca.h"
12 #include "maxp.h"
13 
14 // glyf - Glyph Data
15 // http://www.microsoft.com/typography/otspec/glyf.htm
16 
17 namespace ots {
18 
ParseFlagsForSimpleGlyph(Buffer & glyph,uint32_t num_flags,uint32_t * flag_index,uint32_t * coordinates_length)19 bool OpenTypeGLYF::ParseFlagsForSimpleGlyph(Buffer &glyph,
20                                             uint32_t num_flags,
21                                             uint32_t *flag_index,
22                                             uint32_t *coordinates_length) {
23   uint8_t flag = 0;
24   if (!glyph.ReadU8(&flag)) {
25     return Error("Can't read flag");
26   }
27 
28   uint32_t delta = 0;
29   if (flag & (1u << 1)) {  // x-Short
30     ++delta;
31   } else if (!(flag & (1u << 4))) {
32     delta += 2;
33   }
34 
35   if (flag & (1u << 2)) {  // y-Short
36     ++delta;
37   } else if (!(flag & (1u << 5))) {
38     delta += 2;
39   }
40 
41   /* MS and Apple specs say this bit is reserved and must be set to zero, but
42    * Apple spec then contradicts itself and says it should be set on the first
43    * contour flag for simple glyphs with overlapping contours:
44    * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6AATIntro.html
45    * (“Overlapping contours” section) */
46   if (flag & (1u << 6) && *flag_index != 0) {
47     return Error("Bad glyph flag (%d), "
48                  "bit 6 must be set to zero for flag %d", flag, *flag_index);
49   }
50 
51   if (flag & (1u << 3)) {  // repeat
52     if (*flag_index + 1 >= num_flags) {
53       return Error("Count too high (%d + 1 >= %d)", *flag_index, num_flags);
54     }
55     uint8_t repeat = 0;
56     if (!glyph.ReadU8(&repeat)) {
57       return Error("Can't read repeat value");
58     }
59     if (repeat == 0) {
60       return Error("Zero repeat");
61     }
62     delta += (delta * repeat);
63 
64     *flag_index += repeat;
65     if (*flag_index >= num_flags) {
66       return Error("Count too high (%d >= %d)", *flag_index, num_flags);
67     }
68   }
69 
70   if (flag & (1u << 7)) {  // reserved flag
71     return Error("Bad glyph flag (%d), reserved bit 7 must be set to zero", flag);
72   }
73 
74   *coordinates_length += delta;
75   if (glyph.length() < *coordinates_length) {
76     return Error("Glyph coordinates length bigger than glyph length (%d > %d)",
77                  *coordinates_length, glyph.length());
78   }
79 
80   return true;
81 }
82 
ParseSimpleGlyph(Buffer & glyph,int16_t num_contours)83 bool OpenTypeGLYF::ParseSimpleGlyph(Buffer &glyph,
84                                     int16_t num_contours) {
85   // read the end-points array
86   uint16_t num_flags = 0;
87   for (int i = 0; i < num_contours; ++i) {
88     uint16_t tmp_index = 0;
89     if (!glyph.ReadU16(&tmp_index)) {
90       return Error("Can't read contour index %d", i);
91     }
92     if (tmp_index == 0xffffu) {
93       return Error("Bad contour index %d", i);
94     }
95     // check if the indices are monotonically increasing
96     if (i && (tmp_index + 1 <= num_flags)) {
97       return Error("Decreasing contour index %d + 1 <= %d", tmp_index, num_flags);
98     }
99     num_flags = tmp_index + 1;
100   }
101 
102   if (this->maxp->version_1 &&
103       num_flags > this->maxp->max_points) {
104     Warning("Number of contour points exceeds maxp maxPoints, adjusting limit.");
105     this->maxp->max_points = num_flags;
106   }
107 
108   uint16_t bytecode_length = 0;
109   if (!glyph.ReadU16(&bytecode_length)) {
110     return Error("Can't read bytecode length");
111   }
112 
113   if (this->maxp->version_1 &&
114       this->maxp->max_size_glyf_instructions < bytecode_length) {
115     this->maxp->max_size_glyf_instructions = bytecode_length;
116     Warning("Bytecode length is bigger than maxp.maxSizeOfInstructions %d: %d",
117             this->maxp->max_size_glyf_instructions, bytecode_length);
118   }
119 
120   if (!glyph.Skip(bytecode_length)) {
121     return Error("Can't read bytecode of length %d", bytecode_length);
122   }
123 
124   uint32_t coordinates_length = 0;
125   for (uint32_t i = 0; i < num_flags; ++i) {
126     if (!ParseFlagsForSimpleGlyph(glyph, num_flags, &i, &coordinates_length)) {
127       return Error("Failed to parse glyph flags %d", i);
128     }
129   }
130 
131   if (!glyph.Skip(coordinates_length)) {
132     return Error("Glyph too short %d", glyph.length());
133   }
134 
135   if (glyph.remaining() > 3) {
136     // We allow 0-3 bytes difference since gly_length is 4-bytes aligned,
137     // zero-padded length.
138     Warning("Extra bytes at end of the glyph: %d", glyph.remaining());
139   }
140 
141   this->iov.push_back(std::make_pair(glyph.buffer(), glyph.offset()));
142 
143   return true;
144 }
145 
146 #define ARG_1_AND_2_ARE_WORDS    (1u << 0)
147 #define WE_HAVE_A_SCALE          (1u << 3)
148 #define MORE_COMPONENTS          (1u << 5)
149 #define WE_HAVE_AN_X_AND_Y_SCALE (1u << 6)
150 #define WE_HAVE_A_TWO_BY_TWO     (1u << 7)
151 #define WE_HAVE_INSTRUCTIONS     (1u << 8)
152 
ParseCompositeGlyph(Buffer & glyph,ComponentPointCount * component_point_count)153 bool OpenTypeGLYF::ParseCompositeGlyph(
154     Buffer &glyph,
155     ComponentPointCount* component_point_count) {
156   uint16_t flags = 0;
157   uint16_t gid = 0;
158   do {
159     if (!glyph.ReadU16(&flags) || !glyph.ReadU16(&gid)) {
160       return Error("Can't read composite glyph flags or glyphIndex");
161     }
162 
163     if (gid >= this->maxp->num_glyphs) {
164       return Error("Invalid glyph id used in composite glyph: %d", gid);
165     }
166 
167     if (flags & ARG_1_AND_2_ARE_WORDS) {
168       int16_t argument1;
169       int16_t argument2;
170       if (!glyph.ReadS16(&argument1) || !glyph.ReadS16(&argument2)) {
171         return Error("Can't read argument1 or argument2");
172       }
173     } else {
174       uint8_t argument1;
175       uint8_t argument2;
176       if (!glyph.ReadU8(&argument1) || !glyph.ReadU8(&argument2)) {
177         return Error("Can't read argument1 or argument2");
178       }
179     }
180 
181     if (flags & WE_HAVE_A_SCALE) {
182       int16_t scale;
183       if (!glyph.ReadS16(&scale)) {
184         return Error("Can't read scale");
185       }
186     } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
187       int16_t xscale;
188       int16_t yscale;
189       if (!glyph.ReadS16(&xscale) || !glyph.ReadS16(&yscale)) {
190         return Error("Can't read xscale or yscale");
191       }
192     } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
193       int16_t xscale;
194       int16_t scale01;
195       int16_t scale10;
196       int16_t yscale;
197       if (!glyph.ReadS16(&xscale) ||
198           !glyph.ReadS16(&scale01) ||
199           !glyph.ReadS16(&scale10) ||
200           !glyph.ReadS16(&yscale)) {
201         return Error("Can't read transform");
202       }
203     }
204 
205     // Push inital components on stack at level 1
206     // to traverse them in parent function.
207     component_point_count->gid_stack.push_back({gid, 1});
208   } while (flags & MORE_COMPONENTS);
209 
210   if (flags & WE_HAVE_INSTRUCTIONS) {
211     uint16_t bytecode_length;
212     if (!glyph.ReadU16(&bytecode_length)) {
213       return Error("Can't read instructions size");
214     }
215 
216     if (this->maxp->version_1 &&
217         this->maxp->max_size_glyf_instructions < bytecode_length) {
218       this->maxp->max_size_glyf_instructions = bytecode_length;
219       Warning("Bytecode length is bigger than maxp.maxSizeOfInstructions "
220               "%d: %d",
221               this->maxp->max_size_glyf_instructions, bytecode_length);
222     }
223 
224     if (!glyph.Skip(bytecode_length)) {
225       return Error("Can't read bytecode of length %d", bytecode_length);
226     }
227   }
228 
229   this->iov.push_back(std::make_pair(glyph.buffer(), glyph.offset()));
230 
231   return true;
232 }
233 
Parse(const uint8_t * data,size_t length)234 bool OpenTypeGLYF::Parse(const uint8_t *data, size_t length) {
235   OpenTypeMAXP *maxp = static_cast<OpenTypeMAXP*>(
236       GetFont()->GetTypedTable(OTS_TAG_MAXP));
237   OpenTypeLOCA *loca = static_cast<OpenTypeLOCA*>(
238       GetFont()->GetTypedTable(OTS_TAG_LOCA));
239   OpenTypeHEAD *head = static_cast<OpenTypeHEAD*>(
240       GetFont()->GetTypedTable(OTS_TAG_HEAD));
241   if (!maxp || !loca || !head) {
242     return Error("Missing maxp or loca or head table needed by glyf table");
243   }
244 
245   this->maxp = maxp;
246 
247   const unsigned num_glyphs = maxp->num_glyphs;
248   std::vector<uint32_t> &offsets = loca->offsets;
249 
250   if (offsets.size() != num_glyphs + 1) {
251     return Error("Invalide glyph offsets size %ld != %d", offsets.size(), num_glyphs + 1);
252   }
253 
254   std::vector<uint32_t> resulting_offsets(num_glyphs + 1);
255   uint32_t current_offset = 0;
256 
257   for (unsigned i = 0; i < num_glyphs; ++i) {
258 
259     Buffer glyph(GetGlyphBufferSection(data, length, offsets, i));
260     if (!glyph.buffer())
261       return false;
262 
263     if (!glyph.length()) {
264       resulting_offsets[i] = current_offset;
265       continue;
266     }
267 
268     int16_t num_contours, xmin, ymin, xmax, ymax;
269     if (!glyph.ReadS16(&num_contours) ||
270         !glyph.ReadS16(&xmin) ||
271         !glyph.ReadS16(&ymin) ||
272         !glyph.ReadS16(&xmax) ||
273         !glyph.ReadS16(&ymax)) {
274       return Error("Can't read glyph %d header", i);
275     }
276 
277     if (num_contours <= -2) {
278       // -2, -3, -4, ... are reserved for future use.
279       return Error("Bad number of contours %d in glyph %d", num_contours, i);
280     }
281 
282     // workaround for fonts in http://www.princexml.com/fonts/
283     if ((xmin == 32767) &&
284         (xmax == -32767) &&
285         (ymin == 32767) &&
286         (ymax == -32767)) {
287       Warning("bad xmin/xmax/ymin/ymax values");
288       xmin = xmax = ymin = ymax = 0;
289     }
290 
291     if (xmin > xmax || ymin > ymax) {
292       return Error("Bad bounding box values bl=(%d, %d), tr=(%d, %d) in glyph %d", xmin, ymin, xmax, ymax, i);
293     }
294 
295     if (num_contours == 0) {
296       // This is an empty glyph and shouldn’t have any glyph data, but if it
297       // does we will simply ignore it.
298       glyph.set_offset(0);
299     } else if (num_contours > 0) {
300       if (!ParseSimpleGlyph(glyph, num_contours)) {
301         return Error("Failed to parse glyph %d", i);
302       }
303     } else {
304 
305       ComponentPointCount component_point_count;
306       if (!ParseCompositeGlyph(glyph, &component_point_count)) {
307         return Error("Failed to parse glyph %d", i);
308       }
309 
310       // Check maxComponentDepth and validate maxComponentPoints.
311       // ParseCompositeGlyph placed the first set of component glyphs on the
312       // component_point_count.gid_stack, which we start to process below. If a
313       // nested glyph is in turn a component glyph, additional glyphs are placed
314       // on the stack.
315       while (component_point_count.gid_stack.size()) {
316         GidAtLevel stack_top_gid = component_point_count.gid_stack.back();
317         component_point_count.gid_stack.pop_back();
318 
319         Buffer points_count_glyph(GetGlyphBufferSection(
320             data,
321             length,
322             offsets,
323             stack_top_gid.gid));
324 
325         if (!points_count_glyph.buffer())
326           return false;
327 
328         if (!points_count_glyph.length())
329           continue;
330 
331         if (!TraverseComponentsCountingPoints(points_count_glyph,
332                                               i,
333                                               stack_top_gid.level,
334                                               &component_point_count)) {
335           return Error("Error validating component points and depth.");
336         }
337 
338         if (component_point_count.accumulated_component_points >
339             std::numeric_limits<uint16_t>::max()) {
340           return Error("Illegal composite points value "
341                        "exceeding 0xFFFF for base glyph %d.", i);
342         } else if (this->maxp->version_1 &&
343                    component_point_count.accumulated_component_points >
344                    this->maxp->max_c_points) {
345           Warning("Number of composite points in glyph %d exceeds "
346                   "maxp maxCompositePoints: %d vs %d, adjusting limit.",
347                   i,
348                   component_point_count.accumulated_component_points,
349                   this->maxp->max_c_points
350                   );
351           this->maxp->max_c_points =
352               component_point_count.accumulated_component_points;
353         }
354       }
355     }
356 
357     size_t new_size = glyph.offset();
358     resulting_offsets[i] = current_offset;
359     // glyphs must be four byte aligned
360     // TODO(yusukes): investigate whether this padding is really necessary.
361     //                Which part of the spec requires this?
362     const unsigned padding = (4 - (new_size & 3)) % 4;
363     if (padding) {
364       this->iov.push_back(std::make_pair(
365           reinterpret_cast<const uint8_t*>("\x00\x00\x00\x00"),
366           static_cast<size_t>(padding)));
367       new_size += padding;
368     }
369     current_offset += new_size;
370   }
371   resulting_offsets[num_glyphs] = current_offset;
372 
373   const uint16_t max16 = std::numeric_limits<uint16_t>::max();
374   if ((*std::max_element(resulting_offsets.begin(),
375                          resulting_offsets.end()) >= (max16 * 2u)) &&
376       (head->index_to_loc_format != 1)) {
377     head->index_to_loc_format = 1;
378   }
379 
380   loca->offsets = resulting_offsets;
381 
382   if (this->iov.empty()) {
383     // As a special case when all glyph in the font are empty, add a zero byte
384     // to the table, so that we don’t reject it down the way, and to make the
385     // table work on Windows as well.
386     // See https://github.com/khaledhosny/ots/issues/52
387     static const uint8_t kZero = 0;
388     this->iov.push_back(std::make_pair(&kZero, 1));
389   }
390 
391   return true;
392 }
393 
TraverseComponentsCountingPoints(Buffer & glyph,uint16_t base_glyph_id,uint32_t level,ComponentPointCount * component_point_count)394 bool OpenTypeGLYF::TraverseComponentsCountingPoints(
395     Buffer &glyph,
396     uint16_t base_glyph_id,
397     uint32_t level,
398     ComponentPointCount* component_point_count) {
399 
400   int16_t num_contours;
401   if (!glyph.ReadS16(&num_contours) ||
402       !glyph.Skip(8)) {
403     return Error("Can't read glyph header.");
404   }
405 
406   if (num_contours <= -2) {
407     return Error("Bad number of contours %d in glyph.", num_contours);
408   }
409 
410   if (num_contours == 0)
411     return true;
412 
413   // FontTools counts a component level for each traversed recursion. We start
414   // counting at level 0. If we reach a level that's deeper than
415   // maxComponentDepth, we expand maxComponentDepth unless it's larger than
416   // the maximum possible depth.
417   if (level > std::numeric_limits<uint16_t>::max()) {
418     return Error("Illegal component depth exceeding 0xFFFF in base glyph id %d.",
419                  base_glyph_id);
420   } else if (this->maxp->version_1 &&
421              level > this->maxp->max_c_depth) {
422     this->maxp->max_c_depth = level;
423     Warning("Component depth exceeds maxp maxComponentDepth "
424             "in glyph %d, adjust limit to %d.",
425             base_glyph_id, level);
426   }
427 
428   if (num_contours > 0) {
429     uint16_t num_points = 0;
430     for (int i = 0; i < num_contours; ++i) {
431       // Simple glyph, add contour points.
432       uint16_t tmp_index = 0;
433       if (!glyph.ReadU16(&tmp_index)) {
434         return Error("Can't read contour index %d", i);
435       }
436       num_points = tmp_index + 1;
437     }
438 
439     component_point_count->accumulated_component_points += num_points;
440     return true;
441   } else  {
442     assert(num_contours == -1);
443 
444     // Composite glyph, add gid's to stack.
445     uint16_t flags = 0;
446     uint16_t gid = 0;
447     do {
448       if (!glyph.ReadU16(&flags) || !glyph.ReadU16(&gid)) {
449         return Error("Can't read composite glyph flags or glyphIndex");
450       }
451 
452       size_t skip_bytes = 0;
453       skip_bytes += flags & ARG_1_AND_2_ARE_WORDS ? 4 : 2;
454 
455       if (flags & WE_HAVE_A_SCALE) {
456         skip_bytes += 2;
457       } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
458         skip_bytes += 4;
459       } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
460         skip_bytes += 8;
461       }
462 
463       if (!glyph.Skip(skip_bytes)) {
464         return Error("Failed to parse component glyph.");
465       }
466 
467       if (gid >= this->maxp->num_glyphs) {
468         return Error("Invalid glyph id used in composite glyph: %d", gid);
469       }
470 
471       component_point_count->gid_stack.push_back({gid, level + 1u});
472     } while (flags & MORE_COMPONENTS);
473     return true;
474   }
475 }
476 
GetGlyphBufferSection(const uint8_t * data,size_t length,const std::vector<uint32_t> & loca_offsets,unsigned glyph_id)477 Buffer OpenTypeGLYF::GetGlyphBufferSection(
478     const uint8_t *data,
479     size_t length,
480     const std::vector<uint32_t>& loca_offsets,
481     unsigned glyph_id) {
482 
483   Buffer null_buffer(nullptr, 0);
484 
485   const unsigned gly_offset = loca_offsets[glyph_id];
486   // The LOCA parser checks that these values are monotonic
487   const unsigned gly_length = loca_offsets[glyph_id + 1] - loca_offsets[glyph_id];
488   if (!gly_length) {
489     // this glyph has no outline (e.g. the space character)
490     return Buffer(data + gly_offset, 0);
491   }
492 
493   if (gly_offset >= length) {
494     Error("Glyph %d offset %d too high %ld", glyph_id, gly_offset, length);
495     return null_buffer;
496   }
497   // Since these are unsigned types, the compiler is not allowed to assume
498   // that they never overflow.
499   if (gly_offset + gly_length < gly_offset) {
500     Error("Glyph %d length (%d < 0)!", glyph_id, gly_length);
501     return null_buffer;
502   }
503   if (gly_offset + gly_length > length) {
504     Error("Glyph %d length %d too high", glyph_id, gly_length);
505     return null_buffer;
506   }
507 
508   return Buffer(data + gly_offset, gly_length);
509 }
510 
Serialize(OTSStream * out)511 bool OpenTypeGLYF::Serialize(OTSStream *out) {
512   for (unsigned i = 0; i < this->iov.size(); ++i) {
513     if (!out->Write(this->iov[i].first, this->iov[i].second)) {
514       return Error("Falied to write glyph %d", i);
515     }
516   }
517 
518   return true;
519 }
520 
521 }  // namespace ots
522