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