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