[aat] Detect infinite-loops in state machine
This commit is contained in:
parent
d514f1480c
commit
f7600228a4
|
@ -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 */
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue