[aat] Detect infinite-loops in state machine

pull/703/head
Behdad Esfahbod 7 years ago
parent d514f1480c
commit f7600228a4
  1. 36
      src/hb-aat-layout-common-private.hh

@ -614,15 +614,23 @@ struct StateTableDriver
machine (machine_), machine (machine_),
buffer (buffer_), buffer (buffer_),
num_glyphs (face_->get_num_glyphs ()), 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> template <typename context_t>
inline void drive (context_t *c) inline void drive (context_t *c)
{ {
hb_glyph_info_t *info = buffer->info; hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len; unsigned int count = buffer->len;
unsigned int state = 0;
bool last_was_dont_advance = false;
for (buffer->idx = 0; buffer->idx <= count; buffer->idx++) for (buffer->idx = 0; buffer->idx <= count; buffer->idx++)
{ {
if (!state) if (!state)
@ -637,8 +645,22 @@ struct StateTableDriver
c->transition (this, entry); c->transition (this, entry);
if (entry->flags & context_t::DontAdvance) 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; state = entry->newState;
} }
@ -649,11 +671,11 @@ struct StateTableDriver
public: public:
const StateTable<EntryData> &machine; const StateTable<EntryData> &machine;
hb_buffer_t *buffer; hb_buffer_t *buffer;
unsigned int num_glyphs; unsigned int num_glyphs;
unsigned int state;
unsigned int last_zero; unsigned int last_zero;
private:
hb_set_t dont_advance_set; /* Infinite-loop detection */
}; };

Loading…
Cancel
Save