From 90603761c764febab246c315ff782d8981d9770e Mon Sep 17 00:00:00 2001 From: Rod Sheeter Date: Thu, 9 Apr 2015 07:47:55 -0700 Subject: [PATCH] Mark as transformed. Correct how table records were used by font.cc when writing collections. --- src/font.cc | 29 +++++++++++++++++++++-------- src/normalize.cc | 46 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/src/font.cc b/src/font.cc index ee34c43..5b4bbe6 100644 --- a/src/font.cc +++ b/src/font.cc @@ -223,20 +223,33 @@ bool WriteFont(const Font& font, uint8_t* dst, size_t dst_size) { return WriteFont(font, &offset, dst, dst_size); } +bool WriteTableRecord(const Font::Table* table, size_t* offset, uint8_t* dst, + size_t dst_size) { + if (dst_size < *offset + kSfntEntrySize) { + return FONT_COMPRESSION_FAILURE(); + } + if (table->IsReused()) { + table = table->reuse_of; + } + StoreU32(table->tag, offset, dst); + StoreU32(table->checksum, offset, dst); + StoreU32(table->offset, offset, dst); + StoreU32(table->length, offset, dst); + return true; +} + bool WriteTable(const Font::Table& table, size_t* offset, uint8_t* dst, size_t dst_size) { - StoreU32(table.tag, offset, dst); - StoreU32(table.checksum, offset, dst); - StoreU32(table.offset, offset, dst); - StoreU32(table.length, offset, dst); - - if (table.offset + table.length < table.offset || - dst_size < table.offset + table.length) { - return FONT_COMPRESSION_FAILURE(); + if (!WriteTableRecord(&table, offset, dst, dst_size)) { + return false; } // Write the actual table data if it's the first time we've seen it if (!table.IsReused()) { + if (table.offset + table.length < table.offset || + dst_size < table.offset + table.length) { + return FONT_COMPRESSION_FAILURE(); + } memcpy(dst + table.offset, table.data, table.length); size_t padding_size = (4 - (table.length & 3)) & 3; if (table.offset + table.length + padding_size < padding_size || diff --git a/src/normalize.cc b/src/normalize.cc index 36a4538..c633b3f 100644 --- a/src/normalize.cc +++ b/src/normalize.cc @@ -215,10 +215,14 @@ uint32_t ComputeHeaderChecksum(const Font& font) { checksum += (font.num_tables << 16 | search_range); checksum += (max_pow2 << 16 | range_shift); for (const auto& i : font.tables) { - checksum += i.second.tag; - checksum += i.second.checksum; - checksum += i.second.offset; - checksum += i.second.length; + const Font::Table* table = &i.second; + if (table->IsReused()) { + table = table->reuse_of; + } + checksum += table->tag; + checksum += table->checksum; + checksum += table->offset; + checksum += table->length; } return checksum; } @@ -227,16 +231,21 @@ uint32_t ComputeHeaderChecksum(const Font& font) { bool FixChecksums(Font* font) { Font::Table* head_table = font->FindTable(kHeadTableTag); + if (head_table == NULL) { + return FONT_COMPRESSION_FAILURE(); + } if (head_table->reuse_of != NULL) { head_table = head_table->reuse_of; } - if (head_table == NULL || head_table->length < 12) { + if (head_table->length < 12) { return FONT_COMPRESSION_FAILURE(); } + uint8_t* head_buf = &head_table->buffer[0]; size_t offset = 8; StoreU32(0, &offset, head_buf); uint32_t file_checksum = 0; + uint32_t head_checksum = 0; for (auto& i : font->tables) { Font::Table* table = &i.second; if (table->IsReused()) { @@ -244,17 +253,44 @@ bool FixChecksums(Font* font) { } table->checksum = ComputeULongSum(table->data, table->length); file_checksum += table->checksum; + + if (table->tag == kHeadTableTag) { + head_checksum = table->checksum; + } } file_checksum += ComputeHeaderChecksum(*font); offset = 8; StoreU32(0xb1b0afba - file_checksum, &offset, head_buf); + return true; } +namespace { +bool MarkTransformed(Font* font) { + Font::Table* head_table = font->FindTable(kHeadTableTag); + if (head_table == NULL) { + return FONT_COMPRESSION_FAILURE(); + } + if (head_table->reuse_of != NULL) { + head_table = head_table->reuse_of; + } + if (head_table->length < 17) { + return FONT_COMPRESSION_FAILURE(); + } + // set bit 11 of head table 'flags' to indicate that font has undergone + // lossless modifying transform + int head_flags = head_table->data[16]; + head_table->buffer[16] = head_flags | 0x08; + return true; +} +} // namespace + + bool NormalizeWithoutFixingChecksums(Font* font) { return (MakeEditableBuffer(font, kHeadTableTag) && RemoveDigitalSignature(font) && + MarkTransformed(font) && NormalizeGlyphs(font) && NormalizeOffsets(font)); }