Merge PR #16 (reject composite glyphs w/o bbox), slightly modified to match recent code updates (mostly just adding branch predictions)

This commit is contained in:
Rod Sheeter
2015-07-14 10:12:40 -07:00
parent 3fdb28894a
commit 4e3bb3418f
+23 -37
View File
@@ -271,39 +271,6 @@ void ComputeBbox(unsigned int n_points, const Point* points, uint8_t* dst) {
offset = Store16(dst, offset, y_max); offset = Store16(dst, offset, y_max);
} }
// Process entire bbox stream. This is done as a separate pass to allow for
// composite bbox computations (an optional more aggressive transform).
bool ProcessBboxStream(Buffer* bbox_stream, unsigned int n_glyphs,
const std::vector<uint32_t>& loca_values, uint8_t* glyf_buf,
size_t glyf_buf_length) {
const uint8_t* buf = bbox_stream->buffer();
if (PREDICT_FALSE(n_glyphs >= 65536 || loca_values.size() != n_glyphs + 1)) {
return FONT_COMPRESSION_FAILURE();
}
// Safe because n_glyphs is bounded
unsigned int bitmap_length = ((n_glyphs + 31) >> 5) << 2;
if (PREDICT_FALSE(!bbox_stream->Skip(bitmap_length))) {
return FONT_COMPRESSION_FAILURE();
}
for (unsigned int i = 0; i < n_glyphs; ++i) {
if (buf[i >> 3] & (0x80 >> (i & 7))) {
uint32_t loca_offset = loca_values[i];
if (PREDICT_FALSE(
loca_values[i + 1] - loca_offset < kEndPtsOfContoursOffset)) {
return FONT_COMPRESSION_FAILURE();
}
if (PREDICT_FALSE(glyf_buf_length < 2 + 10 ||
loca_offset > glyf_buf_length - 2 - 10)) {
return FONT_COMPRESSION_FAILURE();
}
if (PREDICT_FALSE(!bbox_stream->Read(glyf_buf + loca_offset + 2, 8))) {
return FONT_COMPRESSION_FAILURE();
}
}
}
return true;
}
bool ProcessComposite(Buffer* composite_stream, uint8_t* dst, bool ProcessComposite(Buffer* composite_stream, uint8_t* dst,
size_t dst_size, size_t* glyph_size, bool* have_instructions) { size_t dst_size, size_t* glyph_size, bool* have_instructions) {
size_t start_offset = composite_stream->offset(); size_t start_offset = composite_stream->offset();
@@ -416,9 +383,19 @@ bool ReconstructGlyf(const uint8_t* data, size_t data_size,
std::unique_ptr<Point[]> points; std::unique_ptr<Point[]> points;
size_t points_size = 0; size_t points_size = 0;
uint32_t loca_offset = 0; uint32_t loca_offset = 0;
const uint8_t* bbox_bitmap = bbox_stream.buffer();
// Safe because num_glyphs is bounded
unsigned int bitmap_length = ((num_glyphs + 31) >> 5) << 2;
if (!bbox_stream.Skip(bitmap_length)) {
return FONT_COMPRESSION_FAILURE();
}
for (unsigned int i = 0; i < num_glyphs; ++i) { for (unsigned int i = 0; i < num_glyphs; ++i) {
size_t glyph_size = 0; size_t glyph_size = 0;
uint16_t n_contours = 0; uint16_t n_contours = 0;
bool have_bbox = false;
if (bbox_bitmap[i >> 3] & (0x80 >> (i & 7))) {
have_bbox = true;
}
if (PREDICT_FALSE(!n_contour_stream.ReadU16(&n_contours))) { if (PREDICT_FALSE(!n_contour_stream.ReadU16(&n_contours))) {
return FONT_COMPRESSION_FAILURE(); return FONT_COMPRESSION_FAILURE();
} }
@@ -428,10 +405,17 @@ bool ReconstructGlyf(const uint8_t* data, size_t data_size,
// composite glyph // composite glyph
bool have_instructions = false; bool have_instructions = false;
unsigned int instruction_size = 0; unsigned int instruction_size = 0;
if (PREDICT_FALSE(!have_bbox)) {
// composite glyphs must have an explicit bbox
return FONT_COMPRESSION_FAILURE();
}
if (PREDICT_FALSE(!ProcessComposite(&composite_stream, glyf_dst, if (PREDICT_FALSE(!ProcessComposite(&composite_stream, glyf_dst,
glyf_dst_size, &glyph_size, &have_instructions))) { glyf_dst_size, &glyph_size, &have_instructions))) {
return FONT_COMPRESSION_FAILURE(); return FONT_COMPRESSION_FAILURE();
} }
if (PREDICT_FALSE(!bbox_stream.Read(glyf_dst + 2, 8))) {
return FONT_COMPRESSION_FAILURE();
}
if (have_instructions) { if (have_instructions) {
if (PREDICT_FALSE(!Read255UShort(&glyph_stream, &instruction_size))) { if (PREDICT_FALSE(!Read255UShort(&glyph_stream, &instruction_size))) {
return FONT_COMPRESSION_FAILURE(); return FONT_COMPRESSION_FAILURE();
@@ -486,7 +470,13 @@ bool ReconstructGlyf(const uint8_t* data, size_t data_size,
return FONT_COMPRESSION_FAILURE(); return FONT_COMPRESSION_FAILURE();
} }
Store16(glyf_dst, 0, n_contours); Store16(glyf_dst, 0, n_contours);
if (have_bbox) {
if (PREDICT_FALSE(!bbox_stream.Read(glyf_dst + 2, 8))) {
return FONT_COMPRESSION_FAILURE();
}
} else {
ComputeBbox(total_n_points, points.get(), glyf_dst); ComputeBbox(total_n_points, points.get(), glyf_dst);
}
size_t offset = kEndPtsOfContoursOffset; size_t offset = kEndPtsOfContoursOffset;
int end_point = -1; int end_point = -1;
for (unsigned int contour_ix = 0; contour_ix < n_contours; ++contour_ix) { for (unsigned int contour_ix = 0; contour_ix < n_contours; ++contour_ix) {
@@ -536,10 +526,6 @@ bool ReconstructGlyf(const uint8_t* data, size_t data_size,
loca_offset += glyph_size; loca_offset += glyph_size;
} }
loca_values[num_glyphs] = loca_offset; loca_values[num_glyphs] = loca_offset;
if (PREDICT_FALSE(!ProcessBboxStream(&bbox_stream, num_glyphs, loca_values,
dst, dst_size))) {
return FONT_COMPRESSION_FAILURE();
}
return StoreLoca(loca_values, index_format, loca_buf, loca_size); return StoreLoca(loca_values, index_format, loca_buf, loca_size);
} }