diff options
Diffstat (limited to 'modules/woff2/src/woff2_dec.cc')
-rw-r--r-- | modules/woff2/src/woff2_dec.cc | 111 |
1 files changed, 71 insertions, 40 deletions
diff --git a/modules/woff2/src/woff2_dec.cc b/modules/woff2/src/woff2_dec.cc index 97b869fe6..8186c8e5d 100644 --- a/modules/woff2/src/woff2_dec.cc +++ b/modules/woff2/src/woff2_dec.cc @@ -1,20 +1,12 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Library for converting WOFF2 format font files to their TTF versions. - -#include "./woff2_dec.h" +/* Copyright 2014 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Library for converting WOFF2 format font files to their TTF versions. */ + +#include <woff2/decode.h> #include <stdlib.h> #include <algorithm> @@ -27,16 +19,7 @@ #include <memory> #include <utility> -#include "mozilla/UniquePtr.h" -namespace std -{ - using mozilla::DefaultDelete; - using mozilla::UniquePtr; - #define default_delete DefaultDelete - #define unique_ptr UniquePtr -} - -#include "./decode.h" +#include <brotli/decode.h> #include "./buffer.h" #include "./port.h" #include "./round.h" @@ -420,6 +403,14 @@ bool ReconstructGlyf(const uint8_t* data, Table* glyf_table, return FONT_COMPRESSION_FAILURE(); } + // https://dev.w3.org/webfonts/WOFF2/spec/#conform-mustRejectLoca + // dst_length here is origLength in the spec + uint32_t expected_loca_dst_length = (info->index_format ? 4 : 2) + * (static_cast<uint32_t>(info->num_glyphs) + 1); + if (PREDICT_FALSE(loca_table->dst_length != expected_loca_dst_length)) { + return FONT_COMPRESSION_FAILURE(); + } + unsigned int offset = (2 + kNumSubStreams) * 4; if (PREDICT_FALSE(offset > glyf_table->transform_length)) { return FONT_COMPRESSION_FAILURE(); @@ -601,6 +592,14 @@ bool ReconstructGlyf(const uint8_t* data, Table* glyf_table, instruction_size, glyph_buf.get(), glyph_buf_size, &glyph_size))) { return FONT_COMPRESSION_FAILURE(); } + } else { + // n_contours == 0; empty glyph. Must NOT have a bbox. + if (PREDICT_FALSE(have_bbox)) { +#ifdef FONT_COMPRESSION_BIN + fprintf(stderr, "Empty glyph has a bbox\n"); +#endif + return FONT_COMPRESSION_FAILURE(); + } } loca_values[i] = out->Size() - glyf_start; @@ -678,6 +677,14 @@ bool ReconstructTransformedHmtx(const uint8_t* transformed_buf, bool has_proportional_lsbs = (hmtx_flags & 1) == 0; bool has_monospace_lsbs = (hmtx_flags & 2) == 0; + // Bits 2-7 are reserved and MUST be zero. + if ((hmtx_flags & 0xFC) != 0) { +#ifdef FONT_COMPRESSION_BIN + fprintf(stderr, "Illegal hmtx flags; bits 2-7 must be 0\n"); +#endif + return FONT_COMPRESSION_FAILURE(); + } + // you say you transformed but there is little evidence of it if (has_proportional_lsbs && has_monospace_lsbs) { return FONT_COMPRESSION_FAILURE(); @@ -751,9 +758,10 @@ bool ReconstructTransformedHmtx(const uint8_t* transformed_buf, bool Woff2Uncompress(uint8_t* dst_buf, size_t dst_size, const uint8_t* src_buf, size_t src_size) { size_t uncompressed_size = dst_size; - int ok = BrotliDecompressBuffer(src_size, src_buf, - &uncompressed_size, dst_buf); - if (PREDICT_FALSE(!ok || uncompressed_size != dst_size)) { + BrotliDecoderResult result = BrotliDecoderDecompress( + src_size, src_buf, &uncompressed_size, dst_buf); + if (PREDICT_FALSE(result != BROTLI_DECODER_RESULT_SUCCESS || + uncompressed_size != dst_size)) { return FONT_COMPRESSION_FAILURE(); } return true; @@ -884,11 +892,26 @@ bool ReconstructFont(uint8_t* transformed_buf, std::vector<Table*> tables = Tables(hdr, font_index); // 'glyf' without 'loca' doesn't make sense - if (PREDICT_FALSE(static_cast<bool>(FindTable(&tables, kGlyfTableTag)) != - static_cast<bool>(FindTable(&tables, kLocaTableTag)))) { + const Table* glyf_table = FindTable(&tables, kGlyfTableTag); + const Table* loca_table = FindTable(&tables, kLocaTableTag); + if (PREDICT_FALSE(static_cast<bool>(glyf_table) != + static_cast<bool>(loca_table))) { +#ifdef FONT_COMPRESSION_BIN + fprintf(stderr, "Cannot have just one of glyf/loca\n"); +#endif return FONT_COMPRESSION_FAILURE(); } + if (glyf_table != NULL) { + if (PREDICT_FALSE((glyf_table->flags & kWoff2FlagsTransform) + != (loca_table->flags & kWoff2FlagsTransform))) { +#ifdef FONT_COMPRESSION_BIN + fprintf(stderr, "Cannot transform just one of glyf/loca\n"); +#endif + return FONT_COMPRESSION_FAILURE(); + } + } + uint32_t font_checksum = metadata->header_checksum; if (hdr->header_version) { font_checksum = hdr->ttc_fonts[font_index].header_checksum; @@ -907,7 +930,7 @@ bool ReconstructFont(uint8_t* transformed_buf, // TODO(user) a collection with optimized hmtx that reused glyf/loca // would fail. We don't optimize hmtx for collections yet. - if (PREDICT_FALSE(static_cast<uint64_t>(table.src_offset + table.src_length) + if (PREDICT_FALSE(static_cast<uint64_t>(table.src_offset) + table.src_length > transformed_buf_size)) { return FONT_COMPRESSION_FAILURE(); } @@ -1108,8 +1131,9 @@ bool ReadWOFF2Header(const uint8_t* data, size_t length, WOFF2Header* hdr) { ttc_font.table_indices.resize(num_tables); - const Table* glyf_table = NULL; - const Table* loca_table = NULL; + + unsigned int glyf_idx = 0; + unsigned int loca_idx = 0; for (uint32_t j = 0; j < num_tables; j++) { unsigned int table_idx; @@ -1121,19 +1145,23 @@ bool ReadWOFF2Header(const uint8_t* data, size_t length, WOFF2Header* hdr) { const Table& table = hdr->tables[table_idx]; if (table.tag == kLocaTableTag) { - loca_table = &table; + loca_idx = table_idx; } if (table.tag == kGlyfTableTag) { - glyf_table = &table; + glyf_idx = table_idx; } } - if (PREDICT_FALSE((glyf_table == NULL) != (loca_table == NULL))) { + // if we have both glyf and loca make sure they are consecutive + // if we have just one we'll reject the font elsewhere + if (glyf_idx > 0 || loca_idx > 0) { + if (PREDICT_FALSE(glyf_idx > loca_idx || loca_idx - glyf_idx != 1)) { #ifdef FONT_COMPRESSION_BIN - fprintf(stderr, "Cannot have just one of glyf/loca\n"); + fprintf(stderr, "TTC font %d has non-consecutive glyf/loca\n", i); #endif - return FONT_COMPRESSION_FAILURE(); + return FONT_COMPRESSION_FAILURE(); + } } } } @@ -1307,6 +1335,9 @@ bool ConvertWOFF2ToTTF(const uint8_t* data, size_t length, const uint8_t* src_buf = data + hdr.compressed_offset; std::vector<uint8_t> 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))) { |