Implement will_overflow ().
This commit is contained in:
parent
6b1ea4cbe7
commit
8ebe5d734f
|
@ -50,6 +50,8 @@ struct graph_t
|
||||||
bool removed_nil = false;
|
bool removed_nil = false;
|
||||||
for (unsigned i = 0; i < objects.length; i++)
|
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
|
// 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.
|
// nil object. We don't need it for our purposes here so drop it.
|
||||||
if (i == 0 && !objects[i])
|
if (i == 0 && !objects[i])
|
||||||
|
@ -151,16 +153,79 @@ struct graph_t
|
||||||
/*
|
/*
|
||||||
* Will any offsets overflow on graph when it's serialized?
|
* Will any offsets overflow on graph when it's serialized?
|
||||||
*/
|
*/
|
||||||
bool will_overflow()
|
bool will_overflow ()
|
||||||
{
|
{
|
||||||
// TODO(garretrieger): implement me.
|
hb_map_t start_positions;
|
||||||
// - Check for offsets that exceed their width or;
|
hb_map_t end_positions;
|
||||||
// - are negative if using a non-signed link.
|
|
||||||
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
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.
|
* Updates all objidx's in all links using the provided mapping.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
* Google Author(s): Garret Rieger
|
* Google Author(s): Garret Rieger
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "hb-repacker.hh"
|
#include "hb-repacker.hh"
|
||||||
#include "hb-open-type.hh"
|
#include "hb-open-type.hh"
|
||||||
|
|
||||||
|
@ -70,6 +72,25 @@ populate_serializer_simple (hb_serialize_context_t* c)
|
||||||
c->end_serialize();
|
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
|
static void
|
||||||
populate_serializer_complex_1 (hb_serialize_context_t* c)
|
populate_serializer_complex_1 (hb_serialize_context_t* c)
|
||||||
{
|
{
|
||||||
|
@ -196,10 +217,34 @@ test_serialize ()
|
||||||
free (buffer_2);
|
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
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
test_serialize ();
|
test_serialize ();
|
||||||
test_sort_kahn_1 ();
|
test_sort_kahn_1 ();
|
||||||
test_sort_kahn_2 ();
|
test_sort_kahn_2 ();
|
||||||
|
test_will_overflow_1 ();
|
||||||
|
test_will_overflow_2 ();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue