[aat] Detect infinite-loops in state machine

This commit is contained in:
Behdad Esfahbod 2018-01-12 11:09:21 +01:00
parent d514f1480c
commit f7600228a4
1 changed files with 29 additions and 7 deletions

View File

@ -614,15 +614,23 @@ struct StateTableDriver
machine (machine_),
buffer (buffer_),
num_glyphs (face_->get_num_glyphs ()),
state (0),
last_zero (0) {}
last_zero (0)
{
dont_advance_set.init ();
}
inline ~StateTableDriver (void)
{
dont_advance_set.finish ();
}
template <typename context_t>
inline void drive (context_t *c)
{
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
unsigned int state = 0;
bool last_was_dont_advance = false;
for (buffer->idx = 0; buffer->idx <= count; buffer->idx++)
{
if (!state)
@ -637,8 +645,22 @@ struct StateTableDriver
c->transition (this, entry);
if (entry->flags & context_t::DontAdvance)
buffer->idx--; /* TODO Detect infinite loop. */
{
if (!last_was_dont_advance)
dont_advance_set.clear ();
unsigned int key = info[buffer->idx].codepoint | (state << 16);
if (likely (!dont_advance_set.has (key)))
{
dont_advance_set.add (key);
buffer->idx--;
last_was_dont_advance = true;
}
}
else
last_was_dont_advance = false;
state = entry->newState;
}
@ -649,11 +671,11 @@ struct StateTableDriver
public:
const StateTable<EntryData> &machine;
hb_buffer_t *buffer;
unsigned int num_glyphs;
unsigned int state;
unsigned int last_zero;
private:
hb_set_t dont_advance_set; /* Infinite-loop detection */
};