diff --git a/src/woff2_dec.cc b/src/woff2_dec.cc
index e202672..7740a5d 100644
--- a/src/woff2_dec.cc
+++ b/src/woff2_dec.cc
@@ -720,6 +720,9 @@ bool ReadTableDirectory(Buffer* file, std::vector
* tables,
if (!ReadBase128(file, &transform_length)) {
return FONT_COMPRESSION_FAILURE();
}
+ if (tag == kLocaTableTag && transform_length) {
+ return FONT_COMPRESSION_FAILURE();
+ }
}
table->tag = tag;
table->flags = flags;
@@ -807,7 +810,7 @@ bool ConvertWOFF2ToTTF(uint8_t* result, size_t result_length,
}
// We don't care about these fields of the header:
// uint16_t reserved
- // uint32_t total_sfnt_size
+ // uint32_t total_sfnt_size, the caller already passes it as result_length
if (!file.Skip(6)) {
return FONT_COMPRESSION_FAILURE();
}
@@ -817,11 +820,33 @@ bool ConvertWOFF2ToTTF(uint8_t* result, size_t result_length,
}
// We don't care about these fields of the header:
// uint16_t major_version, minor_version
- // uint32_t meta_offset, meta_length, meta_orig_length
- // uint32_t priv_offset, priv_length
- if (!file.Skip(24)) {
+ if (!file.Skip(2 * 2)) {
return FONT_COMPRESSION_FAILURE();
}
+ uint32_t meta_offset;
+ uint32_t meta_length;
+ uint32_t meta_length_orig;
+ if (!file.ReadU32(&meta_offset) ||
+ !file.ReadU32(&meta_length) ||
+ !file.ReadU32(&meta_length_orig)) {
+ return FONT_COMPRESSION_FAILURE();
+ }
+ if (meta_offset) {
+ if (meta_offset >= length || length - meta_offset < meta_length) {
+ return FONT_COMPRESSION_FAILURE();
+ }
+ }
+ uint32_t priv_offset;
+ uint32_t priv_length;
+ if (!file.ReadU32(&priv_offset) ||
+ !file.ReadU32(&priv_length)) {
+ return FONT_COMPRESSION_FAILURE();
+ }
+ if (priv_offset) {
+ if (priv_offset >= length || length - priv_offset < priv_length) {
+ return FONT_COMPRESSION_FAILURE();
+ }
+ }
std::vector tables(num_tables);
if (!ReadTableDirectory(&file, &tables, num_tables)) {
return FONT_COMPRESSION_FAILURE();
@@ -926,7 +951,7 @@ bool ConvertWOFF2ToTTF(uint8_t* result, size_t result_length,
if (uncompressed_sum > 30 * 1024 * 1024) {
return FONT_COMPRESSION_FAILURE();
}
- if (src_offset > length || dst_offset > result_length) {
+ if (src_offset > length || dst_offset != result_length) {
fprintf(stderr, "offset fail; src_offset %lu length %lu "
"dst_offset %lu result_length %lu\n",
src_offset, length, dst_offset, result_length);
@@ -951,6 +976,30 @@ bool ConvertWOFF2ToTTF(uint8_t* result, size_t result_length,
std::sort(tables.begin(), tables.end());
}
+ if (meta_offset) {
+ if (src_offset != meta_offset) {
+ return FONT_COMPRESSION_FAILURE();
+ }
+ src_offset = Round4(meta_offset + meta_length);
+ if (src_offset > std::numeric_limits::max()) {
+ return FONT_COMPRESSION_FAILURE();
+ }
+ }
+
+ if (priv_offset) {
+ if (src_offset != priv_offset) {
+ return FONT_COMPRESSION_FAILURE();
+ }
+ src_offset = Round4(priv_offset + priv_length);
+ if (src_offset > std::numeric_limits::max()) {
+ return FONT_COMPRESSION_FAILURE();
+ }
+ }
+
+ if (src_offset != Round4(length)) {
+ return FONT_COMPRESSION_FAILURE();
+ }
+
// Start building the font
size_t offset = 0;
size_t offset_table = 0;