diff --git a/src/font.cc b/src/font.cc index fc496e0..8dc1043 100644 --- a/src/font.cc +++ b/src/font.cc @@ -331,8 +331,11 @@ int NumGlyphs(const Font& font) { return 0; } int index_fmt = IndexFormat(font); - int num_glyphs = (loca_table->length / (index_fmt == 0 ? 2 : 4)) - 1; - return num_glyphs; + int loca_record_size = (index_fmt == 0 ? 2 : 4); + if (loca_table->length < loca_record_size) { + return 0; + } + return (loca_table->length / loca_record_size) - 1; } int IndexFormat(const Font& font) { diff --git a/src/normalize.cc b/src/normalize.cc index b538b91..1af3b7d 100644 --- a/src/normalize.cc +++ b/src/normalize.cc @@ -52,7 +52,7 @@ bool WriteNormalizedLoca(int index_fmt, int num_glyphs, Font* font) { loca_table->buffer.resize(Round4(num_glyphs + 1) * glyph_sz); loca_table->length = (num_glyphs + 1) * glyph_sz; - uint8_t* glyf_dst = &glyf_table->buffer[0]; + uint8_t* glyf_dst = num_glyphs ? &glyf_table->buffer[0] : NULL; uint8_t* loca_dst = &loca_table->buffer[0]; uint32_t glyf_offset = 0; size_t loca_offset = 0; @@ -78,16 +78,13 @@ bool WriteNormalizedLoca(int index_fmt, int num_glyphs, Font* font) { } glyf_offset += glyf_dst_size; } - if (glyf_offset == 0) { - return false; - } StoreLoca(index_fmt, glyf_offset, &loca_offset, loca_dst); glyf_table->buffer.resize(glyf_offset); - glyf_table->data = &glyf_table->buffer[0]; + glyf_table->data = glyf_offset ? &glyf_table->buffer[0] : NULL; glyf_table->length = glyf_offset; - loca_table->data = &loca_table->buffer[0]; + loca_table->data = loca_offset ? &loca_table->buffer[0] : NULL; return true; } diff --git a/src/port.h b/src/port.h index bac47a9..b302d6c 100644 --- a/src/port.h +++ b/src/port.h @@ -60,4 +60,15 @@ inline int Log2Floor(uint32 n) { #define PREDICT_TRUE(x) (x) #endif +#if (defined(__ARM_ARCH) && (__ARM_ARCH == 7)) || \ + (defined(M_ARM) && (M_ARM == 7)) || \ + defined(__aarch64__) || defined(__ARM64_ARCH_8__) || defined(__i386) || \ + defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#define WOFF_LITTLE_ENDIAN +#elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +#define WOFF_BIG_ENDIAN +#endif /* endianness */ +#endif /* CPU whitelist */ + #endif // WOFF2_PORT_H_ diff --git a/src/store_bytes.h b/src/store_bytes.h index 74b279c..82c1bd8 100644 --- a/src/store_bytes.h +++ b/src/store_bytes.h @@ -22,6 +22,8 @@ #include #include +#include "./port.h" + namespace woff2 { inline size_t StoreU32(uint8_t* dst, size_t offset, uint32_t x) { @@ -33,10 +35,10 @@ inline size_t StoreU32(uint8_t* dst, size_t offset, uint32_t x) { } inline size_t Store16(uint8_t* dst, size_t offset, int x) { -#if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) +#if defined(WOFF_LITTLE_ENDIAN) *reinterpret_cast(dst + offset) = ((x & 0xFF) << 8) | ((x & 0xFF00) >> 8); -#elif (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) +#elif defined(WOFF_BIG_ENDIAN) *reinterpret_cast(dst + offset) = static_cast(x); #else dst[offset] = x >> 8; @@ -53,11 +55,11 @@ inline void StoreU32(uint32_t val, size_t* offset, uint8_t* dst) { } inline void Store16(int val, size_t* offset, uint8_t* dst) { -#if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) +#if defined(WOFF_LITTLE_ENDIAN) *reinterpret_cast(dst + *offset) = ((val & 0xFF) << 8) | ((val & 0xFF00) >> 8); *offset += 2; -#elif (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) +#elif defined(WOFF_BIG_ENDIAN) *reinterpret_cast(dst + *offset) = static_cast(val); *offset += 2; #else diff --git a/src/woff2_common.cc b/src/woff2_common.cc index eba6a46..c19acdb 100644 --- a/src/woff2_common.cc +++ b/src/woff2_common.cc @@ -18,6 +18,8 @@ #include "./woff2_common.h" +#include "./port.h" + namespace woff2 { @@ -25,11 +27,11 @@ uint32_t ComputeULongSum(const uint8_t* buf, size_t size) { uint32_t checksum = 0; size_t aligned_size = size & ~3; for (size_t i = 0; i < aligned_size; i += 4) { -#if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) +#if defined(WOFF_LITTLE_ENDIAN) uint32_t v = *reinterpret_cast(buf + i); checksum += (((v & 0xFF) << 24) | ((v & 0xFF00) << 8) | ((v & 0xFF0000) >> 8) | ((v & 0xFF000000) >> 24)); -#elif (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) +#elif defined(WOFF_BIG_ENDIAN) checksum += *reinterpret_cast(buf + i); #else checksum += (buf[i] << 24) | (buf[i + 1] << 16) | diff --git a/src/woff2_dec.cc b/src/woff2_dec.cc index ee85fad..d07e2ed 100644 --- a/src/woff2_dec.cc +++ b/src/woff2_dec.cc @@ -1299,6 +1299,9 @@ bool ConvertWOFF2ToTTF(const uint8_t* data, size_t length, const uint8_t* src_buf = data + hdr.compressed_offset; std::vector uncompressed_buf(hdr.uncompressed_size); + if (PREDICT_FALSE(hdr.uncompressed_size < 1)) { + return FONT_COMPRESSION_FAILURE(); + } if (PREDICT_FALSE(!Woff2Uncompress(&uncompressed_buf[0], hdr.uncompressed_size, src_buf, hdr.compressed_length))) { diff --git a/src/woff2_enc.cc b/src/woff2_enc.cc index bc5238f..4e83a67 100644 --- a/src/woff2_enc.cc +++ b/src/woff2_enc.cc @@ -34,7 +34,6 @@ #include "./variable_length.h" #include "./woff2_common.h" - namespace woff2 { namespace { @@ -106,7 +105,8 @@ size_t TableEntrySize(const Table& table) { size_t ComputeWoff2Length(const FontCollection& font_collection, const std::vector& tables, - std::map index_by_offset, + std::map, uint16_t> + index_by_tag_offset, size_t compressed_data_length, size_t extended_metadata_length) { size_t size = kWoff2HeaderSize; @@ -129,7 +129,8 @@ size_t ComputeWoff2Length(const FontCollection& font_collection, // no collection entry for xform table if (table.tag & 0x80808080) continue; - uint16_t table_index = index_by_offset[table.offset]; + std::pair tag_offset(table.tag, table.offset); + uint16_t table_index = index_by_tag_offset[tag_offset]; size += Size255UShort(table_index); // 255UInt16 index entry } } @@ -321,7 +322,7 @@ bool ConvertTTFToWOFF2(const uint8_t *data, size_t length, } std::vector
tables; - std::map index_by_offset; + std::map, uint16_t> index_by_tag_offset; for (const auto& font : font_collection.fonts) { @@ -331,8 +332,9 @@ bool ConvertTTFToWOFF2(const uint8_t *data, size_t length, continue; } - if (index_by_offset.find(src_table.offset) == index_by_offset.end()) { - index_by_offset[src_table.offset] = tables.size(); + std::pair tag_offset(src_table.tag, src_table.offset); + if (index_by_tag_offset.find(tag_offset) == index_by_tag_offset.end()) { + index_by_tag_offset[tag_offset] = tables.size(); } else { return false; } @@ -357,7 +359,8 @@ bool ConvertTTFToWOFF2(const uint8_t *data, size_t length, } size_t woff2_length = ComputeWoff2Length(font_collection, tables, - index_by_offset, total_compressed_length, compressed_metadata_buf_length); + index_by_tag_offset, total_compressed_length, + compressed_metadata_buf_length); if (woff2_length > *result_length) { #ifdef FONT_COMPRESSION_BIN fprintf(stderr, "Result allocation was too small (%zd vs %zd bytes).\n", @@ -430,14 +433,15 @@ bool ConvertTTFToWOFF2(const uint8_t *data, size_t length, table.IsReused() ? table.reuse_of->offset : table.offset; uint32_t table_length = table.IsReused() ? table.reuse_of->length : table.length; - if (index_by_offset.find(table_offset) == index_by_offset.end()) { + std::pair tag_offset(table.tag, table_offset); + if (index_by_tag_offset.find(tag_offset) == index_by_tag_offset.end()) { #ifdef FONT_COMPRESSION_BIN fprintf(stderr, "Missing table index for offset 0x%08x\n", table_offset); #endif return FONT_COMPRESSION_FAILURE(); } - uint16_t index = index_by_offset[table_offset]; + uint16_t index = index_by_tag_offset[tag_offset]; Store255UShort(index, &offset, result); }