summaryrefslogtreecommitdiffstats
path: root/modules/woff2/src/woff2_dec.cc
diff options
context:
space:
mode:
Diffstat (limited to 'modules/woff2/src/woff2_dec.cc')
-rw-r--r--modules/woff2/src/woff2_dec.cc111
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))) {