OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This is the implementation of decompression of the proposed WOFF Ultra | 5 // This is the implementation of decompression of the proposed WOFF Ultra |
6 // Condensed file format. | 6 // Condensed file format. |
7 | 7 |
8 #include <cassert> | 8 #include <cassert> |
9 #include <cstdlib> | 9 #include <cstdlib> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include <zlib.h> | 12 #include <zlib.h> |
13 | 13 |
14 #include "third_party/brotli/src/brotli/dec/decode.h" | 14 #include "third_party/brotli/src/brotli/dec/decode.h" |
15 | 15 |
16 #include "opentype-sanitiser.h" | 16 #include "opentype-sanitiser.h" |
17 #include "ots-memory-stream.h" | 17 #include "ots-memory-stream.h" |
18 #include "ots.h" | 18 #include "ots.h" |
19 #include "woff2.h" | 19 #include "woff2.h" |
20 | 20 |
21 namespace { | 21 namespace { |
22 | 22 |
23 // simple glyph flags | 23 // simple glyph flags |
24 const int kGlyfOnCurve = 1 << 0; | 24 const uint8_t kGlyfOnCurve = 1 << 0; |
25 const int kGlyfXShort = 1 << 1; | 25 const uint8_t kGlyfXShort = 1 << 1; |
26 const int kGlyfYShort = 1 << 2; | 26 const uint8_t kGlyfYShort = 1 << 2; |
27 const int kGlyfRepeat = 1 << 3; | 27 const uint8_t kGlyfRepeat = 1 << 3; |
28 const int kGlyfThisXIsSame = 1 << 4; | 28 const uint8_t kGlyfThisXIsSame = 1 << 4; |
29 const int kGlyfThisYIsSame = 1 << 5; | 29 const uint8_t kGlyfThisYIsSame = 1 << 5; |
30 | 30 |
31 // composite glyph flags | 31 // composite glyph flags |
32 const int FLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0; | 32 const int FLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0; |
33 const int FLAG_WE_HAVE_A_SCALE = 1 << 3; | 33 const int FLAG_WE_HAVE_A_SCALE = 1 << 3; |
34 const int FLAG_MORE_COMPONENTS = 1 << 5; | 34 const int FLAG_MORE_COMPONENTS = 1 << 5; |
35 const int FLAG_WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6; | 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; | 36 const int FLAG_WE_HAVE_A_TWO_BY_TWO = 1 << 7; |
37 const int FLAG_WE_HAVE_INSTRUCTIONS = 1 << 8; | 37 const int FLAG_WE_HAVE_INSTRUCTIONS = 1 << 8; |
38 | 38 |
39 const size_t kSfntHeaderSize = 12; | 39 const size_t kSfntHeaderSize = 12; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 TAG('t', 'r', 'a', 'k'), // 56 | 115 TAG('t', 'r', 'a', 'k'), // 56 |
116 TAG('Z', 'a', 'p', 'f'), // 57 | 116 TAG('Z', 'a', 'p', 'f'), // 57 |
117 TAG('S', 'i', 'l', 'f'), // 58 | 117 TAG('S', 'i', 'l', 'f'), // 58 |
118 TAG('G', 'l', 'a', 't'), // 59 | 118 TAG('G', 'l', 'a', 't'), // 59 |
119 TAG('G', 'l', 'o', 'c'), // 60 | 119 TAG('G', 'l', 'o', 'c'), // 60 |
120 TAG('F', 'e', 'a', 't'), // 61 | 120 TAG('F', 'e', 'a', 't'), // 61 |
121 TAG('S', 'i', 'l', 'l'), // 62 | 121 TAG('S', 'i', 'l', 'l'), // 62 |
122 }; | 122 }; |
123 | 123 |
124 struct Point { | 124 struct Point { |
125 int x; | 125 int16_t x; |
126 int y; | 126 int16_t y; |
127 bool on_curve; | 127 bool on_curve; |
128 }; | 128 }; |
129 | 129 |
130 struct Table { | 130 struct Table { |
131 uint32_t tag; | 131 uint32_t tag; |
132 uint32_t flags; | 132 uint32_t flags; |
133 uint32_t src_offset; | 133 uint32_t src_offset; |
134 uint32_t src_length; | 134 uint32_t src_length; |
135 | 135 |
136 uint32_t transform_length; | 136 uint32_t transform_length; |
137 | 137 |
138 uint32_t dst_offset; | 138 uint32_t dst_offset; |
139 uint32_t dst_length; | 139 uint32_t dst_length; |
140 | 140 |
141 Table() | 141 Table() |
142 : tag(0), | 142 : tag(0), |
143 flags(0), | 143 flags(0), |
144 src_offset(0), | 144 src_offset(0), |
145 src_length(0), | 145 src_length(0), |
146 transform_length(0), | 146 transform_length(0), |
147 dst_offset(0), | 147 dst_offset(0), |
148 dst_length(0) {} | 148 dst_length(0) {} |
149 }; | 149 }; |
150 | 150 |
151 // Based on section 6.1.1 of MicroType Express draft spec | 151 // Based on section 6.1.1 of MicroType Express draft spec |
152 bool Read255UShort(ots::Buffer* buf, unsigned int* value) { | 152 bool Read255UShort(ots::Buffer* buf, uint16_t* value) { |
153 static const int kWordCode = 253; | 153 static const uint8_t kWordCode = 253; |
154 static const int kOneMoreByteCode2 = 254; | 154 static const uint8_t kOneMoreByteCode2 = 254; |
155 static const int kOneMoreByteCode1 = 255; | 155 static const uint8_t kOneMoreByteCode1 = 255; |
156 static const int kLowestUCode = 253; | 156 static const uint8_t kLowestUCode = 253; |
157 uint8_t code = 0; | 157 uint8_t code = 0; |
158 if (!buf->ReadU8(&code)) { | 158 if (!buf->ReadU8(&code)) { |
159 return OTS_FAILURE(); | 159 return OTS_FAILURE(); |
160 } | 160 } |
161 if (code == kWordCode) { | 161 if (code == kWordCode) { |
162 uint16_t result = 0; | 162 uint16_t result = 0; |
163 if (!buf->ReadU16(&result)) { | 163 if (!buf->ReadU16(&result)) { |
164 return OTS_FAILURE(); | 164 return OTS_FAILURE(); |
165 } | 165 } |
166 *value = result; | 166 *value = result; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 } | 204 } |
205 // Make sure not to exceed the size bound | 205 // Make sure not to exceed the size bound |
206 return OTS_FAILURE(); | 206 return OTS_FAILURE(); |
207 } | 207 } |
208 | 208 |
209 // Caller must ensure that buffer overrun won't happen. | 209 // Caller must ensure that buffer overrun won't happen. |
210 // TODO(ksakamaoto): Consider creating 'writer' version of the Buffer class | 210 // TODO(ksakamaoto): Consider creating 'writer' version of the Buffer class |
211 // and use it across the code. | 211 // and use it across the code. |
212 size_t StoreU32(uint8_t* dst, size_t offset, uint32_t x) { | 212 size_t StoreU32(uint8_t* dst, size_t offset, uint32_t x) { |
213 dst[offset] = x >> 24; | 213 dst[offset] = x >> 24; |
214 dst[offset + 1] = x >> 16; | 214 dst[offset + 1] = (x >> 16) & 0xff; |
215 dst[offset + 2] = x >> 8; | 215 dst[offset + 2] = (x >> 8) & 0xff; |
216 dst[offset + 3] = x; | 216 dst[offset + 3] = x & 0xff; |
217 return offset + 4; | 217 return offset + 4; |
218 } | 218 } |
219 | 219 |
220 size_t Store16(uint8_t* dst, size_t offset, int x) { | 220 size_t StoreU16(uint8_t* dst, size_t offset, uint16_t x) { |
221 dst[offset] = x >> 8; | 221 dst[offset] = x >> 8; |
222 dst[offset + 1] = x; | 222 dst[offset + 1] = x & 0xff; |
223 return offset + 2; | 223 return offset + 2; |
224 } | 224 } |
225 | 225 |
226 int WithSign(int flag, int baseval) { | 226 int WithSign(int flag, int baseval) { |
227 assert(0 <= baseval && baseval < 65536); | 227 assert(0 <= baseval && baseval < 65536); |
228 return (flag & 1) ? baseval : -baseval; | 228 return (flag & 1) ? baseval : -baseval; |
229 } | 229 } |
230 | 230 |
231 bool TripletDecode(const uint8_t* flags_in, const uint8_t* in, size_t in_size, | 231 bool TripletDecode(const uint8_t* flags_in, const uint8_t* in, size_t in_size, |
232 unsigned int n_points, std::vector<Point>* result, | 232 unsigned int n_points, std::vector<Point>* result, |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 dx = WithSign(flag, (in[triplet_index] << 8) + in[triplet_index + 1]); | 283 dx = WithSign(flag, (in[triplet_index] << 8) + in[triplet_index + 1]); |
284 dy = WithSign(flag >> 1, | 284 dy = WithSign(flag >> 1, |
285 (in[triplet_index + 2] << 8) + in[triplet_index + 3]); | 285 (in[triplet_index + 2] << 8) + in[triplet_index + 3]); |
286 } | 286 } |
287 triplet_index += n_data_bytes; | 287 triplet_index += n_data_bytes; |
288 // Possible overflow but coordinate values are not security sensitive | 288 // Possible overflow but coordinate values are not security sensitive |
289 x += dx; | 289 x += dx; |
290 y += dy; | 290 y += dy; |
291 result->push_back(Point()); | 291 result->push_back(Point()); |
292 Point& back = result->back(); | 292 Point& back = result->back(); |
293 back.x = x; | 293 back.x = static_cast<int16_t>(x); |
294 back.y = y; | 294 back.y = static_cast<int16_t>(y); |
295 back.on_curve = on_curve; | 295 back.on_curve = on_curve; |
296 } | 296 } |
297 *in_bytes_consumed = triplet_index; | 297 *in_bytes_consumed = triplet_index; |
298 return true; | 298 return true; |
299 } | 299 } |
300 | 300 |
301 // This function stores just the point data. On entry, dst points to the | 301 // This function stores just the point data. On entry, dst points to the |
302 // beginning of a simple glyph. Returns true on success. | 302 // beginning of a simple glyph. Returns true on success. |
303 bool StorePoints(const std::vector<Point>& points, | 303 bool StorePoints(const std::vector<Point>& points, |
304 unsigned int n_contours, unsigned int instruction_length, | 304 unsigned int n_contours, unsigned int instruction_length, |
305 uint8_t* dst, size_t dst_size, size_t* glyph_size) { | 305 uint8_t* dst, size_t dst_size, size_t* glyph_size) { |
306 // I believe that n_contours < 65536, in which case this is safe. However, a | 306 // I believe that n_contours < 65536, in which case this is safe. However, a |
307 // comment and/or an assert would be good. | 307 // comment and/or an assert would be good. |
308 unsigned int flag_offset = kEndPtsOfContoursOffset + 2 * n_contours + 2 + | 308 unsigned int flag_offset = kEndPtsOfContoursOffset + 2 * n_contours + 2 + |
309 instruction_length; | 309 instruction_length; |
310 int last_flag = -1; | 310 uint8_t last_flag = 0xff; |
311 int repeat_count = 0; | 311 uint8_t repeat_count = 0; |
312 int last_x = 0; | 312 int last_x = 0; |
313 int last_y = 0; | 313 int last_y = 0; |
314 unsigned int x_bytes = 0; | 314 unsigned int x_bytes = 0; |
315 unsigned int y_bytes = 0; | 315 unsigned int y_bytes = 0; |
316 | 316 |
317 for (size_t i = 0; i < points.size(); ++i) { | 317 for (size_t i = 0; i < points.size(); ++i) { |
318 const Point& point = points.at(i); | 318 const Point& point = points.at(i); |
319 int flag = point.on_curve ? kGlyfOnCurve : 0; | 319 uint8_t flag = point.on_curve ? kGlyfOnCurve : 0; |
320 int dx = point.x - last_x; | 320 int dx = point.x - last_x; |
321 int dy = point.y - last_y; | 321 int dy = point.y - last_y; |
322 if (dx == 0) { | 322 if (dx == 0) { |
323 flag |= kGlyfThisXIsSame; | 323 flag |= kGlyfThisXIsSame; |
324 } else if (dx > -256 && dx < 256) { | 324 } else if (dx > -256 && dx < 256) { |
325 flag |= kGlyfXShort | (dx > 0 ? kGlyfThisXIsSame : 0); | 325 flag |= kGlyfXShort | (dx > 0 ? kGlyfThisXIsSame : 0); |
326 x_bytes += 1; | 326 x_bytes += 1; |
327 } else { | 327 } else { |
328 x_bytes += 2; | 328 x_bytes += 2; |
329 } | 329 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 | 372 |
373 int x_offset = flag_offset; | 373 int x_offset = flag_offset; |
374 int y_offset = flag_offset + x_bytes; | 374 int y_offset = flag_offset + x_bytes; |
375 last_x = 0; | 375 last_x = 0; |
376 last_y = 0; | 376 last_y = 0; |
377 for (size_t i = 0; i < points.size(); ++i) { | 377 for (size_t i = 0; i < points.size(); ++i) { |
378 int dx = points.at(i).x - last_x; | 378 int dx = points.at(i).x - last_x; |
379 if (dx == 0) { | 379 if (dx == 0) { |
380 // pass | 380 // pass |
381 } else if (dx > -256 && dx < 256) { | 381 } else if (dx > -256 && dx < 256) { |
382 dst[x_offset++] = std::abs(dx); | 382 dst[x_offset++] = static_cast<uint8_t>(std::abs(dx)); |
383 } else { | 383 } else { |
384 // will always fit for valid input, but overflow is harmless | 384 // will always fit for valid input, but overflow is harmless |
385 x_offset = Store16(dst, x_offset, dx); | 385 x_offset = StoreU16(dst, x_offset, static_cast<uint16_t>(dx)); |
386 } | 386 } |
387 last_x += dx; | 387 last_x += dx; |
388 int dy = points.at(i).y - last_y; | 388 int dy = points.at(i).y - last_y; |
389 if (dy == 0) { | 389 if (dy == 0) { |
390 // pass | 390 // pass |
391 } else if (dy > -256 && dy < 256) { | 391 } else if (dy > -256 && dy < 256) { |
392 dst[y_offset++] = std::abs(dy); | 392 dst[y_offset++] = static_cast<uint8_t>(std::abs(dy)); |
393 } else { | 393 } else { |
394 y_offset = Store16(dst, y_offset, dy); | 394 y_offset = StoreU16(dst, y_offset, static_cast<uint16_t>(dy)); |
395 } | 395 } |
396 last_y += dy; | 396 last_y += dy; |
397 } | 397 } |
398 *glyph_size = y_offset; | 398 *glyph_size = y_offset; |
399 return true; | 399 return true; |
400 } | 400 } |
401 | 401 |
402 // Compute the bounding box of the coordinates, and store into a glyf buffer. | 402 // Compute the bounding box of the coordinates, and store into a glyf buffer. |
403 // A precondition is that there are at least 10 bytes available. | 403 // A precondition is that there are at least 10 bytes available. |
404 void ComputeBbox(const std::vector<Point>& points, uint8_t* dst) { | 404 void ComputeBbox(const std::vector<Point>& points, uint8_t* dst) { |
405 int x_min = 0; | 405 int16_t x_min = 0; |
406 int y_min = 0; | 406 int16_t y_min = 0; |
407 int x_max = 0; | 407 int16_t x_max = 0; |
408 int y_max = 0; | 408 int16_t y_max = 0; |
409 | 409 |
410 for (size_t i = 0; i < points.size(); ++i) { | 410 for (size_t i = 0; i < points.size(); ++i) { |
411 int x = points.at(i).x; | 411 int16_t x = points.at(i).x; |
412 int y = points.at(i).y; | 412 int16_t y = points.at(i).y; |
413 if (i == 0 || x < x_min) x_min = x; | 413 if (i == 0 || x < x_min) x_min = x; |
414 if (i == 0 || x > x_max) x_max = x; | 414 if (i == 0 || x > x_max) x_max = x; |
415 if (i == 0 || y < y_min) y_min = y; | 415 if (i == 0 || y < y_min) y_min = y; |
416 if (i == 0 || y > y_max) y_max = y; | 416 if (i == 0 || y > y_max) y_max = y; |
417 } | 417 } |
418 size_t offset = 2; | 418 size_t offset = 2; |
419 offset = Store16(dst, offset, x_min); | 419 offset = StoreU16(dst, offset, x_min); |
420 offset = Store16(dst, offset, y_min); | 420 offset = StoreU16(dst, offset, y_min); |
421 offset = Store16(dst, offset, x_max); | 421 offset = StoreU16(dst, offset, x_max); |
422 offset = Store16(dst, offset, y_max); | 422 offset = StoreU16(dst, offset, y_max); |
423 } | 423 } |
424 | 424 |
425 // Process entire bbox stream. This is done as a separate pass to allow for | 425 // Process entire bbox stream. This is done as a separate pass to allow for |
426 // composite bbox computations (an optional more aggressive transform). | 426 // composite bbox computations (an optional more aggressive transform). |
427 bool ProcessBboxStream(ots::Buffer* bbox_stream, unsigned int n_glyphs, | 427 bool ProcessBboxStream(ots::Buffer* bbox_stream, unsigned int n_glyphs, |
428 const std::vector<uint32_t>& loca_values, uint8_t* glyf_buf, | 428 const std::vector<uint32_t>& loca_values, uint8_t* glyf_buf, |
429 size_t glyf_buf_length) { | 429 size_t glyf_buf_length) { |
430 const uint8_t* buf = bbox_stream->buffer(); | 430 const uint8_t* buf = bbox_stream->buffer(); |
431 if (n_glyphs >= 65536 || loca_values.size() != n_glyphs + 1) { | 431 if (n_glyphs >= 65536 || loca_values.size() != n_glyphs + 1) { |
432 return OTS_FAILURE(); | 432 return OTS_FAILURE(); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 arg_size += 8; | 479 arg_size += 8; |
480 } | 480 } |
481 if (!composite_stream->Skip(arg_size)) { | 481 if (!composite_stream->Skip(arg_size)) { |
482 return OTS_FAILURE(); | 482 return OTS_FAILURE(); |
483 } | 483 } |
484 } | 484 } |
485 size_t composite_glyph_size = composite_stream->offset() - start_offset; | 485 size_t composite_glyph_size = composite_stream->offset() - start_offset; |
486 if (composite_glyph_size + kCompositeGlyphBegin > dst_size) { | 486 if (composite_glyph_size + kCompositeGlyphBegin > dst_size) { |
487 return OTS_FAILURE(); | 487 return OTS_FAILURE(); |
488 } | 488 } |
489 Store16(dst, 0, 0xffff); // nContours = -1 for composite glyph | 489 StoreU16(dst, 0, 0xffff); // nContours = -1 for composite glyph |
490 std::memcpy(dst + kCompositeGlyphBegin, | 490 std::memcpy(dst + kCompositeGlyphBegin, |
491 composite_stream->buffer() + start_offset, | 491 composite_stream->buffer() + start_offset, |
492 composite_glyph_size); | 492 composite_glyph_size); |
493 *glyph_size = kCompositeGlyphBegin + composite_glyph_size; | 493 *glyph_size = kCompositeGlyphBegin + composite_glyph_size; |
494 *have_instructions = we_have_instructions; | 494 *have_instructions = we_have_instructions; |
495 return true; | 495 return true; |
496 } | 496 } |
497 | 497 |
498 // Build TrueType loca table | 498 // Build TrueType loca table |
499 bool StoreLoca(const std::vector<uint32_t>& loca_values, int index_format, | 499 bool StoreLoca(const std::vector<uint32_t>& loca_values, int index_format, |
500 uint8_t* dst, size_t dst_size) { | 500 uint8_t* dst, size_t dst_size) { |
501 const uint64_t loca_size = loca_values.size(); | 501 const uint64_t loca_size = loca_values.size(); |
502 const uint64_t offset_size = index_format ? 4 : 2; | 502 const uint64_t offset_size = index_format ? 4 : 2; |
503 if ((loca_size << 2) >> 2 != loca_size) { | 503 if ((loca_size << 2) >> 2 != loca_size) { |
504 return OTS_FAILURE(); | 504 return OTS_FAILURE(); |
505 } | 505 } |
506 // No integer overflow here (loca_size <= 2^16). | 506 // No integer overflow here (loca_size <= 2^16). |
507 if (offset_size * loca_size > dst_size) { | 507 if (offset_size * loca_size > dst_size) { |
508 return OTS_FAILURE(); | 508 return OTS_FAILURE(); |
509 } | 509 } |
510 size_t offset = 0; | 510 size_t offset = 0; |
511 for (size_t i = 0; i < loca_values.size(); ++i) { | 511 for (size_t i = 0; i < loca_values.size(); ++i) { |
512 uint32_t value = loca_values.at(i); | 512 uint32_t value = loca_values.at(i); |
513 if (index_format) { | 513 if (index_format) { |
514 offset = StoreU32(dst, offset, value); | 514 offset = StoreU32(dst, offset, value); |
515 } else { | 515 } else { |
516 offset = Store16(dst, offset, value >> 1); | 516 offset = StoreU16(dst, offset, static_cast<uint16_t>(value >> 1)); |
517 } | 517 } |
518 } | 518 } |
519 return true; | 519 return true; |
520 } | 520 } |
521 | 521 |
522 // Reconstruct entire glyf table based on transformed original | 522 // Reconstruct entire glyf table based on transformed original |
523 bool ReconstructGlyf(const uint8_t* data, size_t data_size, | 523 bool ReconstructGlyf(const uint8_t* data, size_t data_size, |
524 uint8_t* dst, size_t dst_size, | 524 uint8_t* dst, size_t dst_size, |
525 uint8_t* loca_buf, size_t loca_size) { | 525 uint8_t* loca_buf, size_t loca_size) { |
526 static const int kNumSubStreams = 7; | 526 static const int kNumSubStreams = 7; |
(...skipping 30 matching lines...) Expand all Loading... |
557 ots::Buffer n_points_stream(substreams.at(1).first, substreams.at(1).second); | 557 ots::Buffer n_points_stream(substreams.at(1).first, substreams.at(1).second); |
558 ots::Buffer flag_stream(substreams.at(2).first, substreams.at(2).second); | 558 ots::Buffer flag_stream(substreams.at(2).first, substreams.at(2).second); |
559 ots::Buffer glyph_stream(substreams.at(3).first, substreams.at(3).second); | 559 ots::Buffer glyph_stream(substreams.at(3).first, substreams.at(3).second); |
560 ots::Buffer composite_stream(substreams.at(4).first, substreams.at(4).second); | 560 ots::Buffer composite_stream(substreams.at(4).first, substreams.at(4).second); |
561 ots::Buffer bbox_stream(substreams.at(5).first, substreams.at(5).second); | 561 ots::Buffer bbox_stream(substreams.at(5).first, substreams.at(5).second); |
562 ots::Buffer instruction_stream(substreams.at(6).first, | 562 ots::Buffer instruction_stream(substreams.at(6).first, |
563 substreams.at(6).second); | 563 substreams.at(6).second); |
564 | 564 |
565 std::vector<uint32_t> loca_values; | 565 std::vector<uint32_t> loca_values; |
566 loca_values.reserve(num_glyphs + 1); | 566 loca_values.reserve(num_glyphs + 1); |
567 std::vector<unsigned int> n_points_vec; | 567 std::vector<uint16_t> n_points_vec; |
568 std::vector<Point> points; | 568 std::vector<Point> points; |
569 uint32_t loca_offset = 0; | 569 uint32_t loca_offset = 0; |
570 for (unsigned int i = 0; i < num_glyphs; ++i) { | 570 for (unsigned int i = 0; i < num_glyphs; ++i) { |
571 size_t glyph_size = 0; | 571 size_t glyph_size = 0; |
572 uint16_t n_contours = 0; | 572 uint16_t n_contours = 0; |
573 if (!n_contour_stream.ReadU16(&n_contours)) { | 573 if (!n_contour_stream.ReadU16(&n_contours)) { |
574 return OTS_FAILURE(); | 574 return OTS_FAILURE(); |
575 } | 575 } |
576 uint8_t* glyf_dst = dst + loca_offset; | 576 uint8_t* glyf_dst = dst + loca_offset; |
577 size_t glyf_dst_size = dst_size - loca_offset; | 577 size_t glyf_dst_size = dst_size - loca_offset; |
578 if (n_contours == 0xffff) { | 578 if (n_contours == 0xffff) { |
579 // composite glyph | 579 // composite glyph |
580 bool have_instructions = false; | 580 bool have_instructions = false; |
581 unsigned int instruction_size = 0; | 581 uint16_t instruction_size = 0; |
582 if (!ProcessComposite(&composite_stream, glyf_dst, glyf_dst_size, | 582 if (!ProcessComposite(&composite_stream, glyf_dst, glyf_dst_size, |
583 &glyph_size, &have_instructions)) { | 583 &glyph_size, &have_instructions)) { |
584 return OTS_FAILURE(); | 584 return OTS_FAILURE(); |
585 } | 585 } |
586 if (have_instructions) { | 586 if (have_instructions) { |
587 if (!Read255UShort(&glyph_stream, &instruction_size)) { | 587 if (!Read255UShort(&glyph_stream, &instruction_size)) { |
588 return OTS_FAILURE(); | 588 return OTS_FAILURE(); |
589 } | 589 } |
590 // No integer overflow here (instruction_size < 2^16). | 590 // No integer overflow here (instruction_size < 2^16). |
591 if (instruction_size + 2 > glyf_dst_size - glyph_size) { | 591 if (instruction_size + 2U > glyf_dst_size - glyph_size) { |
592 return OTS_FAILURE(); | 592 return OTS_FAILURE(); |
593 } | 593 } |
594 Store16(glyf_dst, glyph_size, instruction_size); | 594 StoreU16(glyf_dst, glyph_size, instruction_size); |
595 if (!instruction_stream.Read(glyf_dst + glyph_size + 2, | 595 if (!instruction_stream.Read(glyf_dst + glyph_size + 2, |
596 instruction_size)) { | 596 instruction_size)) { |
597 return OTS_FAILURE(); | 597 return OTS_FAILURE(); |
598 } | 598 } |
599 glyph_size += instruction_size + 2; | 599 glyph_size += instruction_size + 2; |
600 } | 600 } |
601 } else if (n_contours > 0) { | 601 } else if (n_contours > 0) { |
602 // simple glyph | 602 // simple glyph |
603 n_points_vec.clear(); | 603 n_points_vec.clear(); |
604 points.clear(); | 604 points.clear(); |
605 unsigned int total_n_points = 0; | 605 uint32_t total_n_points = 0; |
606 unsigned int n_points_contour; | 606 uint16_t n_points_contour; |
607 for (unsigned int j = 0; j < n_contours; ++j) { | 607 for (uint32_t j = 0; j < n_contours; ++j) { |
608 if (!Read255UShort(&n_points_stream, &n_points_contour)) { | 608 if (!Read255UShort(&n_points_stream, &n_points_contour)) { |
609 return OTS_FAILURE(); | 609 return OTS_FAILURE(); |
610 } | 610 } |
611 n_points_vec.push_back(n_points_contour); | 611 n_points_vec.push_back(n_points_contour); |
612 if (total_n_points + n_points_contour < total_n_points) { | 612 if (total_n_points + n_points_contour < total_n_points) { |
613 return OTS_FAILURE(); | 613 return OTS_FAILURE(); |
614 } | 614 } |
615 total_n_points += n_points_contour; | 615 total_n_points += n_points_contour; |
616 } | 616 } |
617 unsigned int flag_size = total_n_points; | 617 uint32_t flag_size = total_n_points; |
618 if (flag_size > flag_stream.length() - flag_stream.offset()) { | 618 if (flag_size > flag_stream.length() - flag_stream.offset()) { |
619 return OTS_FAILURE(); | 619 return OTS_FAILURE(); |
620 } | 620 } |
621 const uint8_t* flags_buf = flag_stream.buffer() + flag_stream.offset(); | 621 const uint8_t* flags_buf = flag_stream.buffer() + flag_stream.offset(); |
622 const uint8_t* triplet_buf = glyph_stream.buffer() + | 622 const uint8_t* triplet_buf = glyph_stream.buffer() + |
623 glyph_stream.offset(); | 623 glyph_stream.offset(); |
624 size_t triplet_size = glyph_stream.length() - glyph_stream.offset(); | 624 size_t triplet_size = glyph_stream.length() - glyph_stream.offset(); |
625 size_t triplet_bytes_consumed = 0; | 625 size_t triplet_bytes_consumed = 0; |
626 if (!TripletDecode(flags_buf, triplet_buf, triplet_size, total_n_points, | 626 if (!TripletDecode(flags_buf, triplet_buf, triplet_size, total_n_points, |
627 &points, &triplet_bytes_consumed)) { | 627 &points, &triplet_bytes_consumed)) { |
628 return OTS_FAILURE(); | 628 return OTS_FAILURE(); |
629 } | 629 } |
630 const uint32_t header_and_endpts_contours_size = | 630 const uint32_t header_and_endpts_contours_size = |
631 kEndPtsOfContoursOffset + 2 * n_contours; | 631 kEndPtsOfContoursOffset + 2 * n_contours; |
632 if (glyf_dst_size < header_and_endpts_contours_size) { | 632 if (glyf_dst_size < header_and_endpts_contours_size) { |
633 return OTS_FAILURE(); | 633 return OTS_FAILURE(); |
634 } | 634 } |
635 Store16(glyf_dst, 0, n_contours); | 635 StoreU16(glyf_dst, 0, n_contours); |
636 ComputeBbox(points, glyf_dst); | 636 ComputeBbox(points, glyf_dst); |
637 size_t offset = kEndPtsOfContoursOffset; | 637 size_t offset = kEndPtsOfContoursOffset; |
638 int end_point = -1; | 638 int end_point = -1; |
639 for (unsigned int contour_ix = 0; contour_ix < n_contours; ++contour_ix) { | 639 for (unsigned int contour_ix = 0; contour_ix < n_contours; ++contour_ix) { |
640 end_point += n_points_vec.at(contour_ix); | 640 end_point += n_points_vec.at(contour_ix); |
641 if (end_point >= 65536) { | 641 if (end_point >= 65536) { |
642 return OTS_FAILURE(); | 642 return OTS_FAILURE(); |
643 } | 643 } |
644 offset = Store16(glyf_dst, offset, end_point); | 644 offset = StoreU16(glyf_dst, offset, static_cast<uint16_t>(end_point)); |
645 } | 645 } |
646 if (!flag_stream.Skip(flag_size)) { | 646 if (!flag_stream.Skip(flag_size)) { |
647 return OTS_FAILURE(); | 647 return OTS_FAILURE(); |
648 } | 648 } |
649 if (!glyph_stream.Skip(triplet_bytes_consumed)) { | 649 if (!glyph_stream.Skip(triplet_bytes_consumed)) { |
650 return OTS_FAILURE(); | 650 return OTS_FAILURE(); |
651 } | 651 } |
652 unsigned int instruction_size; | 652 uint16_t instruction_size; |
653 if (!Read255UShort(&glyph_stream, &instruction_size)) { | 653 if (!Read255UShort(&glyph_stream, &instruction_size)) { |
654 return OTS_FAILURE(); | 654 return OTS_FAILURE(); |
655 } | 655 } |
656 // No integer overflow here (instruction_size < 2^16). | 656 // No integer overflow here (instruction_size < 2^16). |
657 if (glyf_dst_size - header_and_endpts_contours_size < | 657 if (glyf_dst_size - header_and_endpts_contours_size < |
658 instruction_size + 2) { | 658 instruction_size + 2U) { |
659 return OTS_FAILURE(); | 659 return OTS_FAILURE(); |
660 } | 660 } |
661 uint8_t* instruction_dst = glyf_dst + header_and_endpts_contours_size; | 661 uint8_t* instruction_dst = glyf_dst + header_and_endpts_contours_size; |
662 Store16(instruction_dst, 0, instruction_size); | 662 StoreU16(instruction_dst, 0, instruction_size); |
663 if (!instruction_stream.Read(instruction_dst + 2, instruction_size)) { | 663 if (!instruction_stream.Read(instruction_dst + 2, instruction_size)) { |
664 return OTS_FAILURE(); | 664 return OTS_FAILURE(); |
665 } | 665 } |
666 if (!StorePoints(points, n_contours, instruction_size, | 666 if (!StorePoints(points, n_contours, instruction_size, |
667 glyf_dst, glyf_dst_size, &glyph_size)) { | 667 glyf_dst, glyf_dst_size, &glyph_size)) { |
668 return OTS_FAILURE(); | 668 return OTS_FAILURE(); |
669 } | 669 } |
670 } else { | 670 } else { |
671 glyph_size = 0; | 671 glyph_size = 0; |
672 } | 672 } |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
908 std::vector<Table> tables(num_tables); | 908 std::vector<Table> tables(num_tables); |
909 if (!ReadShortDirectory(&file, &tables, num_tables)) { | 909 if (!ReadShortDirectory(&file, &tables, num_tables)) { |
910 return OTS_FAILURE(); | 910 return OTS_FAILURE(); |
911 } | 911 } |
912 uint64_t src_offset = file.offset(); | 912 uint64_t src_offset = file.offset(); |
913 uint64_t dst_offset = kSfntHeaderSize + | 913 uint64_t dst_offset = kSfntHeaderSize + |
914 kSfntEntrySize * static_cast<uint64_t>(num_tables); | 914 kSfntEntrySize * static_cast<uint64_t>(num_tables); |
915 uint64_t uncompressed_sum = 0; | 915 uint64_t uncompressed_sum = 0; |
916 for (uint16_t i = 0; i < num_tables; ++i) { | 916 for (uint16_t i = 0; i < num_tables; ++i) { |
917 Table* table = &tables.at(i); | 917 Table* table = &tables.at(i); |
918 table->src_offset = src_offset; | 918 table->src_offset = static_cast<uint32_t>(src_offset); |
919 table->src_length = (i == 0 ? compressed_length : 0); | 919 table->src_length = (i == 0 ? compressed_length : 0); |
920 src_offset += table->src_length; | 920 src_offset += table->src_length; |
921 if (src_offset > std::numeric_limits<uint32_t>::max()) { | 921 if (src_offset > std::numeric_limits<uint32_t>::max()) { |
922 return OTS_FAILURE(); | 922 return OTS_FAILURE(); |
923 } | 923 } |
924 src_offset = ots::Round4(src_offset); | 924 src_offset = ots::Round4(src_offset); |
925 table->dst_offset = dst_offset; | 925 table->dst_offset = static_cast<uint32_t>(dst_offset); |
926 dst_offset += table->dst_length; | 926 dst_offset += table->dst_length; |
927 if (dst_offset > std::numeric_limits<uint32_t>::max()) { | 927 if (dst_offset > std::numeric_limits<uint32_t>::max()) { |
928 return OTS_FAILURE(); | 928 return OTS_FAILURE(); |
929 } | 929 } |
930 dst_offset = ots::Round4(dst_offset); | 930 dst_offset = ots::Round4(dst_offset); |
931 if ((table->flags & kCompressionTypeMask) != kCompressionTypeNone) { | 931 if ((table->flags & kCompressionTypeMask) != kCompressionTypeNone) { |
932 uncompressed_sum += table->src_length; | 932 uncompressed_sum += table->src_length; |
933 if (uncompressed_sum > std::numeric_limits<uint32_t>::max()) { | 933 if (uncompressed_sum > std::numeric_limits<uint32_t>::max()) { |
934 return OTS_FAILURE(); | 934 return OTS_FAILURE(); |
935 } | 935 } |
936 } | 936 } |
937 } | 937 } |
938 // Enforce same 30M limit on uncompressed tables as OTS | 938 // Enforce same 30M limit on uncompressed tables as OTS |
939 if (uncompressed_sum > 30 * 1024 * 1024) { | 939 if (uncompressed_sum > 30 * 1024 * 1024) { |
940 return OTS_FAILURE(); | 940 return OTS_FAILURE(); |
941 } | 941 } |
942 if (src_offset > length || dst_offset > result_length) { | 942 if (src_offset > length || dst_offset > result_length) { |
943 return OTS_FAILURE(); | 943 return OTS_FAILURE(); |
944 } | 944 } |
945 | 945 |
946 const uint32_t sfnt_header_and_table_directory_size = 12 + 16 * num_tables; | 946 const uint32_t sfnt_header_and_table_directory_size = 12 + 16 * num_tables; |
947 if (sfnt_header_and_table_directory_size > result_length) { | 947 if (sfnt_header_and_table_directory_size > result_length) { |
948 return OTS_FAILURE(); | 948 return OTS_FAILURE(); |
949 } | 949 } |
950 | 950 |
951 // Start building the font | 951 // Start building the font |
952 size_t offset = 0; | 952 size_t offset = 0; |
953 offset = StoreU32(result, offset, flavor); | 953 offset = StoreU32(result, offset, flavor); |
954 offset = Store16(result, offset, num_tables); | 954 offset = StoreU16(result, offset, num_tables); |
955 unsigned max_pow2 = 0; | 955 uint8_t max_pow2 = 0; |
956 while (1u << (max_pow2 + 1) <= num_tables) { | 956 while (1u << (max_pow2 + 1) <= num_tables) { |
957 max_pow2++; | 957 max_pow2++; |
958 } | 958 } |
959 const uint16_t output_search_range = (1u << max_pow2) << 4; | 959 const uint16_t output_search_range = (1u << max_pow2) << 4; |
960 offset = Store16(result, offset, output_search_range); | 960 offset = StoreU16(result, offset, output_search_range); |
961 offset = Store16(result, offset, max_pow2); | 961 offset = StoreU16(result, offset, max_pow2); |
962 offset = Store16(result, offset, (num_tables << 4) - output_search_range); | 962 offset = StoreU16(result, offset, (num_tables << 4) - output_search_range); |
963 for (uint16_t i = 0; i < num_tables; ++i) { | 963 for (uint16_t i = 0; i < num_tables; ++i) { |
964 const Table* table = &tables.at(i); | 964 const Table* table = &tables.at(i); |
965 offset = StoreU32(result, offset, table->tag); | 965 offset = StoreU32(result, offset, table->tag); |
966 offset = StoreU32(result, offset, 0); // checksum, to fill in later | 966 offset = StoreU32(result, offset, 0); // checksum, to fill in later |
967 offset = StoreU32(result, offset, table->dst_offset); | 967 offset = StoreU32(result, offset, table->dst_offset); |
968 offset = StoreU32(result, offset, table->dst_length); | 968 offset = StoreU32(result, offset, table->dst_length); |
969 } | 969 } |
970 std::vector<uint8_t> uncompressed_buf; | 970 std::vector<uint8_t> uncompressed_buf; |
971 bool continue_valid = false; | 971 bool continue_valid = false; |
972 const uint8_t* transform_buf = NULL; | 972 const uint8_t* transform_buf = NULL; |
(...skipping 21 matching lines...) Expand all Loading... |
994 } | 994 } |
995 total_size += tables.at(j).transform_length; | 995 total_size += tables.at(j).transform_length; |
996 if (total_size > std::numeric_limits<uint32_t>::max()) { | 996 if (total_size > std::numeric_limits<uint32_t>::max()) { |
997 return OTS_FAILURE(); | 997 return OTS_FAILURE(); |
998 } | 998 } |
999 } | 999 } |
1000 // Enforce same 30M limit on uncompressed tables as OTS | 1000 // Enforce same 30M limit on uncompressed tables as OTS |
1001 if (total_size > 30 * 1024 * 1024) { | 1001 if (total_size > 30 * 1024 * 1024) { |
1002 return OTS_FAILURE(); | 1002 return OTS_FAILURE(); |
1003 } | 1003 } |
1004 uncompressed_buf.resize(total_size); | 1004 const size_t total_size_size_t = static_cast<size_t>(total_size); |
1005 if (!Woff2Uncompress(&uncompressed_buf[0], total_size, | 1005 uncompressed_buf.resize(total_size_size_t); |
| 1006 if (!Woff2Uncompress(&uncompressed_buf[0], total_size_size_t, |
1006 src_buf, compressed_length, compression_type)) { | 1007 src_buf, compressed_length, compression_type)) { |
1007 return OTS_FAILURE(); | 1008 return OTS_FAILURE(); |
1008 } | 1009 } |
1009 transform_buf = &uncompressed_buf[0]; | 1010 transform_buf = &uncompressed_buf[0]; |
1010 continue_valid = true; | 1011 continue_valid = true; |
1011 } else { | 1012 } else { |
1012 return OTS_FAILURE(); | 1013 return OTS_FAILURE(); |
1013 } | 1014 } |
1014 | 1015 |
1015 if ((flags & kWoff2FlagsTransform) == 0) { | 1016 if ((flags & kWoff2FlagsTransform) == 0) { |
(...skipping 17 matching lines...) Expand all Loading... |
1033 if (transform_buf > &uncompressed_buf[0] + uncompressed_buf.size()) { | 1034 if (transform_buf > &uncompressed_buf[0] + uncompressed_buf.size()) { |
1034 return OTS_FAILURE(); | 1035 return OTS_FAILURE(); |
1035 } | 1036 } |
1036 } | 1037 } |
1037 } | 1038 } |
1038 | 1039 |
1039 return FixChecksums(tables, result); | 1040 return FixChecksums(tables, result); |
1040 } | 1041 } |
1041 | 1042 |
1042 } // namespace ots | 1043 } // namespace ots |
OLD | NEW |