[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); buffer->unsafe_to_break (buffer->idx, buffer->idx + 2);
} }
if (unlikely (!c->transition (this, entry))) c->transition (this, entry);
;//break; Ignore error.
state = machine.new_state (entry.newState); state = machine.new_state (entry.newState);
DEBUG_MSG (APPLY, nullptr, "s%d", state); DEBUG_MSG (APPLY, nullptr, "s%d", state);

View File

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

View File

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