Home | History | Annotate | Download | only in src
      1 // Copyright (c) 2013 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 // This is the implementation of decompression of the proposed WOFF Ultra
      6 // Condensed file format.
      7 
      8 #include <cassert>
      9 #include <cstdlib>
     10 #include <vector>
     11 
     12 #include <zlib.h>
     13 
     14 #include "third_party/lzma_sdk/LzmaLib.h"
     15 
     16 #include "opentype-sanitiser.h"
     17 #include "ots-memory-stream.h"
     18 #include "ots.h"
     19 #include "woff2.h"
     20 
     21 namespace {
     22 
     23 // simple glyph flags
     24 const int kGlyfOnCurve = 1 << 0;
     25 const int kGlyfXShort = 1 << 1;
     26 const int kGlyfYShort = 1 << 2;
     27 const int kGlyfRepeat = 1 << 3;
     28 const int kGlyfThisXIsSame = 1 << 4;
     29 const int kGlyfThisYIsSame = 1 << 5;
     30 
     31 // composite glyph flags
     32 const int FLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0;
     33 const int FLAG_ARGS_ARE_XY_VALUES = 1 << 1;
     34 const int FLAG_ROUND_XY_TO_GRID = 1 << 2;
     35 const int FLAG_WE_HAVE_A_SCALE = 1 << 3;
     36 const int FLAG_RESERVED = 1 << 4;
     37 const int FLAG_MORE_COMPONENTS = 1 << 5;
     38 const int FLAG_WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6;
     39 const int FLAG_WE_HAVE_A_TWO_BY_TWO = 1 << 7;
     40 const int FLAG_WE_HAVE_INSTRUCTIONS = 1 << 8;
     41 const int FLAG_USE_MY_METRICS = 1 << 9;
     42 const int FLAG_OVERLAP_COMPOUND = 1 << 10;
     43 const int FLAG_SCALED_COMPONENT_OFFSET = 1 << 11;
     44 const int FLAG_UNSCALED_COMPONENT_OFFSET = 1 << 12;
     45 
     46 const size_t kSfntHeaderSize = 12;
     47 const size_t kSfntEntrySize = 16;
     48 const size_t kCheckSumAdjustmentOffset = 8;
     49 
     50 const size_t kEndPtsOfContoursOffset = 10;
     51 const size_t kCompositeGlyphBegin = 10;
     52 
     53 // Note that the byte order is big-endian, not the same as ots.cc
     54 #define TAG(a, b, c, d) ((a << 24) | (b << 16) | (c << 8) | d)
     55 
     56 const unsigned int kWoff2FlagsContinueStream = 1 << 4;
     57 const unsigned int kWoff2FlagsTransform = 1 << 5;
     58 
     59 const size_t kWoff2HeaderSize = 44;
     60 const size_t kWoff2EntrySize = 20;
     61 
     62 const size_t kLzmaHeaderSize = 13;
     63 
     64 // Compression type values common to both short and long formats
     65 const uint32_t kCompressionTypeMask = 0xf;
     66 const uint32_t kCompressionTypeNone = 0;
     67 const uint32_t kCompressionTypeGzip = 1;
     68 const uint32_t kCompressionTypeLzma = 2;
     69 
     70 // This is a special value for the short format only, as described in
     71 // "Design for compressed header format" in draft doc.
     72 const uint32_t kShortFlagsContinue = 3;
     73 
     74 const uint32_t kKnownTags[] = {
     75   TAG('c', 'm', 'a', 'p'),  // 0
     76   TAG('h', 'e', 'a', 'd'),  // 1
     77   TAG('h', 'h', 'e', 'a'),  // 2
     78   TAG('h', 'm', 't', 'x'),  // 3
     79   TAG('m', 'a', 'x', 'p'),  // 4
     80   TAG('n', 'a', 'm', 'e'),  // 5
     81   TAG('O', 'S', '/', '2'),  // 6
     82   TAG('p', 'o', 's', 't'),  // 7
     83   TAG('c', 'v', 't', ' '),  // 8
     84   TAG('f', 'p', 'g', 'm'),  // 9
     85   TAG('g', 'l', 'y', 'f'),  // 10
     86   TAG('l', 'o', 'c', 'a'),  // 11
     87   TAG('p', 'r', 'e', 'p'),  // 12
     88   TAG('C', 'F', 'F', ' '),  // 13
     89   TAG('V', 'O', 'R', 'G'),  // 14
     90   TAG('E', 'B', 'D', 'T'),  // 15
     91   TAG('E', 'B', 'L', 'C'),  // 16
     92   TAG('g', 'a', 's', 'p'),  // 17
     93   TAG('h', 'd', 'm', 'x'),  // 18
     94   TAG('k', 'e', 'r', 'n'),  // 19
     95   TAG('L', 'T', 'S', 'H'),  // 20
     96   TAG('P', 'C', 'L', 'T'),  // 21
     97   TAG('V', 'D', 'M', 'X'),  // 22
     98   TAG('v', 'h', 'e', 'a'),  // 23
     99   TAG('v', 'm', 't', 'x'),  // 24
    100   TAG('B', 'A', 'S', 'E'),  // 25
    101   TAG('G', 'D', 'E', 'F'),  // 26
    102   TAG('G', 'P', 'O', 'S'),  // 27
    103   TAG('G', 'S', 'U', 'B'),  // 28
    104 };
    105 
    106 struct Point {
    107   int x;
    108   int y;
    109   bool on_curve;
    110 };
    111 
    112 struct Table {
    113   uint32_t tag;
    114   uint32_t flags;
    115   uint32_t src_offset;
    116   uint32_t src_length;
    117 
    118   uint32_t transform_length;
    119 
    120   uint32_t dst_offset;
    121   uint32_t dst_length;
    122 
    123   Table()
    124       : tag(0),
    125         flags(0),
    126         src_offset(0),
    127         src_length(0),
    128         transform_length(0),
    129         dst_offset(0),
    130         dst_length(0) {}
    131 };
    132 
    133 // Based on section 6.1.1 of MicroType Express draft spec
    134 bool Read255UShort(ots::Buffer* buf, unsigned int* value) {
    135   static const int kWordCode = 253;
    136   static const int kOneMoreByteCode2 = 254;
    137   static const int kOneMoreByteCode1 = 255;
    138   static const int kLowestUCode = 253;
    139   uint8_t code = 0;
    140   if (!buf->ReadU8(&code)) {
    141     return OTS_FAILURE();
    142   }
    143   if (code == kWordCode) {
    144     uint16_t result = 0;
    145     if (!buf->ReadU16(&result)) {
    146       return OTS_FAILURE();
    147     }
    148     *value = result;
    149     return true;
    150   } else if (code == kOneMoreByteCode1) {
    151     uint8_t result = 0;
    152     if (!buf->ReadU8(&result)) {
    153       return OTS_FAILURE();
    154     }
    155     *value = result + kLowestUCode;
    156     return true;
    157   } else if (code == kOneMoreByteCode2) {
    158     uint8_t result = 0;
    159     if (!buf->ReadU8(&result)) {
    160       return OTS_FAILURE();
    161     }
    162     *value = result + kLowestUCode * 2;
    163     return true;
    164   } else {
    165     *value = code;
    166     return true;
    167   }
    168 }
    169 
    170 bool ReadBase128(ots::Buffer* buf, uint32_t* value) {
    171   uint32_t result = 0;
    172   for (size_t i = 0; i < 5; ++i) {
    173     uint8_t code = 0;
    174     if (!buf->ReadU8(&code)) {
    175       return OTS_FAILURE();
    176     }
    177     // If any of the top seven bits are set then we're about to overflow.
    178     if (result & 0xe0000000U) {
    179       return OTS_FAILURE();
    180     }
    181     result = (result << 7) | (code & 0x7f);
    182     if ((code & 0x80) == 0) {
    183       *value = result;
    184       return true;
    185     }
    186   }
    187   // Make sure not to exceed the size bound
    188   return OTS_FAILURE();
    189 }
    190 
    191 // Caller must ensure that buffer overrun won't happen.
    192 // TODO(ksakamaoto): Consider creating 'writer' version of the Buffer class
    193 // and use it across the code.
    194 size_t StoreU32(uint8_t* dst, size_t offset, uint32_t x) {
    195   dst[offset] = x >> 24;
    196   dst[offset + 1] = x >> 16;
    197   dst[offset + 2] = x >> 8;
    198   dst[offset + 3] = x;
    199   return offset + 4;
    200 }
    201 
    202 size_t Store16(uint8_t* dst, size_t offset, int x) {
    203   dst[offset] = x >> 8;
    204   dst[offset + 1] = x;
    205   return offset + 2;
    206 }
    207 
    208 int WithSign(int flag, int baseval) {
    209   assert(0 <= baseval && baseval < 65536);
    210   return (flag & 1) ? baseval : -baseval;
    211 }
    212 
    213 bool TripletDecode(const uint8_t* flags_in, const uint8_t* in, size_t in_size,
    214     unsigned int n_points, std::vector<Point>* result,
    215     size_t* in_bytes_consumed) {
    216   int x = 0;
    217   int y = 0;
    218 
    219   // Early return if |in| buffer is too small. Each point consumes 1-4 bytes.
    220   if (n_points > in_size) {
    221     return OTS_FAILURE();
    222   }
    223   unsigned int triplet_index = 0;
    224 
    225   for (unsigned int i = 0; i < n_points; ++i) {
    226     uint8_t flag = flags_in[i];
    227     bool on_curve = !(flag >> 7);
    228     flag &= 0x7f;
    229     unsigned int n_data_bytes;
    230     if (flag < 84) {
    231       n_data_bytes = 1;
    232     } else if (flag < 120) {
    233       n_data_bytes = 2;
    234     } else if (flag < 124) {
    235       n_data_bytes = 3;
    236     } else {
    237       n_data_bytes = 4;
    238     }
    239     if (triplet_index + n_data_bytes > in_size ||
    240         triplet_index + n_data_bytes < triplet_index) {
    241       return OTS_FAILURE();
    242     }
    243     int dx, dy;
    244     if (flag < 10) {
    245       dx = 0;
    246       dy = WithSign(flag, ((flag & 14) << 7) + in[triplet_index]);
    247     } else if (flag < 20) {
    248       dx = WithSign(flag, (((flag - 10) & 14) << 7) + in[triplet_index]);
    249       dy = 0;
    250     } else if (flag < 84) {
    251       int b0 = flag - 20;
    252       int b1 = in[triplet_index];
    253       dx = WithSign(flag, 1 + (b0 & 0x30) + (b1 >> 4));
    254       dy = WithSign(flag >> 1, 1 + ((b0 & 0x0c) << 2) + (b1 & 0x0f));
    255     } else if (flag < 120) {
    256       int b0 = flag - 84;
    257       dx = WithSign(flag, 1 + ((b0 / 12) << 8) + in[triplet_index]);
    258       dy = WithSign(flag >> 1,
    259                     1 + (((b0 % 12) >> 2) << 8) + in[triplet_index + 1]);
    260     } else if (flag < 124) {
    261       int b2 = in[triplet_index + 1];
    262       dx = WithSign(flag, (in[triplet_index] << 4) + (b2 >> 4));
    263       dy = WithSign(flag >> 1, ((b2 & 0x0f) << 8) + in[triplet_index + 2]);
    264     } else {
    265       dx = WithSign(flag, (in[triplet_index] << 8) + in[triplet_index + 1]);
    266       dy = WithSign(flag >> 1,
    267           (in[triplet_index + 2] << 8) + in[triplet_index + 3]);
    268     }
    269     triplet_index += n_data_bytes;
    270     // Possible overflow but coordinate values are not security sensitive
    271     x += dx;
    272     y += dy;
    273     result->push_back(Point());
    274     Point& back = result->back();
    275     back.x = x;
    276     back.y = y;
    277     back.on_curve = on_curve;
    278   }
    279   *in_bytes_consumed = triplet_index;
    280   return true;
    281 }
    282 
    283 // This function stores just the point data. On entry, dst points to the
    284 // beginning of a simple glyph. Returns true on success.
    285 bool StorePoints(const std::vector<Point>& points,
    286     unsigned int n_contours, unsigned int instruction_length,
    287     uint8_t* dst, size_t dst_size, size_t* glyph_size) {
    288   // I believe that n_contours < 65536, in which case this is safe. However, a
    289   // comment and/or an assert would be good.
    290   unsigned int flag_offset = kEndPtsOfContoursOffset + 2 * n_contours + 2 +
    291     instruction_length;
    292   int last_flag = -1;
    293   int repeat_count = 0;
    294   int last_x = 0;
    295   int last_y = 0;
    296   unsigned int x_bytes = 0;
    297   unsigned int y_bytes = 0;
    298 
    299   for (size_t i = 0; i < points.size(); ++i) {
    300     const Point& point = points.at(i);
    301     int flag = point.on_curve ? kGlyfOnCurve : 0;
    302     int dx = point.x - last_x;
    303     int dy = point.y - last_y;
    304     if (dx == 0) {
    305       flag |= kGlyfThisXIsSame;
    306     } else if (dx > -256 && dx < 256) {
    307       flag |= kGlyfXShort | (dx > 0 ? kGlyfThisXIsSame : 0);
    308       x_bytes += 1;
    309     } else {
    310       x_bytes += 2;
    311     }
    312     if (dy == 0) {
    313       flag |= kGlyfThisYIsSame;
    314     } else if (dy > -256 && dy < 256) {
    315       flag |= kGlyfYShort | (dy > 0 ? kGlyfThisYIsSame : 0);
    316       y_bytes += 1;
    317     } else {
    318       y_bytes += 2;
    319     }
    320 
    321     if (flag == last_flag && repeat_count != 255) {
    322       dst[flag_offset - 1] |= kGlyfRepeat;
    323       repeat_count++;
    324     } else {
    325       if (repeat_count != 0) {
    326         if (flag_offset >= dst_size) {
    327           return OTS_FAILURE();
    328         }
    329         dst[flag_offset++] = repeat_count;
    330       }
    331       if (flag_offset >= dst_size) {
    332         return OTS_FAILURE();
    333       }
    334       dst[flag_offset++] = flag;
    335       repeat_count = 0;
    336     }
    337     last_x = point.x;
    338     last_y = point.y;
    339     last_flag = flag;
    340   }
    341 
    342   if (repeat_count != 0) {
    343     if (flag_offset >= dst_size) {
    344       return OTS_FAILURE();
    345     }
    346     dst[flag_offset++] = repeat_count;
    347   }
    348   unsigned int xy_bytes = x_bytes + y_bytes;
    349   if (xy_bytes < x_bytes ||
    350       flag_offset + xy_bytes < flag_offset ||
    351       flag_offset + xy_bytes > dst_size) {
    352     return OTS_FAILURE();
    353   }
    354 
    355   int x_offset = flag_offset;
    356   int y_offset = flag_offset + x_bytes;
    357   last_x = 0;
    358   last_y = 0;
    359   for (size_t i = 0; i < points.size(); ++i) {
    360     int dx = points.at(i).x - last_x;
    361     if (dx == 0) {
    362       // pass
    363     } else if (dx > -256 && dx < 256) {
    364       dst[x_offset++] = std::abs(dx);
    365     } else {
    366       // will always fit for valid input, but overflow is harmless
    367       x_offset = Store16(dst, x_offset, dx);
    368     }
    369     last_x += dx;
    370     int dy = points.at(i).y - last_y;
    371     if (dy == 0) {
    372       // pass
    373     } else if (dy > -256 && dy < 256) {
    374       dst[y_offset++] = std::abs(dy);
    375     } else {
    376       y_offset = Store16(dst, y_offset, dy);
    377     }
    378     last_y += dy;
    379   }
    380   *glyph_size = y_offset;
    381   return true;
    382 }
    383 
    384 // Compute the bounding box of the coordinates, and store into a glyf buffer.
    385 // A precondition is that there are at least 10 bytes available.
    386 void ComputeBbox(const std::vector<Point>& points, uint8_t* dst) {
    387   int x_min = 0;
    388   int y_min = 0;
    389   int x_max = 0;
    390   int y_max = 0;
    391 
    392   for (size_t i = 0; i < points.size(); ++i) {
    393     int x = points.at(i).x;
    394     int y = points.at(i).y;
    395     if (i == 0 || x < x_min) x_min = x;
    396     if (i == 0 || x > x_max) x_max = x;
    397     if (i == 0 || y < y_min) y_min = y;
    398     if (i == 0 || y > y_max) y_max = y;
    399   }
    400   size_t offset = 2;
    401   offset = Store16(dst, offset, x_min);
    402   offset = Store16(dst, offset, y_min);
    403   offset = Store16(dst, offset, x_max);
    404   offset = Store16(dst, offset, y_max);
    405 }
    406 
    407 // Process entire bbox stream. This is done as a separate pass to allow for
    408 // composite bbox computations (an optional more aggressive transform).
    409 bool ProcessBboxStream(ots::Buffer* bbox_stream, unsigned int n_glyphs,
    410     const std::vector<uint32_t>& loca_values, uint8_t* glyf_buf,
    411     size_t glyf_buf_length) {
    412   const uint8_t* buf = bbox_stream->buffer();
    413   if (n_glyphs >= 65536 || loca_values.size() != n_glyphs + 1) {
    414     return OTS_FAILURE();
    415   }
    416   // Safe because n_glyphs is bounded
    417   unsigned int bitmap_length = ((n_glyphs + 31) >> 5) << 2;
    418   if (!bbox_stream->Skip(bitmap_length)) {
    419     return OTS_FAILURE();
    420   }
    421   for (unsigned int i = 0; i < n_glyphs; ++i) {
    422     if (buf[i >> 3] & (0x80 >> (i & 7))) {
    423       uint32_t loca_offset = loca_values.at(i);
    424       if (loca_values.at(i + 1) - loca_offset < kEndPtsOfContoursOffset) {
    425         return OTS_FAILURE();
    426       }
    427       if (glyf_buf_length < 2 + 10 ||
    428           loca_offset > glyf_buf_length - 2 - 10) {
    429         return OTS_FAILURE();
    430       }
    431       if (!bbox_stream->Read(glyf_buf + loca_offset + 2, 8)) {
    432         return OTS_FAILURE();
    433       }
    434     }
    435   }
    436   return true;
    437 }
    438 
    439 bool ProcessComposite(ots::Buffer* composite_stream, uint8_t* dst,
    440     size_t dst_size, size_t* glyph_size, bool* have_instructions) {
    441   size_t start_offset = composite_stream->offset();
    442   bool we_have_instructions = false;
    443 
    444   uint16_t flags = FLAG_MORE_COMPONENTS;
    445   while (flags & FLAG_MORE_COMPONENTS) {
    446     if (!composite_stream->ReadU16(&flags)) {
    447       return OTS_FAILURE();
    448     }
    449     we_have_instructions |= (flags & FLAG_WE_HAVE_INSTRUCTIONS) != 0;
    450     size_t arg_size = 2;  // glyph index
    451     if (flags & FLAG_ARG_1_AND_2_ARE_WORDS) {
    452       arg_size += 4;
    453     } else {
    454       arg_size += 2;
    455     }
    456     if (flags & FLAG_WE_HAVE_A_SCALE) {
    457       arg_size += 2;
    458     } else if (flags & FLAG_WE_HAVE_AN_X_AND_Y_SCALE) {
    459       arg_size += 4;
    460     } else if (flags & FLAG_WE_HAVE_A_TWO_BY_TWO) {
    461       arg_size += 8;
    462     }
    463     if (!composite_stream->Skip(arg_size)) {
    464       return OTS_FAILURE();
    465     }
    466   }
    467   size_t composite_glyph_size = composite_stream->offset() - start_offset;
    468   if (composite_glyph_size + kCompositeGlyphBegin > dst_size) {
    469     return OTS_FAILURE();
    470   }
    471   Store16(dst, 0, 0xffff);  // nContours = -1 for composite glyph
    472   std::memcpy(dst + kCompositeGlyphBegin,
    473       composite_stream->buffer() + start_offset,
    474       composite_glyph_size);
    475   *glyph_size = kCompositeGlyphBegin + composite_glyph_size;
    476   *have_instructions = we_have_instructions;
    477   return true;
    478 }
    479 
    480 // Build TrueType loca table
    481 bool StoreLoca(const std::vector<uint32_t>& loca_values, int index_format,
    482     uint8_t* dst, size_t dst_size) {
    483   const uint64_t loca_size = loca_values.size();
    484   const uint64_t offset_size = index_format ? 4 : 2;
    485   if ((loca_size << 2) >> 2 != loca_size) {
    486     return OTS_FAILURE();
    487   }
    488   // No integer overflow here (loca_size <= 2^16).
    489   if (offset_size * loca_size > dst_size) {
    490     return OTS_FAILURE();
    491   }
    492   size_t offset = 0;
    493   for (size_t i = 0; i < loca_values.size(); ++i) {
    494     uint32_t value = loca_values.at(i);
    495     if (index_format) {
    496       offset = StoreU32(dst, offset, value);
    497     } else {
    498       offset = Store16(dst, offset, value >> 1);
    499     }
    500   }
    501   return true;
    502 }
    503 
    504 // Reconstruct entire glyf table based on transformed original
    505 bool ReconstructGlyf(const uint8_t* data, size_t data_size,
    506     uint8_t* dst, size_t dst_size,
    507     uint8_t* loca_buf, size_t loca_size) {
    508   static const int kNumSubStreams = 7;
    509   ots::Buffer file(data, data_size);
    510   uint32_t version;
    511   std::vector<std::pair<const uint8_t*, size_t> > substreams(kNumSubStreams);
    512 
    513   if (!file.ReadU32(&version)) {
    514     return OTS_FAILURE();
    515   }
    516   uint16_t num_glyphs;
    517   uint16_t index_format;
    518   if (!file.ReadU16(&num_glyphs) ||
    519       !file.ReadU16(&index_format)) {
    520     return OTS_FAILURE();
    521   }
    522   unsigned int offset = (2 + kNumSubStreams) * 4;
    523   if (offset > data_size) {
    524     return OTS_FAILURE();
    525   }
    526   // Invariant from here on: data_size >= offset
    527   for (int i = 0; i < kNumSubStreams; ++i) {
    528     uint32_t substream_size;
    529     if (!file.ReadU32(&substream_size)) {
    530       return OTS_FAILURE();
    531     }
    532     if (substream_size > data_size - offset) {
    533       return OTS_FAILURE();
    534     }
    535     substreams.at(i) = std::make_pair(data + offset, substream_size);
    536     offset += substream_size;
    537   }
    538   ots::Buffer n_contour_stream(substreams.at(0).first, substreams.at(0).second);
    539   ots::Buffer n_points_stream(substreams.at(1).first, substreams.at(1).second);
    540   ots::Buffer flag_stream(substreams.at(2).first, substreams.at(2).second);
    541   ots::Buffer glyph_stream(substreams.at(3).first, substreams.at(3).second);
    542   ots::Buffer composite_stream(substreams.at(4).first, substreams.at(4).second);
    543   ots::Buffer bbox_stream(substreams.at(5).first, substreams.at(5).second);
    544   ots::Buffer instruction_stream(substreams.at(6).first,
    545                                  substreams.at(6).second);
    546 
    547   std::vector<uint32_t> loca_values;
    548   loca_values.reserve(num_glyphs + 1);
    549   std::vector<unsigned int> n_points_vec;
    550   std::vector<Point> points;
    551   uint32_t loca_offset = 0;
    552   for (unsigned int i = 0; i < num_glyphs; ++i) {
    553     size_t glyph_size = 0;
    554     uint16_t n_contours = 0;
    555     if (!n_contour_stream.ReadU16(&n_contours)) {
    556       return OTS_FAILURE();
    557     }
    558     uint8_t* glyf_dst = dst + loca_offset;
    559     size_t glyf_dst_size = dst_size - loca_offset;
    560     if (n_contours == 0xffff) {
    561       // composite glyph
    562       bool have_instructions = false;
    563       unsigned int instruction_size = 0;
    564       if (!ProcessComposite(&composite_stream, glyf_dst, glyf_dst_size,
    565             &glyph_size, &have_instructions)) {
    566         return OTS_FAILURE();
    567       }
    568       if (have_instructions) {
    569         if (!Read255UShort(&glyph_stream, &instruction_size)) {
    570           return OTS_FAILURE();
    571         }
    572         // No integer overflow here (instruction_size < 2^16).
    573         if (instruction_size + 2 > glyf_dst_size - glyph_size) {
    574           return OTS_FAILURE();
    575         }
    576         Store16(glyf_dst, glyph_size, instruction_size);
    577         if (!instruction_stream.Read(glyf_dst + glyph_size + 2,
    578               instruction_size)) {
    579           return OTS_FAILURE();
    580         }
    581         glyph_size += instruction_size + 2;
    582       }
    583     } else if (n_contours > 0) {
    584       // simple glyph
    585       n_points_vec.clear();
    586       points.clear();
    587       unsigned int total_n_points = 0;
    588       unsigned int n_points_contour;
    589       for (unsigned int j = 0; j < n_contours; ++j) {
    590         if (!Read255UShort(&n_points_stream, &n_points_contour)) {
    591           return OTS_FAILURE();
    592         }
    593         n_points_vec.push_back(n_points_contour);
    594         if (total_n_points + n_points_contour < total_n_points) {
    595           return OTS_FAILURE();
    596         }
    597         total_n_points += n_points_contour;
    598       }
    599       unsigned int flag_size = total_n_points;
    600       if (flag_size > flag_stream.length() - flag_stream.offset()) {
    601         return OTS_FAILURE();
    602       }
    603       const uint8_t* flags_buf = flag_stream.buffer() + flag_stream.offset();
    604       const uint8_t* triplet_buf = glyph_stream.buffer() +
    605         glyph_stream.offset();
    606       size_t triplet_size = glyph_stream.length() - glyph_stream.offset();
    607       size_t triplet_bytes_consumed = 0;
    608       if (!TripletDecode(flags_buf, triplet_buf, triplet_size, total_n_points,
    609             &points, &triplet_bytes_consumed)) {
    610         return OTS_FAILURE();
    611       }
    612       const uint32_t header_and_endpts_contours_size =
    613           kEndPtsOfContoursOffset + 2 * n_contours;
    614       if (glyf_dst_size < header_and_endpts_contours_size) {
    615         return OTS_FAILURE();
    616       }
    617       Store16(glyf_dst, 0, n_contours);
    618       ComputeBbox(points, glyf_dst);
    619       size_t offset = kEndPtsOfContoursOffset;
    620       int end_point = -1;
    621       for (unsigned int contour_ix = 0; contour_ix < n_contours; ++contour_ix) {
    622         end_point += n_points_vec.at(contour_ix);
    623         if (end_point >= 65536) {
    624           return OTS_FAILURE();
    625         }
    626         offset = Store16(glyf_dst, offset, end_point);
    627       }
    628       if (!flag_stream.Skip(flag_size)) {
    629         return OTS_FAILURE();
    630       }
    631       if (!glyph_stream.Skip(triplet_bytes_consumed)) {
    632         return OTS_FAILURE();
    633       }
    634       unsigned int instruction_size;
    635       if (!Read255UShort(&glyph_stream, &instruction_size)) {
    636         return OTS_FAILURE();
    637       }
    638       // No integer overflow here (instruction_size < 2^16).
    639       if (glyf_dst_size - header_and_endpts_contours_size <
    640           instruction_size + 2) {
    641         return OTS_FAILURE();
    642       }
    643       uint8_t* instruction_dst = glyf_dst + header_and_endpts_contours_size;
    644       Store16(instruction_dst, 0, instruction_size);
    645       if (!instruction_stream.Read(instruction_dst + 2, instruction_size)) {
    646         return OTS_FAILURE();
    647       }
    648       if (!StorePoints(points, n_contours, instruction_size,
    649             glyf_dst, glyf_dst_size, &glyph_size)) {
    650         return OTS_FAILURE();
    651       }
    652     } else {
    653       glyph_size = 0;
    654     }
    655     loca_values.push_back(loca_offset);
    656     if (glyph_size + 3 < glyph_size) {
    657       return OTS_FAILURE();
    658     }
    659     glyph_size = ots::Round2(glyph_size);
    660     if (glyph_size > dst_size - loca_offset) {
    661       // This shouldn't happen, but this test defensively maintains the
    662       // invariant that loca_offset <= dst_size.
    663       return OTS_FAILURE();
    664     }
    665     loca_offset += glyph_size;
    666   }
    667   loca_values.push_back(loca_offset);
    668   assert(loca_values.size() == static_cast<size_t>(num_glyphs + 1));
    669   if (!ProcessBboxStream(&bbox_stream, num_glyphs, loca_values,
    670           dst, dst_size)) {
    671     return OTS_FAILURE();
    672   }
    673   return StoreLoca(loca_values, index_format, loca_buf, loca_size);
    674 }
    675 
    676 // This is linear search, but could be changed to binary because we
    677 // do have a guarantee that the tables are sorted by tag. But the total
    678 // cpu time is expected to be very small in any case.
    679 const Table* FindTable(const std::vector<Table>& tables, uint32_t tag) {
    680   size_t n_tables = tables.size();
    681   for (size_t i = 0; i < n_tables; ++i) {
    682     if (tables.at(i).tag == tag) {
    683       return &tables.at(i);
    684     }
    685   }
    686   return NULL;
    687 }
    688 
    689 bool ReconstructTransformed(const std::vector<Table>& tables, uint32_t tag,
    690     const uint8_t* transformed_buf, size_t transformed_size,
    691     uint8_t* dst, size_t dst_length) {
    692   if (tag == TAG('g', 'l', 'y', 'f')) {
    693     const Table* glyf_table = FindTable(tables, tag);
    694     const Table* loca_table = FindTable(tables, TAG('l', 'o', 'c', 'a'));
    695     if (glyf_table == NULL || loca_table == NULL) {
    696       return OTS_FAILURE();
    697     }
    698     if (static_cast<uint64_t>(glyf_table->dst_offset) + glyf_table->dst_length >
    699         dst_length) {
    700       return OTS_FAILURE();
    701     }
    702     if (static_cast<uint64_t>(loca_table->dst_offset) + loca_table->dst_length >
    703         dst_length) {
    704       return OTS_FAILURE();
    705     }
    706     return ReconstructGlyf(transformed_buf, transformed_size,
    707         dst + glyf_table->dst_offset, glyf_table->dst_length,
    708         dst + loca_table->dst_offset, loca_table->dst_length);
    709   } else if (tag == TAG('l', 'o', 'c', 'a')) {
    710     // processing was already done by glyf table, but validate
    711     if (!FindTable(tables, TAG('g', 'l', 'y', 'f'))) {
    712       return OTS_FAILURE();
    713     }
    714   } else {
    715     // transform for the tag is not known
    716     return OTS_FAILURE();
    717   }
    718   return true;
    719 }
    720 
    721 uint32_t ComputeChecksum(const uint8_t* buf, size_t size) {
    722   uint32_t checksum = 0;
    723   for (size_t i = 0; i < size; i += 4) {
    724     // We assume the addition is mod 2^32, which is valid because unsigned
    725     checksum += (buf[i] << 24) | (buf[i + 1] << 16) |
    726       (buf[i + 2] << 8) | buf[i + 3];
    727   }
    728   return checksum;
    729 }
    730 
    731 bool FixChecksums(const std::vector<Table>& tables, uint8_t* dst) {
    732   const Table* head_table = FindTable(tables, TAG('h', 'e', 'a', 'd'));
    733   if (head_table == NULL ||
    734       head_table->dst_length < kCheckSumAdjustmentOffset + 4) {
    735     return OTS_FAILURE();
    736   }
    737   size_t adjustment_offset = head_table->dst_offset + kCheckSumAdjustmentOffset;
    738   if (adjustment_offset < head_table->dst_offset) {
    739     return OTS_FAILURE();
    740   }
    741   StoreU32(dst, adjustment_offset, 0);
    742   size_t n_tables = tables.size();
    743   uint32_t file_checksum = 0;
    744   for (size_t i = 0; i < n_tables; ++i) {
    745     const Table* table = &tables.at(i);
    746     size_t table_length = table->dst_length;
    747     uint8_t* table_data = dst + table->dst_offset;
    748     uint32_t checksum = ComputeChecksum(table_data, table_length);
    749     StoreU32(dst, kSfntHeaderSize + i * kSfntEntrySize + 4, checksum);
    750     file_checksum += checksum;  // The addition is mod 2^32
    751   }
    752   file_checksum += ComputeChecksum(dst,
    753       kSfntHeaderSize + kSfntEntrySize * n_tables);
    754   uint32_t checksum_adjustment = 0xb1b0afba - file_checksum;
    755   StoreU32(dst, adjustment_offset, checksum_adjustment);
    756   return true;
    757 }
    758 
    759 bool Woff2Uncompress(uint8_t* dst_buf, size_t dst_size,
    760     const uint8_t* src_buf, size_t src_size, uint32_t compression_type) {
    761   if (compression_type == kCompressionTypeGzip) {
    762     uLongf uncompressed_length = dst_size;
    763     int r = uncompress(reinterpret_cast<Bytef *>(dst_buf), &uncompressed_length,
    764         src_buf, src_size);
    765     if (r != Z_OK || uncompressed_length != dst_size) {
    766       return OTS_FAILURE();
    767     }
    768     return true;
    769   } else if (compression_type == kCompressionTypeLzma) {
    770     if (src_size < kLzmaHeaderSize) {
    771       // Make sure we have at least a full Lzma header
    772       return OTS_FAILURE();
    773     }
    774     // TODO: check that size matches (or elide size?)
    775     size_t uncompressed_size = dst_size;
    776     size_t compressed_size = src_size;
    777     int result = LzmaUncompress(dst_buf, &dst_size,
    778         src_buf + kLzmaHeaderSize, &compressed_size,
    779         src_buf, LZMA_PROPS_SIZE);
    780     if (result != SZ_OK || uncompressed_size != dst_size) {
    781       return OTS_FAILURE();
    782     }
    783     return true;
    784   }
    785   // Unknown compression type
    786   return OTS_FAILURE();
    787 }
    788 
    789 bool ReadShortDirectory(ots::Buffer* file, std::vector<Table>* tables,
    790     size_t num_tables) {
    791   uint32_t last_compression_type = 0;
    792   for (size_t i = 0; i < num_tables; ++i) {
    793     Table* table = &tables->at(i);
    794     uint8_t flag_byte;
    795     if (!file->ReadU8(&flag_byte)) {
    796       return OTS_FAILURE();
    797     }
    798     uint32_t tag;
    799     if ((flag_byte & 0x1f) == 0x1f) {
    800       if (!file->ReadU32(&tag)) {
    801         return OTS_FAILURE();
    802       }
    803     } else {
    804       if ((flag_byte & 0x1f) >= arraysize(kKnownTags)) {
    805         return OTS_FAILURE();
    806       }
    807       tag = kKnownTags[flag_byte & 0x1f];
    808     }
    809     uint32_t flags = flag_byte >> 6;
    810     if (flags == kShortFlagsContinue) {
    811       flags = last_compression_type | kWoff2FlagsContinueStream;
    812     } else {
    813       if (flags == kCompressionTypeNone ||
    814           flags == kCompressionTypeGzip ||
    815           flags == kCompressionTypeLzma) {
    816         last_compression_type = flags;
    817       } else {
    818         return OTS_FAILURE();
    819       }
    820     }
    821     if ((flag_byte & 0x20) != 0) {
    822       flags |= kWoff2FlagsTransform;
    823     }
    824     uint32_t dst_length;
    825     if (!ReadBase128(file, &dst_length)) {
    826       return OTS_FAILURE();
    827     }
    828     uint32_t transform_length = dst_length;
    829     if ((flags & kWoff2FlagsTransform) != 0) {
    830       if (!ReadBase128(file, &transform_length)) {
    831         return OTS_FAILURE();
    832       }
    833     }
    834     uint32_t src_length = transform_length;
    835     if ((flag_byte >> 6) == 1 || (flag_byte >> 6) == 2) {
    836       if (!ReadBase128(file, &src_length)) {
    837         return OTS_FAILURE();
    838       }
    839     }
    840     // Disallow huge numbers (> 1GB) for sanity.
    841     if (src_length > 1024 * 1024 * 1024 ||
    842         transform_length > 1024 * 1024 * 1024 ||
    843         dst_length > 1024 * 1024 * 1024) {
    844       return OTS_FAILURE();
    845     }
    846 
    847     table->tag = tag;
    848     table->flags = flags;
    849     table->src_length = src_length;
    850     table->transform_length = transform_length;
    851     table->dst_length = dst_length;
    852   }
    853   return true;
    854 }
    855 
    856 }  // namespace
    857 
    858 namespace ots {
    859 
    860 size_t ComputeWOFF2FinalSize(const uint8_t* data, size_t length) {
    861   ots::Buffer file(data, length);
    862   uint32_t total_length;
    863 
    864   if (!file.Skip(16) ||
    865       !file.ReadU32(&total_length)) {
    866     return 0;
    867   }
    868   return total_length;
    869 }
    870 
    871 bool ConvertWOFF2ToTTF(uint8_t* result, size_t result_length,
    872                        const uint8_t* data, size_t length) {
    873   static const uint32_t kWoff2Signature = 0x774f4632;  // "wOF2"
    874   ots::Buffer file(data, length);
    875 
    876   uint32_t signature;
    877   uint32_t flavor;
    878   if (!file.ReadU32(&signature) || signature != kWoff2Signature ||
    879       !file.ReadU32(&flavor)) {
    880     return OTS_FAILURE();
    881   }
    882 
    883   if (!IsValidVersionTag(ntohl(flavor))) {
    884     return OTS_FAILURE();
    885   }
    886 
    887   uint32_t reported_length;
    888   if (!file.ReadU32(&reported_length) || length != reported_length) {
    889     return OTS_FAILURE();
    890   }
    891   uint16_t num_tables;
    892   if (!file.ReadU16(&num_tables) || !num_tables) {
    893     return OTS_FAILURE();
    894   }
    895   // We don't care about these fields of the header:
    896   //   uint16_t reserved
    897   //   uint32_t total_sfnt_size
    898   //   uint16_t major_version, minor_version
    899   //   uint32_t meta_offset, meta_length, meta_orig_length
    900   //   uint32_t priv_offset, priv_length
    901   if (!file.Skip(30)) {
    902     return OTS_FAILURE();
    903   }
    904   std::vector<Table> tables(num_tables);
    905   if (!ReadShortDirectory(&file, &tables, num_tables)) {
    906     return OTS_FAILURE();
    907   }
    908   uint64_t src_offset = file.offset();
    909   uint64_t dst_offset = kSfntHeaderSize +
    910       kSfntEntrySize * static_cast<uint64_t>(num_tables);
    911   uint64_t uncompressed_sum = 0;
    912   for (uint16_t i = 0; i < num_tables; ++i) {
    913     Table* table = &tables.at(i);
    914     table->src_offset = src_offset;
    915     src_offset += table->src_length;
    916     if (src_offset > std::numeric_limits<uint32_t>::max()) {
    917       return OTS_FAILURE();
    918     }
    919     src_offset = ots::Round4(src_offset);
    920     table->dst_offset = dst_offset;
    921     dst_offset += table->dst_length;
    922     if (dst_offset > std::numeric_limits<uint32_t>::max()) {
    923       return OTS_FAILURE();
    924     }
    925     dst_offset = ots::Round4(dst_offset);
    926     if ((table->flags & kCompressionTypeMask) != kCompressionTypeNone) {
    927       uncompressed_sum += table->src_length;
    928       if (uncompressed_sum > std::numeric_limits<uint32_t>::max()) {
    929         return OTS_FAILURE();
    930       }
    931     }
    932   }
    933   // Enforce same 30M limit on uncompressed tables as OTS
    934   if (uncompressed_sum > 30 * 1024 * 1024) {
    935     return OTS_FAILURE();
    936   }
    937   if (src_offset > length || dst_offset > result_length) {
    938     return OTS_FAILURE();
    939   }
    940 
    941   const uint32_t sfnt_header_and_table_directory_size = 12 + 16 * num_tables;
    942   if (sfnt_header_and_table_directory_size > result_length) {
    943     return OTS_FAILURE();
    944   }
    945 
    946   // Start building the font
    947   size_t offset = 0;
    948   offset = StoreU32(result, offset, flavor);
    949   offset = Store16(result, offset, num_tables);
    950   unsigned max_pow2 = 0;
    951   while (1u << (max_pow2 + 1) <= num_tables) {
    952     max_pow2++;
    953   }
    954   const uint16_t output_search_range = (1u << max_pow2) << 4;
    955   offset = Store16(result, offset, output_search_range);
    956   offset = Store16(result, offset, max_pow2);
    957   offset = Store16(result, offset, (num_tables << 4) - output_search_range);
    958   for (uint16_t i = 0; i < num_tables; ++i) {
    959     const Table* table = &tables.at(i);
    960     offset = StoreU32(result, offset, table->tag);
    961     offset = StoreU32(result, offset, 0);  // checksum, to fill in later
    962     offset = StoreU32(result, offset, table->dst_offset);
    963     offset = StoreU32(result, offset, table->dst_length);
    964   }
    965   std::vector<uint8_t> uncompressed_buf;
    966   bool continue_valid = false;
    967   for (uint16_t i = 0; i < num_tables; ++i) {
    968     const Table* table = &tables.at(i);
    969     uint32_t flags = table->flags;
    970     const uint8_t* src_buf = data + table->src_offset;
    971     uint32_t compression_type = flags & kCompressionTypeMask;
    972     const uint8_t* transform_buf = NULL;
    973     size_t transform_length = table->transform_length;
    974     if ((flags & kWoff2FlagsContinueStream) != 0) {
    975       if (!continue_valid) {
    976         return OTS_FAILURE();
    977       }
    978     } else if (compression_type == kCompressionTypeNone) {
    979       if (transform_length != table->src_length) {
    980         return OTS_FAILURE();
    981       }
    982       transform_buf = src_buf;
    983       continue_valid = false;
    984     } else if ((flags & kWoff2FlagsContinueStream) == 0) {
    985       uint64_t total_size = transform_length;
    986       for (uint16_t j = i + 1; j < num_tables; ++j) {
    987         if ((tables.at(j).flags & kWoff2FlagsContinueStream) == 0) {
    988           break;
    989         }
    990         total_size += tables.at(j).transform_length;
    991         if (total_size > std::numeric_limits<uint32_t>::max()) {
    992           return OTS_FAILURE();
    993         }
    994       }
    995       // Enforce same 30M limit on uncompressed tables as OTS
    996       if (total_size > 30 * 1024 * 1024) {
    997         return OTS_FAILURE();
    998       }
    999       uncompressed_buf.resize(total_size);
   1000       if (!Woff2Uncompress(&uncompressed_buf[0], total_size,
   1001           src_buf, table->src_length, compression_type)) {
   1002         return OTS_FAILURE();
   1003       }
   1004       transform_buf = &uncompressed_buf[0];
   1005       continue_valid = true;
   1006     } else {
   1007       return OTS_FAILURE();
   1008     }
   1009 
   1010     if ((flags & kWoff2FlagsTransform) == 0) {
   1011       if (transform_length != table->dst_length) {
   1012         return OTS_FAILURE();
   1013       }
   1014       if (static_cast<uint64_t>(table->dst_offset) + transform_length >
   1015           result_length) {
   1016         return OTS_FAILURE();
   1017       }
   1018       std::memcpy(result + table->dst_offset, transform_buf,
   1019           transform_length);
   1020     } else {
   1021       if (!ReconstructTransformed(tables, table->tag,
   1022             transform_buf, transform_length, result, result_length)) {
   1023         return OTS_FAILURE();
   1024       }
   1025     }
   1026     if (continue_valid) {
   1027       transform_buf += transform_length;
   1028       if (transform_buf > &uncompressed_buf[0] + uncompressed_buf.size()) {
   1029         return OTS_FAILURE();
   1030       }
   1031     }
   1032   }
   1033 
   1034   return FixChecksums(tables, result);
   1035 }
   1036 
   1037 }  // namespace ots
   1038