[gvar] Use hb_bytes_t.check_range instead having in house one

And use TupleVarHeader calculated size for validity check.

Fixes https://crbug.com/oss-fuzz/20919 and possibly other gvar related issues
This commit is contained in:
Ebrahim Byagowi 2020-02-28 21:09:07 +03:30 committed by GitHub
parent 15b43a4104
commit 61208401f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 13 additions and 23 deletions

View File

@ -203,10 +203,10 @@ struct GlyphVarData
struct tuple_iterator_t struct tuple_iterator_t
{ {
void init (const GlyphVarData *var_data_, unsigned int length_, unsigned int axis_count_) void init (hb_bytes_t var_data_bytes_, unsigned int axis_count_)
{ {
var_data = var_data_; var_data_bytes = var_data_bytes_;
length = length_; var_data = var_data_bytes_.as<GlyphVarData> ();
index = 0; index = 0;
axis_count = axis_count_; axis_count = axis_count_;
current_tuple = &var_data->get_tuple_var_header (); current_tuple = &var_data->get_tuple_var_header ();
@ -217,10 +217,9 @@ struct GlyphVarData
{ {
if (var_data->has_shared_point_numbers ()) if (var_data->has_shared_point_numbers ())
{ {
hb_bytes_t bytes ((const char *) var_data, length);
const HBUINT8 *base = &(var_data+var_data->data); const HBUINT8 *base = &(var_data+var_data->data);
const HBUINT8 *p = base; const HBUINT8 *p = base;
if (!unpack_points (p, shared_indices, bytes)) return false; if (!unpack_points (p, shared_indices, var_data_bytes)) return false;
data_offset = p - base; data_offset = p - base;
} }
return true; return true;
@ -229,7 +228,8 @@ struct GlyphVarData
bool is_valid () const bool is_valid () const
{ {
return (index < var_data->tupleVarCount.get_count ()) && return (index < var_data->tupleVarCount.get_count ()) &&
in_range (current_tuple) && var_data_bytes.check_range (current_tuple, TupleVarHeader::min_size) &&
var_data_bytes.check_range (current_tuple, current_tuple->get_data_size ()) &&
current_tuple->get_size (axis_count); current_tuple->get_size (axis_count);
} }
@ -241,32 +241,25 @@ struct GlyphVarData
return is_valid (); return is_valid ();
} }
bool in_range (const void *p, unsigned int l) const
{ return (const char*) p >= (const char*) var_data && (const char*) p+l <= (const char*) var_data + length; }
template <typename T> bool in_range (const T *p) const { return in_range (p, sizeof (*p)); }
const HBUINT8 *get_serialized_data () const const HBUINT8 *get_serialized_data () const
{ return &(var_data+var_data->data) + data_offset; } { return &(var_data+var_data->data) + data_offset; }
private: private:
const GlyphVarData *var_data; const GlyphVarData *var_data;
unsigned int length;
unsigned int index; unsigned int index;
unsigned int axis_count; unsigned int axis_count;
unsigned int data_offset; unsigned int data_offset;
public: public:
hb_bytes_t var_data_bytes;
const TupleVarHeader *current_tuple; const TupleVarHeader *current_tuple;
}; };
static bool get_tuple_iterator (const GlyphVarData *var_data, static bool get_tuple_iterator (hb_bytes_t var_data_bytes, unsigned axis_count,
unsigned int length,
unsigned int axis_count,
hb_vector_t<unsigned int> &shared_indices /* OUT */, hb_vector_t<unsigned int> &shared_indices /* OUT */,
tuple_iterator_t *iterator /* OUT */) tuple_iterator_t *iterator /* OUT */)
{ {
iterator->init (var_data, length, axis_count); iterator->init (var_data_bytes, axis_count);
if (!iterator->get_shared_indices (shared_indices)) if (!iterator->get_shared_indices (shared_indices))
return false; return false;
return iterator->is_valid (); return iterator->is_valid ();
@ -574,14 +567,11 @@ struct gvar
if (!coord_count || coord_count != gvar_table->axisCount) return true; if (!coord_count || coord_count != gvar_table->axisCount) return true;
hb_bytes_t var_data_bytes = gvar_table->get_glyph_var_data_bytes (gvar_table.get_blob (), glyph); hb_bytes_t var_data_bytes = gvar_table->get_glyph_var_data_bytes (gvar_table.get_blob (), glyph);
const GlyphVarData *var_data = var_data_bytes.as<GlyphVarData> (); if (!var_data_bytes.as<GlyphVarData> ()->has_data ()) return true;
if (!var_data->has_data ()) return true;
hb_vector_t<unsigned int> shared_indices; hb_vector_t<unsigned int> shared_indices;
GlyphVarData::tuple_iterator_t iterator; GlyphVarData::tuple_iterator_t iterator;
if (!GlyphVarData::get_tuple_iterator (var_data, var_data_bytes.length, if (!GlyphVarData::get_tuple_iterator (var_data_bytes, gvar_table->axisCount,
gvar_table->axisCount, shared_indices, &iterator))
shared_indices,
&iterator))
return true; /* so isn't applied at all */ return true; /* so isn't applied at all */
/* Save original points for inferred delta calculation */ /* Save original points for inferred delta calculation */
@ -599,7 +589,7 @@ struct gvar
if (scalar == 0.f) continue; if (scalar == 0.f) continue;
const HBUINT8 *p = iterator.get_serialized_data (); const HBUINT8 *p = iterator.get_serialized_data ();
unsigned int length = iterator.current_tuple->get_data_size (); unsigned int length = iterator.current_tuple->get_data_size ();
if (unlikely (!iterator.in_range (p, length))) if (unlikely (!iterator.var_data_bytes.check_range (p, length)))
return false; return false;
hb_bytes_t bytes ((const char *) p, length); hb_bytes_t bytes ((const char *) p, length);