Bug 1074223 - Update OTS to pick up fixes for upstream issues 35, 37. Current rev: c24a839b1c66c4de09e58fabaacb82bf3bd692a4. r=jdaggett

This commit is contained in:
Jonathan Kew 2014-10-09 08:43:30 +01:00
parent c26c3eecbe
commit b9a1569585
22 changed files with 244 additions and 143 deletions

View File

@ -2,10 +2,11 @@ This is the Sanitiser for OpenType project, from http://code.google.com/p/ots/.
Our reference repository is https://github.com/khaledhosny/ots/.
Current revision: 5c25bdac8f02080f49fa416ea997ed77e3be0d30
Current revision: c24a839b1c66c4de09e58fabaacb82bf3bd692a4
Upstream files included: LICENSE, src/, include/
Additional files: README.mozilla, src/moz.build
Additional patch: ots-visibility.patch (bug 711079).
Additional patch: ots-brotli-path.patch (bug 1064737).

View File

@ -227,7 +227,10 @@ class OTS_API OTSContext {
bool Process(OTSStream *output, const uint8_t *input, size_t length);
// This function will be called when OTS is reporting an error.
virtual void Message(const char *format, ...) MSGFUNC_FMT_ATTR {}
// level: the severity of the generated message:
// 0: error messages in case OTS fails to sanitize the font.
// 1: warning messages about issue OTS fixed in the sanitized font.
virtual void Message(int level, const char *format, ...) MSGFUNC_FMT_ATTR {}
// This function will be called when OTS needs to decide what to do for a
// font table.
@ -236,6 +239,9 @@ class OTS_API OTSContext {
virtual TableAction GetTableAction(uint32_t tag) { return ots::TABLE_ACTION_DEFAULT; }
};
// For backward compatibility - remove once Chrome switches over to the new API.
bool Process(OTSStream *output, const uint8_t *input, size_t length);
// Force to disable debug output even when the library is compiled with
// -DOTS_DEBUG.
void DisableDebugOutput();

View File

@ -0,0 +1,22 @@
diff --git a/gfx/ots/src/woff2.cc b/gfx/ots/src/woff2.cc
--- a/gfx/ots/src/woff2.cc
+++ b/gfx/ots/src/woff2.cc
@@ -6,17 +6,17 @@
// Condensed file format.
#include <cassert>
#include <cstdlib>
#include <vector>
#include <zlib.h>
-#include "third_party/brotli/src/brotli/dec/decode.h"
+#include "decode.h"
#include "opentype-sanitiser.h"
#include "ots-memory-stream.h"
#include "ots.h"
#include "woff2.h"
namespace {

View File

@ -37,7 +37,7 @@ diff --git a/gfx/ots/include/opentype-sanitiser.h b/gfx/ots/include/opentype-san
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned int uint32_t;
@@ -187,17 +187,17 @@ class OTSStream {
@@ -187,17 +207,17 @@ class OTSStream {
enum TableAction {
TABLE_ACTION_DEFAULT, // Use OTS's default action for that table
@ -56,3 +56,18 @@ diff --git a/gfx/ots/include/opentype-sanitiser.h b/gfx/ots/include/opentype-san
// output: a pointer to an object implementing the OTSStream interface. The
// sanitisied output will be written to this. In the even of a failure,
// partial output may have been written.
@@ -222,13 +242,13 @@ class OTSContext {
// For backward compatibility - remove once Chrome switches over to the new API.
bool Process(OTSStream *output, const uint8_t *input, size_t length);
// Force to disable debug output even when the library is compiled with
// -DOTS_DEBUG.
void DisableDebugOutput();
// Enable WOFF2 support(experimental).
-void EnableWOFF2();
+void OTS_API EnableWOFF2();
} // namespace ots
#endif // OPENTYPE_SANITISER_H_

View File

@ -462,7 +462,7 @@ bool ParsePrivateDictData(
}
bool ParseDictData(const uint8_t *data, size_t table_length,
const ots::CFFIndex &index, size_t glyphs,
const ots::CFFIndex &index, uint16_t glyphs,
size_t sid_max, DICT_DATA_TYPE type,
ots::OpenTypeCFF *out_cff) {
for (unsigned i = 1; i < index.offsets.size(); ++i) {
@ -476,7 +476,7 @@ bool ParseDictData(const uint8_t *data, size_t table_length,
FONT_FORMAT font_format = FORMAT_UNKNOWN;
bool have_ros = false;
size_t charstring_glyphs = 0;
uint16_t charstring_glyphs = 0;
size_t charset_offset = 0;
while (table.offset() < dict_length) {
@ -700,7 +700,7 @@ bool ParseDictData(const uint8_t *data, size_t table_length,
return OTS_FAILURE();
}
if (format == 0) {
for (size_t j = 0; j < glyphs; ++j) {
for (uint16_t j = 0; j < glyphs; ++j) {
uint8_t fd_index = 0;
if (!cff_table.ReadU8(&fd_index)) {
return OTS_FAILURE();
@ -844,7 +844,7 @@ bool ParseDictData(const uint8_t *data, size_t table_length,
}
switch (format) {
case 0:
for (unsigned j = 1 /* .notdef is omitted */; j < glyphs; ++j) {
for (uint16_t j = 1 /* .notdef is omitted */; j < glyphs; ++j) {
uint16_t sid = 0;
if (!cff_table.ReadU16(&sid)) {
return OTS_FAILURE();
@ -967,7 +967,7 @@ bool ots_cff_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
return OTS_FAILURE();
}
const size_t num_glyphs = file->maxp->num_glyphs;
const uint16_t num_glyphs = file->maxp->num_glyphs;
const size_t sid_max = string_index.count + kNStdString;
// string_index.count == 0 is allowed.
@ -996,7 +996,8 @@ bool ots_cff_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
// Check if all charstrings (font hinting code for each glyph) are valid.
for (size_t i = 0; i < file->cff->char_strings_array.size(); ++i) {
if (!ValidateType2CharStringIndex(*(file->cff->char_strings_array.at(i)),
if (!ValidateType2CharStringIndex(file,
*(file->cff->char_strings_array.at(i)),
global_subrs_index,
file->cff->fd_select,
file->cff->local_subrs_per_font,

View File

@ -14,6 +14,8 @@
#include <string>
#include <utility>
#define TABLE_NAME "CFF"
namespace {
// Type 2 Charstring Implementation Limits. See Appendix. B in Adobe Technical
@ -28,7 +30,8 @@ const size_t kMaxSubrNesting = 10;
// will fail with the dummy value.
const int32_t dummy_result = INT_MAX;
bool ExecuteType2CharString(size_t call_depth,
bool ExecuteType2CharString(ots::OpenTypeFile *file,
size_t call_depth,
const ots::CFFIndex& global_subrs_index,
const ots::CFFIndex& local_subrs_index,
ots::Buffer *cff_table,
@ -222,7 +225,8 @@ bool ReadNextNumberFromType2CharString(ots::Buffer *char_string,
// succeeds. If the |op| is kCallSubr or kCallGSubr, the function recursively
// calls ExecuteType2CharString() function. The arguments other than |op| and
// |argument_stack| are passed for that reason.
bool ExecuteType2CharStringOperator(int32_t op,
bool ExecuteType2CharStringOperator(ots::OpenTypeFile *file,
int32_t op,
size_t call_depth,
const ots::CFFIndex& global_subrs_index,
const ots::CFFIndex& local_subrs_index,
@ -286,7 +290,8 @@ bool ExecuteType2CharStringOperator(int32_t op,
}
ots::Buffer char_string_to_jump(cff_table->buffer() + offset, length);
return ExecuteType2CharString(call_depth + 1,
return ExecuteType2CharString(file,
call_depth + 1,
global_subrs_index,
local_subrs_index,
cff_table,
@ -708,8 +713,7 @@ bool ExecuteType2CharStringOperator(int32_t op,
return true;
}
//OTS_WARNING("Undefined operator: %d (0x%x)", op, op);
return OTS_FAILURE();
return OTS_FAILURE_MSG("Undefined operator: %d (0x%x)", op, op);
}
// Executes |char_string| and updates |argument_stack|.
@ -725,7 +729,8 @@ bool ExecuteType2CharStringOperator(int32_t op,
// in_out_found_width: true is set if |char_string| contains 'width' byte (which
// is 0 or 1 byte.)
// in_out_num_stems: total number of hstems and vstems processed so far.
bool ExecuteType2CharString(size_t call_depth,
bool ExecuteType2CharString(ots::OpenTypeFile *file,
size_t call_depth,
const ots::CFFIndex& global_subrs_index,
const ots::CFFIndex& local_subrs_index,
ots::Buffer *cff_table,
@ -774,7 +779,8 @@ bool ExecuteType2CharString(size_t call_depth,
}
// An operator is found. Execute it.
if (!ExecuteType2CharStringOperator(operator_or_operand,
if (!ExecuteType2CharStringOperator(file,
operator_or_operand,
call_depth,
global_subrs_index,
local_subrs_index,
@ -839,18 +845,21 @@ bool SelectLocalSubr(const std::map<uint16_t, uint8_t> &fd_select,
namespace ots {
bool ValidateType2CharStringIndex(
ots::OpenTypeFile *file,
const CFFIndex& char_strings_index,
const CFFIndex& global_subrs_index,
const std::map<uint16_t, uint8_t> &fd_select,
const std::vector<CFFIndex *> &local_subrs_per_font,
const CFFIndex *local_subrs,
Buffer* cff_table) {
if (char_strings_index.offsets.size() == 0) {
const uint16_t num_offsets =
static_cast<uint16_t>(char_strings_index.offsets.size());
if (num_offsets != char_strings_index.offsets.size() || num_offsets == 0) {
return OTS_FAILURE(); // no charstring.
}
// For each glyph, validate the corresponding charstring.
for (unsigned i = 1; i < char_strings_index.offsets.size(); ++i) {
for (uint16_t i = 1; i < num_offsets; ++i) {
// Prepare a Buffer object, |char_string|, which contains the charstring
// for the |i|-th glyph.
const size_t length =
@ -866,7 +875,7 @@ bool ValidateType2CharStringIndex(
Buffer char_string(cff_table->buffer() + offset, length);
// Get a local subrs for the glyph.
const unsigned glyph_index = i - 1; // index in the map is 0-origin.
const uint16_t glyph_index = i - 1; // index in the map is 0-origin.
const CFFIndex *local_subrs_to_use = NULL;
if (!SelectLocalSubr(fd_select,
local_subrs_per_font,
@ -886,7 +895,8 @@ bool ValidateType2CharStringIndex(
bool found_endchar = false;
bool found_width = false;
size_t num_stems = 0;
if (!ExecuteType2CharString(0 /* initial call_depth is zero */,
if (!ExecuteType2CharString(file,
0 /* initial call_depth is zero */,
global_subrs_index, *local_subrs_to_use,
cff_table, &char_string, &argument_stack,
&found_endchar, &found_width, &num_stems)) {
@ -900,3 +910,5 @@ bool ValidateType2CharStringIndex(
}
} // namespace ots
#undef TABLE_NAME

View File

@ -35,6 +35,7 @@ namespace ots {
// cff_table: A buffer which contains actual byte code of charstring, global
// subroutines and local subroutines.
bool ValidateType2CharStringIndex(
OpenTypeFile *file,
const CFFIndex &char_strings_index,
const CFFIndex &global_subrs_index,
const std::map<uint16_t, uint8_t> &fd_select,

View File

@ -218,7 +218,7 @@ bool ParseFormat4(ots::OpenTypeFile *file, int platform, int encoding,
// glyphs and that we don't access anything out-of-bounds.
for (unsigned i = 0; i < segcount; ++i) {
for (unsigned cp = ranges[i].start_range; cp <= ranges[i].end_range; ++cp) {
const uint16_t code_point = cp;
const uint16_t code_point = static_cast<uint16_t>(cp);
if (ranges[i].id_range_offset == 0) {
// this is explictly allowed to overflow in the spec
const uint16_t glyph = code_point + ranges[i].id_delta;
@ -866,13 +866,13 @@ bool ots_cmap_serialise(OTSStream *out, OpenTypeFile *file) {
const bool have_314 = (!have_304) && file->cmap->subtable_3_1_4_data;
const bool have_31012 = file->cmap->subtable_3_10_12.size() != 0;
const bool have_31013 = file->cmap->subtable_3_10_13.size() != 0;
const unsigned num_subtables = static_cast<unsigned>(have_034) +
static_cast<unsigned>(have_0514) +
static_cast<unsigned>(have_100) +
static_cast<unsigned>(have_304) +
static_cast<unsigned>(have_314) +
static_cast<unsigned>(have_31012) +
static_cast<unsigned>(have_31013);
const uint16_t num_subtables = static_cast<uint16_t>(have_034) +
static_cast<uint16_t>(have_0514) +
static_cast<uint16_t>(have_100) +
static_cast<uint16_t>(have_304) +
static_cast<uint16_t>(have_314) +
static_cast<uint16_t>(have_31012) +
static_cast<uint16_t>(have_31013);
const off_t table_start = out->Tell();
// Some fonts don't have 3-0-4 MS Symbol nor 3-1-4 Unicode BMP tables
@ -1006,8 +1006,8 @@ bool ots_cmap_serialise(OTSStream *out, OpenTypeFile *file) {
= file->cmap->subtable_3_10_13;
const unsigned num_groups = groups.size();
if (!out->WriteU16(13) ||
!out->WriteU32(0) ||
!out->WriteU32(num_groups * 12 + 14) ||
!out->WriteU16(0) ||
!out->WriteU32(num_groups * 12 + 16) ||
!out->WriteU32(0) ||
!out->WriteU32(num_groups)) {
return OTS_FAILURE();

View File

@ -87,12 +87,14 @@ bool ots_gasp_should_serialise(OpenTypeFile *file) {
bool ots_gasp_serialise(OTSStream *out, OpenTypeFile *file) {
const OpenTypeGASP *gasp = file->gasp;
if (!out->WriteU16(gasp->version) ||
!out->WriteU16(gasp->gasp_ranges.size())) {
const uint16_t num_ranges = static_cast<uint16_t>(gasp->gasp_ranges.size());
if (num_ranges != gasp->gasp_ranges.size() ||
!out->WriteU16(gasp->version) ||
!out->WriteU16(num_ranges)) {
return OTS_FAILURE_MSG("failed to write gasp header");
}
for (unsigned i = 0; i < gasp->gasp_ranges.size(); ++i) {
for (uint16_t i = 0; i < num_ranges; ++i) {
if (!out->WriteU16(gasp->gasp_ranges[i].first) ||
!out->WriteU16(gasp->gasp_ranges[i].second)) {
return OTS_FAILURE_MSG("Failed to write gasp subtable %d", i);

View File

@ -107,13 +107,16 @@ bool ots_hdmx_should_serialise(OpenTypeFile *file) {
bool ots_hdmx_serialise(OTSStream *out, OpenTypeFile *file) {
OpenTypeHDMX * const hdmx = file->hdmx;
if (!out->WriteU16(hdmx->version) ||
!out->WriteS16(hdmx->records.size()) ||
const int16_t num_recs = static_cast<int16_t>(hdmx->records.size());
if (hdmx->records.size() >
static_cast<size_t>(std::numeric_limits<int16_t>::max()) ||
!out->WriteU16(hdmx->version) ||
!out->WriteS16(num_recs) ||
!out->WriteS32(hdmx->size_device_record)) {
return OTS_FAILURE_MSG("Failed to write hdmx header");
}
for (unsigned i = 0; i < hdmx->records.size(); ++i) {
for (int16_t i = 0; i < num_recs; ++i) {
const OpenTypeHDMXDeviceRecord& rec = hdmx->records[i];
if (!out->Write(&rec.pixel_size, 1) ||
!out->Write(&rec.max_width, 1) ||

View File

@ -113,8 +113,8 @@ bool ots_kern_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
if (subtable.entry_selector != max_pow2) {
return OTS_FAILURE_MSG("Bad subtable %d entry selector %d", i, subtable.entry_selector);
}
const uint32_t expected_range_shift
= kFormat0PairSize * num_pairs - subtable.search_range;
const uint16_t expected_range_shift =
kFormat0PairSize * num_pairs - subtable.search_range;
if (subtable.range_shift != expected_range_shift) {
OTS_WARNING("bad range shift");
subtable.range_shift = expected_range_shift;
@ -161,17 +161,21 @@ bool ots_kern_should_serialise(OpenTypeFile *file) {
bool ots_kern_serialise(OTSStream *out, OpenTypeFile *file) {
const OpenTypeKERN *kern = file->kern;
if (!out->WriteU16(kern->version) ||
!out->WriteU16(kern->subtables.size())) {
const uint16_t num_subtables = static_cast<uint16_t>(kern->subtables.size());
if (num_subtables != kern->subtables.size() ||
!out->WriteU16(kern->version) ||
!out->WriteU16(num_subtables)) {
return OTS_FAILURE_MSG("Can't write kern table header");
}
for (unsigned i = 0; i < kern->subtables.size(); ++i) {
const uint16_t length = 14 + (6 * kern->subtables[i].pairs.size());
if (!out->WriteU16(kern->subtables[i].version) ||
!out->WriteU16(length) ||
for (uint16_t i = 0; i < num_subtables; ++i) {
const size_t length = 14 + (6 * kern->subtables[i].pairs.size());
if (length > std::numeric_limits<uint16_t>::max() ||
!out->WriteU16(kern->subtables[i].version) ||
!out->WriteU16(static_cast<uint16_t>(length)) ||
!out->WriteU16(kern->subtables[i].coverage) ||
!out->WriteU16(kern->subtables[i].pairs.size()) ||
!out->WriteU16(
static_cast<uint16_t>(kern->subtables[i].pairs.size())) ||
!out->WriteU16(kern->subtables[i].search_range) ||
!out->WriteU16(kern->subtables[i].entry_selector) ||
!out->WriteU16(kern->subtables[i].range_shift)) {

View File

@ -78,7 +78,9 @@ bool ots_loca_serialise(OTSStream *out, OpenTypeFile *file) {
if (head->index_to_loc_format == 0) {
for (unsigned i = 0; i < loca->offsets.size(); ++i) {
if (!out->WriteU16(loca->offsets[i] >> 1)) {
const uint16_t offset = static_cast<uint16_t>(loca->offsets[i] >> 1);
if ((offset != (loca->offsets[i] >> 1)) ||
!out->WriteU16(offset)) {
return OTS_FAILURE_MSG("Failed to write glyph offset for glyph %d", i);
}
}

View File

@ -67,11 +67,13 @@ bool ots_ltsh_should_serialise(OpenTypeFile *file) {
bool ots_ltsh_serialise(OTSStream *out, OpenTypeFile *file) {
const OpenTypeLTSH *ltsh = file->ltsh;
if (!out->WriteU16(ltsh->version) ||
!out->WriteU16(ltsh->ypels.size())) {
const uint16_t num_ypels = static_cast<uint16_t>(ltsh->ypels.size());
if (num_ypels != ltsh->ypels.size() ||
!out->WriteU16(ltsh->version) ||
!out->WriteU16(num_ypels)) {
return OTS_FAILURE_MSG("Failed to write pels size");
}
for (unsigned i = 0; i < ltsh->ypels.size(); ++i) {
for (uint16_t i = 0; i < num_ypels; ++i) {
if (!out->Write(&(ltsh->ypels[i]), 1)) {
return OTS_FAILURE_MSG("Failed to write pixel size for glyph %d", i);
}

View File

@ -126,6 +126,8 @@ bool ParseMetricsTable(const ots::OpenTypeFile *file,
return OTS_FAILURE_MSG("Failed to read metric %d", i);
}
// This check is bogus, see https://github.com/khaledhosny/ots/issues/36
#if 0
// Since so many fonts don't have proper value on |adv| and |sb|,
// we should not call ots_failure() here. For example, about 20% of fonts
// in http://www.princexml.com/fonts/ (200+ fonts) fails these tests.
@ -138,6 +140,7 @@ bool ParseMetricsTable(const ots::OpenTypeFile *file,
OTS_WARNING("bad sb: %d < %d", sb, header->min_sb1);
sb = header->min_sb1;
}
#endif
metrics->entries.push_back(std::make_pair(adv, sb));
}
@ -150,12 +153,15 @@ bool ParseMetricsTable(const ots::OpenTypeFile *file,
return OTS_FAILURE_MSG("Failed to read side bearing %d", i + num_metrics);
}
// This check is bogus, see https://github.com/khaledhosny/ots/issues/36
#if 0
if (sb < header->min_sb1) {
// The same as above. Three fonts in http://www.fontsquirrel.com/fontface
// (e.g., Notice2Std.otf) have weird lsb values.
OTS_WARNING("bad lsb: %d < %d", sb, header->min_sb1);
sb = header->min_sb1;
}
#endif
metrics->sbs.push_back(sb);
}

View File

@ -200,7 +200,7 @@ bool ots_name_parse(OpenTypeFile* file, const uint8_t* data, size_t length) {
// 4 - full name
// 5 - version
// 6 - postscript name
static const unsigned kStdNameCount = 7;
static const uint16_t kStdNameCount = 7;
static const char* kStdNames[kStdNameCount] = {
NULL,
"OTS derived font",
@ -237,7 +237,7 @@ bool ots_name_parse(OpenTypeFile* file, const uint8_t* data, size_t length) {
}
}
for (unsigned i = 0; i < kStdNameCount; ++i) {
for (uint16_t i = 0; i < kStdNameCount; ++i) {
if (kStdNames[i] == NULL) {
continue;
}
@ -271,8 +271,8 @@ bool ots_name_should_serialise(OpenTypeFile* file) {
bool ots_name_serialise(OTSStream* out, OpenTypeFile* file) {
const OpenTypeNAME* name = file->name;
uint16_t name_count = name->names.size();
uint16_t lang_tag_count = name->lang_tags.size();
uint16_t name_count = static_cast<uint16_t>(name->names.size());
uint16_t lang_tag_count = static_cast<uint16_t>(name->lang_tags.size());
uint16_t format = 0;
size_t string_offset = 6 + name_count * 12;
@ -286,7 +286,7 @@ bool ots_name_serialise(OTSStream* out, OpenTypeFile* file) {
}
if (!out->WriteU16(format) ||
!out->WriteU16(name_count) ||
!out->WriteU16(string_offset)) {
!out->WriteU16(static_cast<uint16_t>(string_offset))) {
return OTS_FAILURE_MSG("Failed to write name header");
}
@ -294,12 +294,14 @@ bool ots_name_serialise(OTSStream* out, OpenTypeFile* file) {
for (std::vector<NameRecord>::const_iterator name_iter = name->names.begin();
name_iter != name->names.end(); name_iter++) {
const NameRecord& rec = *name_iter;
if (!out->WriteU16(rec.platform_id) ||
if (string_data.size() + rec.text.size() >
std::numeric_limits<uint16_t>::max() ||
!out->WriteU16(rec.platform_id) ||
!out->WriteU16(rec.encoding_id) ||
!out->WriteU16(rec.language_id) ||
!out->WriteU16(rec.name_id) ||
!out->WriteU16(rec.text.size()) ||
!out->WriteU16(string_data.size()) ) {
!out->WriteU16(static_cast<uint16_t>(rec.text.size())) ||
!out->WriteU16(static_cast<uint16_t>(string_data.size())) ) {
return OTS_FAILURE_MSG("Faile to write name entry");
}
string_data.append(rec.text);
@ -312,8 +314,10 @@ bool ots_name_serialise(OTSStream* out, OpenTypeFile* file) {
for (std::vector<std::string>::const_iterator tag_iter =
name->lang_tags.begin();
tag_iter != name->lang_tags.end(); tag_iter++) {
if (!out->WriteU16(tag_iter->size()) ||
!out->WriteU16(string_data.size())) {
if (string_data.size() + tag_iter->size() >
std::numeric_limits<uint16_t>::max() ||
!out->WriteU16(static_cast<uint16_t>(tag_iter->size())) ||
!out->WriteU16(static_cast<uint16_t>(string_data.size()))) {
return OTS_FAILURE_MSG("Failed to write string");
}
string_data.append(*tag_iter);

View File

@ -211,8 +211,8 @@ bool ProcessTTF(ots::OpenTypeFile *header,
// range_shift is NumTables x 16-searchRange. We know that 16*num_tables
// doesn't over flow because we range checked it above. Also, we know that
// it's > header->search_range by construction of search_range.
const uint32_t expected_range_shift
= 16 * header->num_tables - header->search_range;
const uint16_t expected_range_shift =
16 * header->num_tables - header->search_range;
if (header->range_shift != expected_range_shift) {
OTS_FAILURE_MSG_HDR("bad range shift");
header->range_shift = expected_range_shift; // the same as above.
@ -611,7 +611,7 @@ bool ProcessGeneric(ots::OpenTypeFile *header, uint32_t signature,
}
}
unsigned num_output_tables = 0;
uint16_t num_output_tables = 0;
for (unsigned i = 0; ; ++i) {
if (table_parsers[i].parse == NULL) {
break;
@ -630,7 +630,7 @@ bool ProcessGeneric(ots::OpenTypeFile *header, uint32_t signature,
}
}
unsigned max_pow2 = 0;
uint16_t max_pow2 = 0;
while (1u << (max_pow2 + 1) <= num_output_tables) {
max_pow2++;
}
@ -831,6 +831,12 @@ bool OTSContext::Process(OTSStream *output,
return result;
}
// For backward compatibility
bool Process(OTSStream *output, const uint8_t *data, size_t length) {
static OTSContext context;
return context.Process(output, data, length);
}
#if !defined(_MSC_VER) && defined(OTS_DEBUG)
bool Failure(const char *f, int l, const char *fn) {
if (g_debug_output) {

View File

@ -34,28 +34,31 @@ bool Failure(const char *f, int l, const char *fn);
// its result (indicating a failure).
#if defined(_MSC_VER) || !defined(OTS_DEBUG)
#define OTS_MESSAGE_(otf_,...) \
(otf_)->context->Message(__VA_ARGS__)
#define OTS_MESSAGE_(level,otf_,...) \
(otf_)->context->Message(level,__VA_ARGS__)
#else
#define OTS_MESSAGE_(otf_,...) \
#define OTS_MESSAGE_(level,otf_,...) \
OTS_FAILURE(), \
(otf_)->context->Message(__VA_ARGS__)
(otf_)->context->Message(level,__VA_ARGS__)
#endif
// Generate a simple message
#define OTS_FAILURE_MSG_(otf_,...) \
(OTS_MESSAGE_(otf_,__VA_ARGS__), false)
(OTS_MESSAGE_(0,otf_,__VA_ARGS__), false)
#define OTS_WARNING_MSG_(otf_,...) \
OTS_MESSAGE_(1,otf_,__VA_ARGS__)
// Generate a message with an associated table tag
#define OTS_FAILURE_MSG_TAG_(otf_,msg_,tag_) \
(OTS_MESSAGE_(otf_,"%4.4s: %s", tag_, msg_), false)
(OTS_MESSAGE_(0,otf_,"%4.4s: %s", tag_, msg_), false)
// Convenience macro for use in files that only handle a single table tag,
// Convenience macros for use in files that only handle a single table tag,
// defined as TABLE_NAME at the top of the file; the 'file' variable is
// expected to be the current OpenTypeFile pointer.
#define OTS_FAILURE_MSG(...) OTS_FAILURE_MSG_(file, TABLE_NAME ": " __VA_ARGS__)
#define OTS_WARNING OTS_FAILURE_MSG
#define OTS_WARNING(...) OTS_WARNING_MSG_(file, TABLE_NAME ": " __VA_ARGS__)
// -----------------------------------------------------------------------------
// Buffer helper class

View File

@ -148,11 +148,14 @@ bool ots_post_serialise(OTSStream *out, OpenTypeFile *file) {
return true; // v1.0 and v3.0 does not have glyph names.
}
if (!out->WriteU16(post->glyph_name_index.size())) {
const uint16_t num_indexes =
static_cast<uint16_t>(post->glyph_name_index.size());
if (num_indexes != post->glyph_name_index.size() ||
!out->WriteU16(num_indexes)) {
return OTS_FAILURE_MSG("Failed to write number of indices");
}
for (unsigned i = 0; i < post->glyph_name_index.size(); ++i) {
for (uint16_t i = 0; i < num_indexes; ++i) {
if (!out->WriteU16(post->glyph_name_index[i])) {
return OTS_FAILURE_MSG("Failed to write name index %d", i);
}
@ -161,8 +164,9 @@ bool ots_post_serialise(OTSStream *out, OpenTypeFile *file) {
// Now we just have to write out the strings in the correct order
for (unsigned i = 0; i < post->names.size(); ++i) {
const std::string& s = post->names[i];
const uint8_t string_length = s.size();
if (!out->Write(&string_length, 1)) {
const uint8_t string_length = static_cast<uint8_t>(s.size());
if (string_length != s.size() ||
!out->Write(&string_length, 1)) {
return OTS_FAILURE_MSG("Failed to write string %d", i);
}
// Some ttf fonts (e.g., frank.ttf on Windows Vista) have zero-length name.

View File

@ -75,15 +75,17 @@ bool ots_vorg_should_serialise(OpenTypeFile *file) {
bool ots_vorg_serialise(OTSStream *out, OpenTypeFile *file) {
OpenTypeVORG * const vorg = file->vorg;
if (!out->WriteU16(vorg->major_version) ||
const uint16_t num_metrics = static_cast<uint16_t>(vorg->metrics.size());
if (num_metrics != vorg->metrics.size() ||
!out->WriteU16(vorg->major_version) ||
!out->WriteU16(vorg->minor_version) ||
!out->WriteS16(vorg->default_vert_origin_y) ||
!out->WriteU16(vorg->metrics.size())) {
!out->WriteU16(num_metrics)) {
return OTS_FAILURE_MSG("Failed to write table header");
}
for (unsigned i = 0; i < vorg->metrics.size(); ++i) {
for (uint16_t i = 0; i < num_metrics; ++i) {
const OpenTypeVORGMetrics& rec = vorg->metrics[i];
if (!out->WriteU16(rec.glyph_index) ||
!out->WriteS16(rec.vert_origin_y)) {

View File

@ -21,12 +21,12 @@
namespace {
// simple glyph flags
const int kGlyfOnCurve = 1 << 0;
const int kGlyfXShort = 1 << 1;
const int kGlyfYShort = 1 << 2;
const int kGlyfRepeat = 1 << 3;
const int kGlyfThisXIsSame = 1 << 4;
const int kGlyfThisYIsSame = 1 << 5;
const uint8_t kGlyfOnCurve = 1 << 0;
const uint8_t kGlyfXShort = 1 << 1;
const uint8_t kGlyfYShort = 1 << 2;
const uint8_t kGlyfRepeat = 1 << 3;
const uint8_t kGlyfThisXIsSame = 1 << 4;
const uint8_t kGlyfThisYIsSame = 1 << 5;
// composite glyph flags
const int FLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0;
@ -122,8 +122,8 @@ const uint32_t kKnownTags[] = {
};
struct Point {
int x;
int y;
int16_t x;
int16_t y;
bool on_curve;
};
@ -149,11 +149,11 @@ struct Table {
};
// Based on section 6.1.1 of MicroType Express draft spec
bool Read255UShort(ots::Buffer* buf, unsigned int* value) {
static const int kWordCode = 253;
static const int kOneMoreByteCode2 = 254;
static const int kOneMoreByteCode1 = 255;
static const int kLowestUCode = 253;
bool Read255UShort(ots::Buffer* buf, uint16_t* value) {
static const uint8_t kWordCode = 253;
static const uint8_t kOneMoreByteCode2 = 254;
static const uint8_t kOneMoreByteCode1 = 255;
static const uint8_t kLowestUCode = 253;
uint8_t code = 0;
if (!buf->ReadU8(&code)) {
return OTS_FAILURE();
@ -211,15 +211,15 @@ bool ReadBase128(ots::Buffer* buf, uint32_t* value) {
// and use it across the code.
size_t StoreU32(uint8_t* dst, size_t offset, uint32_t x) {
dst[offset] = x >> 24;
dst[offset + 1] = x >> 16;
dst[offset + 2] = x >> 8;
dst[offset + 3] = x;
dst[offset + 1] = (x >> 16) & 0xff;
dst[offset + 2] = (x >> 8) & 0xff;
dst[offset + 3] = x & 0xff;
return offset + 4;
}
size_t Store16(uint8_t* dst, size_t offset, int x) {
size_t StoreU16(uint8_t* dst, size_t offset, uint16_t x) {
dst[offset] = x >> 8;
dst[offset + 1] = x;
dst[offset + 1] = x & 0xff;
return offset + 2;
}
@ -290,8 +290,8 @@ bool TripletDecode(const uint8_t* flags_in, const uint8_t* in, size_t in_size,
y += dy;
result->push_back(Point());
Point& back = result->back();
back.x = x;
back.y = y;
back.x = static_cast<int16_t>(x);
back.y = static_cast<int16_t>(y);
back.on_curve = on_curve;
}
*in_bytes_consumed = triplet_index;
@ -307,8 +307,8 @@ bool StorePoints(const std::vector<Point>& points,
// comment and/or an assert would be good.
unsigned int flag_offset = kEndPtsOfContoursOffset + 2 * n_contours + 2 +
instruction_length;
int last_flag = -1;
int repeat_count = 0;
uint8_t last_flag = 0xff;
uint8_t repeat_count = 0;
int last_x = 0;
int last_y = 0;
unsigned int x_bytes = 0;
@ -316,7 +316,7 @@ bool StorePoints(const std::vector<Point>& points,
for (size_t i = 0; i < points.size(); ++i) {
const Point& point = points.at(i);
int flag = point.on_curve ? kGlyfOnCurve : 0;
uint8_t flag = point.on_curve ? kGlyfOnCurve : 0;
int dx = point.x - last_x;
int dy = point.y - last_y;
if (dx == 0) {
@ -379,19 +379,19 @@ bool StorePoints(const std::vector<Point>& points,
if (dx == 0) {
// pass
} else if (dx > -256 && dx < 256) {
dst[x_offset++] = std::abs(dx);
dst[x_offset++] = static_cast<uint8_t>(std::abs(dx));
} else {
// will always fit for valid input, but overflow is harmless
x_offset = Store16(dst, x_offset, dx);
x_offset = StoreU16(dst, x_offset, static_cast<uint16_t>(dx));
}
last_x += dx;
int dy = points.at(i).y - last_y;
if (dy == 0) {
// pass
} else if (dy > -256 && dy < 256) {
dst[y_offset++] = std::abs(dy);
dst[y_offset++] = static_cast<uint8_t>(std::abs(dy));
} else {
y_offset = Store16(dst, y_offset, dy);
y_offset = StoreU16(dst, y_offset, static_cast<uint16_t>(dy));
}
last_y += dy;
}
@ -402,24 +402,24 @@ bool StorePoints(const std::vector<Point>& points,
// Compute the bounding box of the coordinates, and store into a glyf buffer.
// A precondition is that there are at least 10 bytes available.
void ComputeBbox(const std::vector<Point>& points, uint8_t* dst) {
int x_min = 0;
int y_min = 0;
int x_max = 0;
int y_max = 0;
int16_t x_min = 0;
int16_t y_min = 0;
int16_t x_max = 0;
int16_t y_max = 0;
for (size_t i = 0; i < points.size(); ++i) {
int x = points.at(i).x;
int y = points.at(i).y;
int16_t x = points.at(i).x;
int16_t y = points.at(i).y;
if (i == 0 || x < x_min) x_min = x;
if (i == 0 || x > x_max) x_max = x;
if (i == 0 || y < y_min) y_min = y;
if (i == 0 || y > y_max) y_max = y;
}
size_t offset = 2;
offset = Store16(dst, offset, x_min);
offset = Store16(dst, offset, y_min);
offset = Store16(dst, offset, x_max);
offset = Store16(dst, offset, y_max);
offset = StoreU16(dst, offset, x_min);
offset = StoreU16(dst, offset, y_min);
offset = StoreU16(dst, offset, x_max);
offset = StoreU16(dst, offset, y_max);
}
// Process entire bbox stream. This is done as a separate pass to allow for
@ -486,7 +486,7 @@ bool ProcessComposite(ots::Buffer* composite_stream, uint8_t* dst,
if (composite_glyph_size + kCompositeGlyphBegin > dst_size) {
return OTS_FAILURE();
}
Store16(dst, 0, 0xffff); // nContours = -1 for composite glyph
StoreU16(dst, 0, 0xffff); // nContours = -1 for composite glyph
std::memcpy(dst + kCompositeGlyphBegin,
composite_stream->buffer() + start_offset,
composite_glyph_size);
@ -513,7 +513,7 @@ bool StoreLoca(const std::vector<uint32_t>& loca_values, int index_format,
if (index_format) {
offset = StoreU32(dst, offset, value);
} else {
offset = Store16(dst, offset, value >> 1);
offset = StoreU16(dst, offset, static_cast<uint16_t>(value >> 1));
}
}
return true;
@ -564,7 +564,7 @@ bool ReconstructGlyf(const uint8_t* data, size_t data_size,
std::vector<uint32_t> loca_values;
loca_values.reserve(num_glyphs + 1);
std::vector<unsigned int> n_points_vec;
std::vector<uint16_t> n_points_vec;
std::vector<Point> points;
uint32_t loca_offset = 0;
for (unsigned int i = 0; i < num_glyphs; ++i) {
@ -578,7 +578,7 @@ bool ReconstructGlyf(const uint8_t* data, size_t data_size,
if (n_contours == 0xffff) {
// composite glyph
bool have_instructions = false;
unsigned int instruction_size = 0;
uint16_t instruction_size = 0;
if (!ProcessComposite(&composite_stream, glyf_dst, glyf_dst_size,
&glyph_size, &have_instructions)) {
return OTS_FAILURE();
@ -588,10 +588,10 @@ bool ReconstructGlyf(const uint8_t* data, size_t data_size,
return OTS_FAILURE();
}
// No integer overflow here (instruction_size < 2^16).
if (instruction_size + 2 > glyf_dst_size - glyph_size) {
if (instruction_size + 2U > glyf_dst_size - glyph_size) {
return OTS_FAILURE();
}
Store16(glyf_dst, glyph_size, instruction_size);
StoreU16(glyf_dst, glyph_size, instruction_size);
if (!instruction_stream.Read(glyf_dst + glyph_size + 2,
instruction_size)) {
return OTS_FAILURE();
@ -602,9 +602,9 @@ bool ReconstructGlyf(const uint8_t* data, size_t data_size,
// simple glyph
n_points_vec.clear();
points.clear();
unsigned int total_n_points = 0;
unsigned int n_points_contour;
for (unsigned int j = 0; j < n_contours; ++j) {
uint32_t total_n_points = 0;
uint16_t n_points_contour;
for (uint32_t j = 0; j < n_contours; ++j) {
if (!Read255UShort(&n_points_stream, &n_points_contour)) {
return OTS_FAILURE();
}
@ -614,7 +614,7 @@ bool ReconstructGlyf(const uint8_t* data, size_t data_size,
}
total_n_points += n_points_contour;
}
unsigned int flag_size = total_n_points;
uint32_t flag_size = total_n_points;
if (flag_size > flag_stream.length() - flag_stream.offset()) {
return OTS_FAILURE();
}
@ -632,7 +632,7 @@ bool ReconstructGlyf(const uint8_t* data, size_t data_size,
if (glyf_dst_size < header_and_endpts_contours_size) {
return OTS_FAILURE();
}
Store16(glyf_dst, 0, n_contours);
StoreU16(glyf_dst, 0, n_contours);
ComputeBbox(points, glyf_dst);
size_t endpts_offset = kEndPtsOfContoursOffset;
int end_point = -1;
@ -641,7 +641,7 @@ bool ReconstructGlyf(const uint8_t* data, size_t data_size,
if (end_point >= 65536) {
return OTS_FAILURE();
}
endpts_offset = Store16(glyf_dst, endpts_offset, end_point);
endpts_offset = StoreU16(glyf_dst, endpts_offset, static_cast<uint16_t>(end_point));
}
if (!flag_stream.Skip(flag_size)) {
return OTS_FAILURE();
@ -649,17 +649,17 @@ bool ReconstructGlyf(const uint8_t* data, size_t data_size,
if (!glyph_stream.Skip(triplet_bytes_consumed)) {
return OTS_FAILURE();
}
unsigned int instruction_size;
uint16_t instruction_size;
if (!Read255UShort(&glyph_stream, &instruction_size)) {
return OTS_FAILURE();
}
// No integer overflow here (instruction_size < 2^16).
if (glyf_dst_size - header_and_endpts_contours_size <
instruction_size + 2) {
instruction_size + 2U) {
return OTS_FAILURE();
}
uint8_t* instruction_dst = glyf_dst + header_and_endpts_contours_size;
Store16(instruction_dst, 0, instruction_size);
StoreU16(instruction_dst, 0, instruction_size);
if (!instruction_stream.Read(instruction_dst + 2, instruction_size)) {
return OTS_FAILURE();
}
@ -915,14 +915,14 @@ bool ConvertWOFF2ToTTF(uint8_t* result, size_t result_length,
uint64_t uncompressed_sum = 0;
for (uint16_t i = 0; i < num_tables; ++i) {
Table* table = &tables.at(i);
table->src_offset = src_offset;
table->src_offset = static_cast<uint32_t>(src_offset);
table->src_length = (i == 0 ? compressed_length : 0);
src_offset += table->src_length;
if (src_offset > std::numeric_limits<uint32_t>::max()) {
return OTS_FAILURE();
}
src_offset = ots::Round4(src_offset);
table->dst_offset = dst_offset;
table->dst_offset = static_cast<uint32_t>(dst_offset);
dst_offset += table->dst_length;
if (dst_offset > std::numeric_limits<uint32_t>::max()) {
return OTS_FAILURE();
@ -951,15 +951,15 @@ bool ConvertWOFF2ToTTF(uint8_t* result, size_t result_length,
// Start building the font
size_t offset = 0;
offset = StoreU32(result, offset, flavor);
offset = Store16(result, offset, num_tables);
unsigned max_pow2 = 0;
offset = StoreU16(result, offset, num_tables);
uint8_t max_pow2 = 0;
while (1u << (max_pow2 + 1) <= num_tables) {
max_pow2++;
}
const uint16_t output_search_range = (1u << max_pow2) << 4;
offset = Store16(result, offset, output_search_range);
offset = Store16(result, offset, max_pow2);
offset = Store16(result, offset, (num_tables << 4) - output_search_range);
offset = StoreU16(result, offset, output_search_range);
offset = StoreU16(result, offset, max_pow2);
offset = StoreU16(result, offset, (num_tables << 4) - output_search_range);
for (uint16_t i = 0; i < num_tables; ++i) {
const Table* table = &tables.at(i);
offset = StoreU32(result, offset, table->tag);
@ -1001,8 +1001,9 @@ bool ConvertWOFF2ToTTF(uint8_t* result, size_t result_length,
if (total_size > 30 * 1024 * 1024) {
return OTS_FAILURE();
}
uncompressed_buf.resize(total_size);
if (!Woff2Uncompress(&uncompressed_buf[0], total_size,
const size_t total_size_size_t = static_cast<size_t>(total_size);
uncompressed_buf.resize(total_size_size_t);
if (!Woff2Uncompress(&uncompressed_buf[0], total_size_size_t,
src_buf, compressed_length, compression_type)) {
return OTS_FAILURE();
}

View File

@ -12,7 +12,7 @@ cp $1/LICENSE .
echo "Updating src..."
cd src
ls --ignore moz.build | xargs rm -rf
ls | fgrep -v moz.build | xargs rm -rf
cp -r $1/src/* .
cd ..
@ -22,7 +22,10 @@ cp -r $1/include .
echo "Updating README.mozilla..."
REVISION=`cd $1; git log | head -1 | sed "s/commit //"`
sed "s/\(Current revision: \).*/\1$REVISION/" -i README.mozilla
sed -e "s/\(Current revision: \).*/\1$REVISION/" -i "" README.mozilla
echo "Applying ots-visibility.patch..."
patch -p3 < ots-visibility.patch
echo "Applying ots-brotli-path.patch..."
patch -p3 < ots-brotli-path.patch

View File

@ -194,7 +194,8 @@ public:
return ots::TABLE_ACTION_DEFAULT;
}
virtual void Message(const char* format, ...) MSGFUNC_FMT_ATTR MOZ_OVERRIDE {
virtual void Message(int level, const char* format,
...) MSGFUNC_FMT_ATTR MOZ_OVERRIDE {
va_list va;
va_start(va, format);