[AAT] Handle transition errors during machine operation

Before we used to give up.  Now, just ignore error and continue processing.

Fixes https://github.com/harfbuzz/harfbuzz/issues/1531
This commit is contained in:
Behdad Esfahbod 2019-01-24 18:01:07 +01:00
parent e234bb6a42
commit b976940243
3 changed files with 21 additions and 37 deletions

View File

@ -777,8 +777,7 @@ struct StateTableDriver
buffer->unsafe_to_break (buffer->idx, buffer->idx + 2);
}
if (unlikely (!c->transition (this, entry)))
;//break; Ignore error.
c->transition (this, entry);
state = machine.new_state (entry.newState);
DEBUG_MSG (APPLY, nullptr, "s%d", state);

View File

@ -232,7 +232,7 @@ struct KerxSubTableFormat1
{
return Format1EntryT::performAction (entry);
}
bool transition (StateTableDriver<Types, EntryData> *driver,
void transition (StateTableDriver<Types, EntryData> *driver,
const Entry<EntryData> &entry)
{
hb_buffer_t *buffer = driver->buffer;
@ -259,7 +259,7 @@ struct KerxSubTableFormat1
if (!c->sanitizer.check_array (actions, depth, tuple_count))
{
depth = 0;
return false;
return;
}
hb_mask_t kern_mask = c->plan->kern_mask;
@ -334,8 +334,6 @@ struct KerxSubTableFormat1
}
}
}
return true;
}
private:
@ -502,7 +500,7 @@ struct KerxSubTableFormat4
{
return entry.data.ankrActionIndex != 0xFFFF;
}
bool transition (StateTableDriver<Types, EntryData> *driver,
void transition (StateTableDriver<Types, EntryData> *driver,
const Entry<EntryData> &entry)
{
hb_buffer_t *buffer = driver->buffer;
@ -516,8 +514,7 @@ struct KerxSubTableFormat4
{
/* indexed into glyph outline. */
const HBUINT16 *data = &ankrData[entry.data.ankrActionIndex];
if (!c->sanitizer.check_array (data, 2))
return false;
if (!c->sanitizer.check_array (data, 2)) return;
HB_UNUSED unsigned int markControlPoint = *data++;
HB_UNUSED unsigned int currControlPoint = *data++;
hb_position_t markX = 0;
@ -532,7 +529,7 @@ struct KerxSubTableFormat4
currControlPoint,
HB_DIRECTION_LTR /*XXX*/,
&currX, &currY))
return true; /* True, such that the machine continues. */
return;
o.x_offset = markX - currX;
o.y_offset = markY - currY;
@ -543,8 +540,7 @@ struct KerxSubTableFormat4
{
/* Indexed into 'ankr' table. */
const HBUINT16 *data = &ankrData[entry.data.ankrActionIndex];
if (!c->sanitizer.check_array (data, 2))
return false;
if (!c->sanitizer.check_array (data, 2)) return;
unsigned int markAnchorPoint = *data++;
unsigned int currAnchorPoint = *data++;
const Anchor &markAnchor = c->ankr_table->get_anchor (c->buffer->info[mark].codepoint,
@ -562,8 +558,7 @@ struct KerxSubTableFormat4
case 2: /* Control Point Coordinate Actions. */
{
const FWORD *data = (const FWORD *) &ankrData[entry.data.ankrActionIndex];
if (!c->sanitizer.check_array (data, 4))
return false;
if (!c->sanitizer.check_array (data, 4)) return;
int markX = *data++;
int markY = *data++;
int currX = *data++;
@ -584,8 +579,6 @@ struct KerxSubTableFormat4
mark_set = true;
mark = buffer->idx;
}
return true;
}
private:

View File

@ -78,7 +78,7 @@ struct RearrangementSubtable
{
return (entry.flags & Verb) && start < end;
}
bool transition (StateTableDriver<Types, EntryData> *driver,
void transition (StateTableDriver<Types, EntryData> *driver,
const Entry<EntryData> &entry)
{
hb_buffer_t *buffer = driver->buffer;
@ -152,8 +152,6 @@ struct RearrangementSubtable
}
}
}
return true;
}
public:
@ -232,7 +230,7 @@ struct ContextualSubtable
return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF;
}
bool transition (StateTableDriver<Types, EntryData> *driver,
void transition (StateTableDriver<Types, EntryData> *driver,
const Entry<EntryData> &entry)
{
hb_buffer_t *buffer = driver->buffer;
@ -240,7 +238,7 @@ struct ContextualSubtable
/* Looks like CoreText applies neither mark nor current substitution for
* end-of-text if mark was not explicitly set. */
if (buffer->idx == buffer->len && !mark_set)
return true;
return;
const GlyphID *replacement;
@ -297,8 +295,6 @@ struct ContextualSubtable
mark_set = true;
mark = buffer->idx;
}
return true;
}
public:
@ -457,7 +453,7 @@ struct LigatureSubtable
{
return LigatureEntryT::performAction (entry);
}
bool transition (StateTableDriver<Types, EntryData> *driver,
void transition (StateTableDriver<Types, EntryData> *driver,
const Entry<EntryData> &entry)
{
hb_buffer_t *buffer = driver->buffer;
@ -466,7 +462,7 @@ struct LigatureSubtable
if (entry.flags & LigatureEntryT::SetComponent)
{
if (unlikely (match_length >= ARRAY_LENGTH (match_positions)))
return false;
match_length = 0; /* TODO Use a ring buffer instead. */
/* Never mark same index twice, in case DontAdvance was used... */
if (match_length && match_positions[match_length - 1] == buffer->out_len)
@ -482,10 +478,10 @@ struct LigatureSubtable
unsigned int end = buffer->out_len;
if (unlikely (!match_length))
return true;
return;
if (buffer->idx >= buffer->len)
return false; // TODO Work on previous instead?
return; // TODO Work on previous instead?
unsigned int cursor = match_length;
@ -508,7 +504,7 @@ struct LigatureSubtable
DEBUG_MSG (APPLY, nullptr, "Moving to stack position %u", cursor - 1);
buffer->move_to (match_positions[--cursor]);
if (unlikely (!actionData->sanitize (&c->sanitizer))) return false;
if (unlikely (!actionData->sanitize (&c->sanitizer))) break;
action = *actionData;
uint32_t uoffset = action & LigActionOffset;
@ -518,7 +514,7 @@ struct LigatureSubtable
unsigned int component_idx = buffer->cur().codepoint + offset;
component_idx = Types::wordOffsetToIndex (component_idx, table, component.arrayZ);
const HBUINT16 &componentData = component[component_idx];
if (unlikely (!componentData.sanitize (&c->sanitizer))) return false;
if (unlikely (!componentData.sanitize (&c->sanitizer))) break;
ligature_idx += componentData;
DEBUG_MSG (APPLY, nullptr, "Action store %u last %u",
@ -528,7 +524,7 @@ struct LigatureSubtable
{
ligature_idx = Types::offsetToIndex (ligature_idx, table, ligature.arrayZ);
const GlyphID &ligatureData = ligature[ligature_idx];
if (unlikely (!ligatureData.sanitize (&c->sanitizer))) return false;
if (unlikely (!ligatureData.sanitize (&c->sanitizer))) break;
hb_codepoint_t lig = ligatureData;
DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig);
@ -552,8 +548,6 @@ struct LigatureSubtable
while (!(action & LigActionLast));
buffer->move_to (end);
}
return true;
}
public:
@ -723,7 +717,7 @@ struct InsertionSubtable
return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) &&
(entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF);
}
bool transition (StateTableDriver<Types, EntryData> *driver,
void transition (StateTableDriver<Types, EntryData> *driver,
const Entry<EntryData> &entry)
{
hb_buffer_t *buffer = driver->buffer;
@ -736,7 +730,7 @@ struct InsertionSubtable
unsigned int count = (flags & MarkedInsertCount);
unsigned int start = entry.data.markedInsertIndex;
const GlyphID *glyphs = &insertionAction[start];
if (unlikely (!c->sanitizer.check_array (glyphs, count))) return false;
if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
bool before = flags & MarkedInsertBefore;
@ -764,7 +758,7 @@ struct InsertionSubtable
unsigned int count = (flags & CurrentInsertCount) >> 5;
unsigned int start = entry.data.currentInsertIndex;
const GlyphID *glyphs = &insertionAction[start];
if (unlikely (!c->sanitizer.check_array (glyphs, count))) return false;
if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
bool before = flags & CurrentInsertBefore;
@ -795,8 +789,6 @@ struct InsertionSubtable
*/
buffer->move_to ((flags & DontAdvance) ? end : end + count);
}
return true;
}
public: