Implement will_overflow ().
This commit is contained in:
parent
6b1ea4cbe7
commit
8ebe5d734f
|
@ -50,6 +50,8 @@ struct graph_t
|
|||
bool removed_nil = false;
|
||||
for (unsigned i = 0; i < objects.length; i++)
|
||||
{
|
||||
// TODO(grieger): check all links point to valid objects.
|
||||
|
||||
// If this graph came from a serialization buffer object 0 is the
|
||||
// nil object. We don't need it for our purposes here so drop it.
|
||||
if (i == 0 && !objects[i])
|
||||
|
@ -151,16 +153,79 @@ struct graph_t
|
|||
/*
|
||||
* Will any offsets overflow on graph when it's serialized?
|
||||
*/
|
||||
bool will_overflow()
|
||||
bool will_overflow ()
|
||||
{
|
||||
// TODO(garretrieger): implement me.
|
||||
// - Check for offsets that exceed their width or;
|
||||
// - are negative if using a non-signed link.
|
||||
hb_map_t start_positions;
|
||||
hb_map_t end_positions;
|
||||
|
||||
unsigned current_pos = 0;
|
||||
for (int i = objects_.length - 1; i >= 0; i--)
|
||||
{
|
||||
start_positions.set (i, current_pos);
|
||||
current_pos += objects_[i].tail - objects_[i].head;
|
||||
end_positions.set (i, current_pos);
|
||||
}
|
||||
|
||||
|
||||
for (unsigned parent_idx = 0; parent_idx < objects_.length; parent_idx++)
|
||||
{
|
||||
for (const auto& link : objects_[parent_idx].links)
|
||||
{
|
||||
int64_t offset = compute_offset (parent_idx,
|
||||
link,
|
||||
start_positions,
|
||||
end_positions);
|
||||
|
||||
if (!is_valid_offset (offset, link)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int64_t compute_offset (
|
||||
unsigned parent_idx,
|
||||
const hb_serialize_context_t::object_t::link_t& link,
|
||||
const hb_map_t& start_positions,
|
||||
const hb_map_t& end_positions)
|
||||
{
|
||||
unsigned child_idx = link.objidx;
|
||||
int64_t offset = 0;
|
||||
switch ((hb_serialize_context_t::whence_t) link.whence) {
|
||||
case hb_serialize_context_t::whence_t::Head:
|
||||
offset = start_positions[child_idx] - start_positions[parent_idx]; break;
|
||||
case hb_serialize_context_t::whence_t::Tail:
|
||||
offset = start_positions[child_idx] - end_positions[parent_idx]; break;
|
||||
case hb_serialize_context_t::whence_t::Absolute:
|
||||
offset = start_positions[child_idx]; break;
|
||||
}
|
||||
|
||||
assert (offset >= link.bias);
|
||||
offset -= link.bias;
|
||||
return offset;
|
||||
}
|
||||
|
||||
bool is_valid_offset (int64_t offset,
|
||||
const hb_serialize_context_t::object_t::link_t& link)
|
||||
{
|
||||
if (link.is_signed)
|
||||
{
|
||||
if (link.is_wide)
|
||||
return offset >= -((int64_t) 1 << 31) && offset < ((int64_t) 1 << 31);
|
||||
else
|
||||
return offset >= -(1 << 15) && offset < (1 << 15);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (link.is_wide)
|
||||
return offset >= 0 && offset < ((int64_t) 1 << 32);
|
||||
else
|
||||
return offset >= 0 && offset < (1 << 16);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates all objidx's in all links using the provided mapping.
|
||||
*/
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
* Google Author(s): Garret Rieger
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "hb-repacker.hh"
|
||||
#include "hb-open-type.hh"
|
||||
|
||||
|
@ -70,6 +72,25 @@ populate_serializer_simple (hb_serialize_context_t* c)
|
|||
c->end_serialize();
|
||||
}
|
||||
|
||||
static void
|
||||
populate_serializer_with_overflow (hb_serialize_context_t* c)
|
||||
{
|
||||
std::string large_string(40000, 'a');
|
||||
c->start_serialize<char> ();
|
||||
|
||||
unsigned obj_1 = add_object (large_string.c_str(), 40000, c);
|
||||
unsigned obj_2 = add_object (large_string.c_str(), 40000, c);
|
||||
unsigned obj_3 = add_object (large_string.c_str(), 40000, c);
|
||||
|
||||
start_object ("abc", 3, c);
|
||||
add_offset (obj_3, c);
|
||||
add_offset (obj_2, c);
|
||||
add_offset (obj_1, c);
|
||||
c->pop_pack ();
|
||||
|
||||
c->end_serialize();
|
||||
}
|
||||
|
||||
static void
|
||||
populate_serializer_complex_1 (hb_serialize_context_t* c)
|
||||
{
|
||||
|
@ -196,10 +217,34 @@ test_serialize ()
|
|||
free (buffer_2);
|
||||
}
|
||||
|
||||
static void test_will_overflow_1 ()
|
||||
{
|
||||
size_t buffer_size = 100;
|
||||
void* buffer = malloc (buffer_size);
|
||||
hb_serialize_context_t c (buffer, buffer_size);
|
||||
populate_serializer_complex_2 (&c);
|
||||
graph_t graph (c.object_graph ());
|
||||
|
||||
assert (!graph.will_overflow ());
|
||||
}
|
||||
|
||||
static void test_will_overflow_2 ()
|
||||
{
|
||||
size_t buffer_size = 160000;
|
||||
void* buffer = malloc (buffer_size);
|
||||
hb_serialize_context_t c (buffer, buffer_size);
|
||||
populate_serializer_with_overflow (&c);
|
||||
graph_t graph (c.object_graph ());
|
||||
|
||||
assert (graph.will_overflow ());
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
test_serialize ();
|
||||
test_sort_kahn_1 ();
|
||||
test_sort_kahn_2 ();
|
||||
test_will_overflow_1 ();
|
||||
test_will_overflow_2 ();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue