@@ -70,6 +70,10 @@ const size_t kCompositeGlyphBegin = 10; |
70 | 70 | // Largest glyph ever observed was 72k bytes |
71 | 71 | const size_t kDefaultGlyphBuf = 5120; |
72 | 72 |
|
| 73 | +// Over 14k test fonts the max compression ratio seen to date was ~20. |
| 74 | +// >100 suggests you wrote a bad uncompressed size. |
| 75 | +const float kMaxPlausibleCompressionRatio = 100.0; |
| 76 | + |
73 | 77 | // metadata for a TTC font entry |
74 | 78 | struct TtcFont { |
75 | 79 | uint32_t flavor; |
@@ -478,7 +482,7 @@ bool ReconstructGlyf(const uint8_t* data, Table* glyf_table, |
478 | 482 | } |
479 | 483 | } |
480 | 484 |
|
481 | | - size_t size_needed = 2 + composite_size + instruction_size; |
| 485 | + size_t size_needed = 12 + composite_size + instruction_size; |
482 | 486 | if (PREDICT_FALSE(glyph_buf_size < size_needed)) { |
483 | 487 | glyph_buf.reset(new uint8_t[size_needed]); |
484 | 488 | glyph_buf_size = size_needed; |
@@ -672,6 +676,11 @@ bool ReconstructTransformedHmtx(const uint8_t* transformed_buf, |
672 | 676 |
|
673 | 677 | assert(x_mins.size() == num_glyphs); |
674 | 678 |
|
| 679 | + // num_glyphs 0 is OK if there is no 'glyf' but cannot then xform 'hmtx'. |
| 680 | + if (PREDICT_FALSE(num_hmetrics > num_glyphs)) { |
| 681 | + return FONT_COMPRESSION_FAILURE(); |
| 682 | + } |
| 683 | + |
675 | 684 | for (uint16_t i = 0; i < num_hmetrics; i++) { |
676 | 685 | uint16_t advance_width; |
677 | 686 | if (PREDICT_FALSE(!hmtx_buff_in.ReadU16(&advance_width))) { |
@@ -1270,6 +1279,14 @@ bool ConvertWOFF2ToTTF(const uint8_t* data, size_t length, |
1270 | 1279 | return FONT_COMPRESSION_FAILURE(); |
1271 | 1280 | } |
1272 | 1281 |
|
| 1282 | + const float compression_ratio = (float) hdr.uncompressed_size / length; |
| 1283 | + if (compression_ratio > kMaxPlausibleCompressionRatio) { |
| 1284 | +#ifdef FONT_COMPRESSION_BIN |
| 1285 | + fprintf(stderr, "Implausible compression ratio %.01f\n", compression_ratio); |
| 1286 | +#endif |
| 1287 | + return FONT_COMPRESSION_FAILURE(); |
| 1288 | + } |
| 1289 | + |
1273 | 1290 | const uint8_t* src_buf = data + hdr.compressed_offset; |
1274 | 1291 | std::vector<uint8_t> uncompressed_buf(hdr.uncompressed_size); |
1275 | 1292 | if (PREDICT_FALSE(!Woff2Uncompress(&uncompressed_buf[0], |
|