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