[PATCH v4 0/3] MR10844: gdi32/uniscribe: Perform bounds check in GSUB_apply_MultipleSubst().
Check if the current number of glyphs exceed the maximum limit and then return an E_OUTOFMEMORY. Modify the functions to bubble this error so that it can be dealt with. -- v4: gdi32/uniscribe: Propagate GSUB_E_OUTOFMEMORY error. gdi32/uniscribe: Return GSUB_E_OUTOFMEMORY on lookup buffer overflow. gdi32/uniscribe: Pass maximum glyph count to GSUB lookup functions. https://gitlab.winehq.org/wine/wine/-/merge_requests/10844
From: समीर सिंह Sameer Singh <lumarzeli30@gmail.com> --- dlls/gdi32/uniscribe/opentype.c | 28 ++++---- dlls/gdi32/uniscribe/shape.c | 96 +++++++++++++-------------- dlls/gdi32/uniscribe/usp10_internal.h | 2 +- 3 files changed, 63 insertions(+), 63 deletions(-) diff --git a/dlls/gdi32/uniscribe/opentype.c b/dlls/gdi32/uniscribe/opentype.c index b2a72b8c3ff..faeb3e9ddb0 100644 --- a/dlls/gdi32/uniscribe/opentype.c +++ b/dlls/gdi32/uniscribe/opentype.c @@ -813,7 +813,7 @@ void OpenType_GDEF_UpdateGlyphProps(ScriptCache *psc, const WORD *pwGlyphs, cons /********** * GSUB **********/ -static INT GSUB_apply_lookup(const OT_LookupList* lookup, INT lookup_index, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count); +static INT GSUB_apply_lookup(const OT_LookupList* lookup, INT lookup_index, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count, INT max_glyphs); static int GSUB_is_glyph_covered(const void *table, unsigned int glyph) { @@ -924,7 +924,7 @@ static INT GSUB_apply_SingleSubst(const OT_LookupTable *look, WORD *glyphs, INT return GSUB_E_NOGLYPH; } -static INT GSUB_apply_MultipleSubst(const OT_LookupTable *look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count) +static INT GSUB_apply_MultipleSubst(const OT_LookupTable *look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count, INT max_glyphs) { int j; TRACE("Multiple Substitution Subtable\n"); @@ -1070,7 +1070,7 @@ static INT GSUB_apply_LigatureSubst(const OT_LookupTable *look, WORD *glyphs, IN return GSUB_E_NOGLYPH; } -static INT GSUB_apply_ContextSubst(const OT_LookupList* lookup, const OT_LookupTable *look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count) +static INT GSUB_apply_ContextSubst(const OT_LookupList* lookup, const OT_LookupTable *look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count, INT max_glyphs) { int j; TRACE("Context Substitution Subtable\n"); @@ -1137,7 +1137,7 @@ static INT GSUB_apply_ContextSubst(const OT_LookupList* lookup, const OT_LookupT } TRACE(" SUBST: %u -> %u %u.\n", l, sequence_index, lookup_index); - newIndex = GSUB_apply_lookup(lookup, lookup_index, glyphs, g, write_dir, glyph_count); + newIndex = GSUB_apply_lookup(lookup, lookup_index, glyphs, g, write_dir, glyph_count, max_glyphs); if (newIndex == GSUB_E_NOGLYPH) { ERR(" Chain failed to generate a glyph\n"); @@ -1224,7 +1224,7 @@ static INT GSUB_apply_ContextSubst(const OT_LookupList* lookup, const OT_LookupT } TRACE(" SUBST: %u -> %u %u.\n", l, sequence_index, lookup_index); - newIndex = GSUB_apply_lookup(lookup, lookup_index, glyphs, g, write_dir, glyph_count); + newIndex = GSUB_apply_lookup(lookup, lookup_index, glyphs, g, write_dir, glyph_count, max_glyphs); if (newIndex == GSUB_E_NOGLYPH) { ERR(" Chain failed to generate a glyph\n"); @@ -1241,7 +1241,7 @@ static INT GSUB_apply_ContextSubst(const OT_LookupList* lookup, const OT_LookupT return GSUB_E_NOGLYPH; } -static INT GSUB_apply_ChainContextSubst(const OT_LookupList* lookup, const OT_LookupTable *look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count) +static INT GSUB_apply_ChainContextSubst(const OT_LookupList* lookup, const OT_LookupTable *look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count, INT max_glyphs) { int j; @@ -1384,7 +1384,7 @@ static INT GSUB_apply_ChainContextSubst(const OT_LookupList* lookup, const OT_Lo } TRACE("SUBST: %u -> %u %u.\n", k, sequence_index, lookup_index); - new_index = GSUB_apply_lookup(lookup, lookup_index, glyphs, g, write_dir, glyph_count); + new_index = GSUB_apply_lookup(lookup, lookup_index, glyphs, g, write_dir, glyph_count, max_glyphs); if (new_index == GSUB_E_NOGLYPH) ERR("Chain failed to generate a glyph.\n"); } @@ -1471,7 +1471,7 @@ static INT GSUB_apply_ChainContextSubst(const OT_LookupList* lookup, const OT_Lo } TRACE("SUBST: %u -> %u %u.\n", k, sequence_index, lookup_index); - new_index = GSUB_apply_lookup(lookup, lookup_index, glyphs, g, write_dir, glyph_count); + new_index = GSUB_apply_lookup(lookup, lookup_index, glyphs, g, write_dir, glyph_count, max_glyphs); if (new_index == GSUB_E_NOGLYPH) ERR("Chain failed to generate a glyph.\n"); } @@ -1481,7 +1481,7 @@ static INT GSUB_apply_ChainContextSubst(const OT_LookupList* lookup, const OT_Lo return GSUB_E_NOGLYPH; } -static INT GSUB_apply_lookup(const OT_LookupList* lookup, INT lookup_index, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count) +static INT GSUB_apply_lookup(const OT_LookupList* lookup, INT lookup_index, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count, INT max_glyphs) { int offset; enum gsub_lookup_type type; @@ -1518,15 +1518,15 @@ static INT GSUB_apply_lookup(const OT_LookupList* lookup, INT lookup_index, WORD case GSUB_LOOKUP_SINGLE: return GSUB_apply_SingleSubst(look, glyphs, glyph_index, write_dir, glyph_count); case GSUB_LOOKUP_MULTIPLE: - return GSUB_apply_MultipleSubst(look, glyphs, glyph_index, write_dir, glyph_count); + return GSUB_apply_MultipleSubst(look, glyphs, glyph_index, write_dir, glyph_count, max_glyphs); case GSUB_LOOKUP_ALTERNATE: return GSUB_apply_AlternateSubst(look, glyphs, glyph_index, write_dir, glyph_count); case GSUB_LOOKUP_LIGATURE: return GSUB_apply_LigatureSubst(look, glyphs, glyph_index, write_dir, glyph_count); case GSUB_LOOKUP_CONTEXT: - return GSUB_apply_ContextSubst(lookup, look, glyphs, glyph_index, write_dir, glyph_count); + return GSUB_apply_ContextSubst(lookup, look, glyphs, glyph_index, write_dir, glyph_count, max_glyphs); case GSUB_LOOKUP_CONTEXT_CHAINED: - return GSUB_apply_ChainContextSubst(lookup, look, glyphs, glyph_index, write_dir, glyph_count); + return GSUB_apply_ChainContextSubst(lookup, look, glyphs, glyph_index, write_dir, glyph_count, max_glyphs); case GSUB_LOOKUP_EXTENSION: FIXME("Extension Substitution types not valid here\n"); break; @@ -1537,12 +1537,12 @@ static INT GSUB_apply_lookup(const OT_LookupList* lookup, INT lookup_index, WORD } int OpenType_apply_GSUB_lookup(const void *table, unsigned int lookup_index, WORD *glyphs, - unsigned int glyph_index, int write_dir, int *glyph_count) + unsigned int glyph_index, int write_dir, int *glyph_count, int max_glyphs) { const GSUB_Header *header = (const GSUB_Header *)table; const OT_LookupList *lookup = (const OT_LookupList*)((const BYTE*)header + GET_BE_WORD(header->LookupList)); - return GSUB_apply_lookup(lookup, lookup_index, glyphs, glyph_index, write_dir, glyph_count); + return GSUB_apply_lookup(lookup, lookup_index, glyphs, glyph_index, write_dir, glyph_count, max_glyphs); } /********** diff --git a/dlls/gdi32/uniscribe/shape.c b/dlls/gdi32/uniscribe/shape.c index baee7e3ec6e..223fe532710 100644 --- a/dlls/gdi32/uniscribe/shape.c +++ b/dlls/gdi32/uniscribe/shape.c @@ -547,7 +547,7 @@ static const ScriptShapeData ShapingData[] = extern scriptData scriptInformation[]; static int GSUB_apply_feature_all_lookups(const void *header, LoadedFeature *feature, - WORD *glyphs, unsigned int glyph_index, int write_dir, int *glyph_count) + WORD *glyphs, unsigned int glyph_index, int write_dir, int *glyph_count, int max_glyphs) { int i; int out_index = GSUB_E_NOGLYPH; @@ -555,7 +555,7 @@ static int GSUB_apply_feature_all_lookups(const void *header, LoadedFeature *fea TRACE("%i lookups\n", feature->lookup_count); for (i = 0; i < feature->lookup_count; i++) { - out_index = OpenType_apply_GSUB_lookup(header, feature->lookups[i], glyphs, glyph_index, write_dir, glyph_count); + out_index = OpenType_apply_GSUB_lookup(header, feature->lookups[i], glyphs, glyph_index, write_dir, glyph_count, max_glyphs); if (out_index != GSUB_E_NOGLYPH) break; } @@ -564,7 +564,7 @@ static int GSUB_apply_feature_all_lookups(const void *header, LoadedFeature *fea else { int out2; - out2 = GSUB_apply_feature_all_lookups(header, feature, glyphs, glyph_index, write_dir, glyph_count); + out2 = GSUB_apply_feature_all_lookups(header, feature, glyphs, glyph_index, write_dir, glyph_count, max_glyphs); if (out2!=GSUB_E_NOGLYPH) out_index = out2; } @@ -654,7 +654,7 @@ static LoadedFeature* load_OT_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache return feature; } -static INT apply_GSUB_feature_to_glyph(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, WORD *glyphs, INT index, INT write_dir, INT* glyph_count, const char* feat) +static INT apply_GSUB_feature_to_glyph(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, WORD *glyphs, INT index, INT write_dir, INT* glyph_count, INT max_glyphs, const char* feat) { LoadedFeature *feature; @@ -663,7 +663,7 @@ static INT apply_GSUB_feature_to_glyph(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCach return GSUB_E_NOFEATURE; TRACE("applying feature %s\n",feat); - return GSUB_apply_feature_all_lookups(psc->GSUB_Table, feature, glyphs, index, write_dir, glyph_count); + return GSUB_apply_feature_all_lookups(psc->GSUB_Table, feature, glyphs, index, write_dir, glyph_count, max_glyphs); } static VOID *load_gsub_table(HDC hdc) @@ -724,7 +724,7 @@ int SHAPE_does_GSUB_feature_apply_to_chars(HDC hdc, SCRIPT_ANALYSIS *psa, Script glyphs = calloc(count, 2 * sizeof(*glyphs)); NtGdiGetGlyphIndicesW(hdc, chars, count, glyphs, 0); - rc = apply_GSUB_feature_to_glyph(hdc, psa, psc, glyphs, 0, write_dir, &glyph_count, feature); + rc = apply_GSUB_feature_to_glyph(hdc, psa, psc, glyphs, 0, write_dir, &glyph_count, 2 * count, feature); if (rc > GSUB_E_NOGLYPH) rc = count - glyph_count; else @@ -823,7 +823,7 @@ static void UpdateClusters(int nextIndex, int changeCount, int write_dir, int ch } } -static int apply_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, WORD *pwOutGlyphs, int write_dir, INT* pcGlyphs, INT cChars, const char* feat, WORD *pwLogClust ) +static int apply_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, WORD *pwOutGlyphs, int write_dir, INT* pcGlyphs, INT cChars, INT cMaxGlyphs, const char* feat, WORD *pwLogClust ) { if (psc->GSUB_Table) { @@ -849,7 +849,7 @@ static int apply_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, W INT nextIndex; INT prevCount = *pcGlyphs; - nextIndex = OpenType_apply_GSUB_lookup(psc->GSUB_Table, feature->lookups[lookup_index], pwOutGlyphs, i, write_dir, pcGlyphs); + nextIndex = OpenType_apply_GSUB_lookup(psc->GSUB_Table, feature->lookups[lookup_index], pwOutGlyphs, i, write_dir, pcGlyphs, cMaxGlyphs); if (*pcGlyphs != prevCount) { UpdateClusters(nextIndex, *pcGlyphs - prevCount, write_dir, cChars, pwLogClust); @@ -1129,7 +1129,7 @@ static HRESULT ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS INT prevCount = *pcGlyphs; /* Apply CCMP first */ - apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, "ccmp"); + apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, cMaxGlyphs, "ccmp"); if (prevCount != *pcGlyphs) { @@ -1139,7 +1139,7 @@ static HRESULT ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS } /* Apply the contextual feature */ - nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, contextual_features[context_shape[char_index]]); + nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, cMaxGlyphs, contextual_features[context_shape[char_index]]); if (nextIndex > GSUB_E_NOGLYPH) { @@ -1400,7 +1400,7 @@ right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa))) INT prevCount = *pcGlyphs; /* Apply CCMP first */ - apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, "ccmp"); + apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, cMaxGlyphs, "ccmp"); if (prevCount != *pcGlyphs) { @@ -1410,7 +1410,7 @@ right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa))) } /* Apply the contextual feature */ - nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, contextual_features[context_shape[char_index]]); + nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, cMaxGlyphs, contextual_features[context_shape[char_index]]); if (nextIndex > GSUB_E_NOGLYPH) { UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust); @@ -1548,7 +1548,7 @@ static HRESULT ContextualShape_Phags_pa(HDC hdc, ScriptCache *psc, SCRIPT_ANALYS { INT nextIndex; INT prevCount = *pcGlyphs; - nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, contextual_features[context_shape[char_index]]); + nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, cMaxGlyphs, contextual_features[context_shape[char_index]]); if (nextIndex > GSUB_E_NOGLYPH) { @@ -2004,7 +2004,7 @@ static inline void shift_syllable_glyph_indices(IndicSyllable *glyph_index, INT glyph_index->pref+= shift; } -static void Apply_Indic_BasicForm(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index, LoadedFeature *feature ) +static void Apply_Indic_BasicForm(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index, LoadedFeature *feature ) { int index = glyph_index->start; @@ -2015,7 +2015,7 @@ static void Apply_Indic_BasicForm(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *ps { INT nextIndex; INT prevCount = *pcGlyphs; - nextIndex = GSUB_apply_feature_all_lookups(psc->GSUB_Table, feature, pwOutGlyphs, index, 1, pcGlyphs); + nextIndex = GSUB_apply_feature_all_lookups(psc->GSUB_Table, feature, pwOutGlyphs, index, 1, pcGlyphs, cMaxGlyphs); if (nextIndex > GSUB_E_NOGLYPH) { UpdateClusters(nextIndex, *pcGlyphs - prevCount, 1, cChars, pwLogClust); @@ -2038,7 +2038,7 @@ static inline INT find_consonant_halant(WCHAR* pwChars, INT index, INT end, lexi return -1; } -static void Apply_Indic_PreBase(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index, const char* feature) +static void Apply_Indic_PreBase(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index, const char* feature) { INT index, nextIndex; INT count,g_offset; @@ -2050,7 +2050,7 @@ static void Apply_Indic_PreBase(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, while (index >= 0 && index + g_offset < (glyph_index->base - glyph_index->start)) { INT prevCount = *pcGlyphs; - nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, index+glyph_index->start+g_offset, 1, pcGlyphs, feature); + nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, index+glyph_index->start+g_offset, 1, pcGlyphs, cMaxGlyphs, feature); if (nextIndex > GSUB_E_NOGLYPH) { UpdateClusters(nextIndex, *pcGlyphs - prevCount, 1, cChars, pwLogClust); @@ -2063,14 +2063,14 @@ static void Apply_Indic_PreBase(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, } } -static void Apply_Indic_Rphf(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index) +static void Apply_Indic_Rphf(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index) { INT nextIndex; INT prevCount = *pcGlyphs; if (syllable->ralf >= 0) { - nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index->ralf, 1, pcGlyphs, "rphf"); + nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index->ralf, 1, pcGlyphs, cMaxGlyphs, "rphf"); if (nextIndex > GSUB_E_NOGLYPH) { UpdateClusters(nextIndex, *pcGlyphs - prevCount, 1, cChars, pwLogClust); @@ -2092,7 +2092,7 @@ static inline INT find_halant_consonant(WCHAR* pwChars, INT index, INT end, lexi return -1; } -static void Apply_Indic_PostBase(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index, BOOL modern, const char* feat) +static void Apply_Indic_PostBase(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index, BOOL modern, const char* feat) { INT index, nextIndex; INT count, g_offset=0; @@ -2118,7 +2118,7 @@ static void Apply_Indic_PostBase(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa pwOutGlyphs[index+glyph_index->base+g_offset+1] = g; } - nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, index+glyph_index->base+g_offset, 1, pcGlyphs, feat); + nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, index+glyph_index->base+g_offset, 1, pcGlyphs, cMaxGlyphs, feat); if (nextIndex > GSUB_E_NOGLYPH) { UpdateClusters(nextIndex, *pcGlyphs - prevCount, 1, cChars, pwLogClust); @@ -2137,7 +2137,7 @@ static void Apply_Indic_PostBase(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa } } -static void ShapeIndicSyllables(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllables, INT syllable_count, WORD *pwOutGlyphs, INT* pcGlyphs, WORD *pwLogClust, lexical_function lexical, second_reorder_function second_reorder, BOOL modern) +static void ShapeIndicSyllables(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllables, INT syllable_count, WORD *pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust, lexical_function lexical, second_reorder_function second_reorder, BOOL modern) { int c; int overall_shift = 0; @@ -2164,52 +2164,52 @@ static void ShapeIndicSyllables(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, if (locl) { TRACE("applying feature locl\n"); - Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indices, locl); + Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, locl); } if (nukt) { TRACE("applying feature nukt\n"); - Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indices, nukt); + Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, nukt); } if (akhn) { TRACE("applying feature akhn\n"); - Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indices, akhn); + Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, akhn); } if (rphf) - Apply_Indic_Rphf(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indices); + Apply_Indic_Rphf(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices); if (rkrf) { TRACE("applying feature rkrf\n"); - Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indices, rkrf); + Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, rkrf); } if (pref) - Apply_Indic_PostBase(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indices, modern, "pref"); + Apply_Indic_PostBase(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, modern, "pref"); if (blwf) { if (!modern) - Apply_Indic_PreBase(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indices, "blwf"); + Apply_Indic_PreBase(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, "blwf"); - Apply_Indic_PostBase(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indices, modern, "blwf"); + Apply_Indic_PostBase(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, modern, "blwf"); } if (half) - Apply_Indic_PreBase(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indices, "half"); + Apply_Indic_PreBase(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, "half"); if (pstf) { TRACE("applying feature pstf\n"); - Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indices, pstf); + Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, pstf); } if (vatu) { TRACE("applying feature vatu\n"); - Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indices, vatu); + Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, vatu); } if (cjct) { TRACE("applying feature cjct\n"); - Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indices, cjct); + Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, cjct); } if (second_reorder) @@ -2332,7 +2332,7 @@ static HRESULT ContextualShape_Sinhala(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSI /* Step 4: Base Form application to syllables */ NtGdiGetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0); *pcGlyphs = cCount; - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, sinhala_lex, NULL, TRUE); + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, sinhala_lex, NULL, TRUE); free(input); free(syllables); @@ -2391,7 +2391,7 @@ static HRESULT ContextualShape_Devanagari(HDC hdc, ScriptCache *psc, SCRIPT_ANAL *pcGlyphs = cCount; /* Step 3: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, devanagari_lex, NULL, modern); + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, devanagari_lex, NULL, modern); free(input); free(syllables); @@ -2457,12 +2457,12 @@ static HRESULT ContextualShape_Bengali(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSI int gCount = 1; if (index > 0) index++; - apply_GSUB_feature_to_glyph(hdc, psa, psc, &pwOutGlyphs[index], 0, 1, &gCount, "init"); + apply_GSUB_feature_to_glyph(hdc, psa, psc, &pwOutGlyphs[index], 0, 1, &gCount, cMaxGlyphs, "init"); } } /* Step 4: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, bengali_lex, NULL, modern); + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, bengali_lex, NULL, modern); free(input); free(syllables); @@ -2513,7 +2513,7 @@ static HRESULT ContextualShape_Gurmukhi(HDC hdc, ScriptCache *psc, SCRIPT_ANALYS *pcGlyphs = cCount; /* Step 3: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, gurmukhi_lex, NULL, modern); + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, gurmukhi_lex, NULL, modern); free(input); free(syllables); @@ -2554,7 +2554,7 @@ static HRESULT ContextualShape_Gujarati(HDC hdc, ScriptCache *psc, SCRIPT_ANALYS *pcGlyphs = cCount; /* Step 2: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, gujarati_lex, NULL, modern); + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, gujarati_lex, NULL, modern); free(input); free(syllables); @@ -2611,7 +2611,7 @@ static HRESULT ContextualShape_Oriya(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *pcGlyphs = cCount; /* Step 3: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, oriya_lex, NULL, modern); + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, oriya_lex, NULL, modern); free(input); free(syllables); @@ -2662,7 +2662,7 @@ static HRESULT ContextualShape_Tamil(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *pcGlyphs = cCount; /* Step 3: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, tamil_lex, SecondReorder_Like_Tamil, modern); + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, tamil_lex, SecondReorder_Like_Tamil, modern); free(input); free(syllables); @@ -2712,7 +2712,7 @@ static HRESULT ContextualShape_Telugu(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *pcGlyphs = cCount; /* Step 3: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, telugu_lex, SecondReorder_Like_Telugu, modern); + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, telugu_lex, SecondReorder_Like_Telugu, modern); free(input); free(syllables); @@ -2765,7 +2765,7 @@ static HRESULT ContextualShape_Kannada(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSI *pcGlyphs = cCount; /* Step 3: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, kannada_lex, SecondReorder_Like_Telugu, modern); + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, kannada_lex, SecondReorder_Like_Telugu, modern); free(input); free(syllables); @@ -2811,7 +2811,7 @@ static HRESULT ContextualShape_Malayalam(HDC hdc, ScriptCache *psc, SCRIPT_ANALY *pcGlyphs = cCount; /* Step 3: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, malayalam_lex, SecondReorder_Like_Tamil, modern); + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, malayalam_lex, SecondReorder_Like_Tamil, modern); free(input); free(syllables); @@ -2846,7 +2846,7 @@ static HRESULT ContextualShape_Khmer(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *pcGlyphs = cCount; /* Step 2: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, khmer_lex, NULL, FALSE); + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, khmer_lex, NULL, FALSE); free(input); free(syllables); @@ -2910,7 +2910,7 @@ static HRESULT ContextualShape_Mongolian(HDC hdc, ScriptCache *psc, SCRIPT_ANALY { INT nextIndex; INT prevCount = *pcGlyphs; - nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, contextual_features[context_shape[char_index]]); + nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, cMaxGlyphs, contextual_features[context_shape[char_index]]); if (nextIndex > GSUB_E_NOGLYPH) { @@ -3443,7 +3443,7 @@ static void SHAPE_ApplyOpenTypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYS for (i = 0; i < rpRangeProperties->cotfRecords; i++) { if (rpRangeProperties->potfRecords[i].lParameter > 0) - apply_GSUB_feature(hdc, psa, psc, pwOutGlyphs, dirL, pcGlyphs, cChars, (const char*)&rpRangeProperties->potfRecords[i].tagFeature, pwLogClust); + apply_GSUB_feature(hdc, psa, psc, pwOutGlyphs, dirL, pcGlyphs, cChars, cMaxGlyphs, (const char*)&rpRangeProperties->potfRecords[i].tagFeature, pwLogClust); } } diff --git a/dlls/gdi32/uniscribe/usp10_internal.h b/dlls/gdi32/uniscribe/usp10_internal.h index d14464796c4..0ce7becefa4 100644 --- a/dlls/gdi32/uniscribe/usp10_internal.h +++ b/dlls/gdi32/uniscribe/usp10_internal.h @@ -297,7 +297,7 @@ DWORD OpenType_CMAP_GetGlyphIndex(HDC hdc, ScriptCache *psc, DWORD utf32c, LPWOR void OpenType_GDEF_UpdateGlyphProps(ScriptCache *psc, const WORD *pwGlyphs, const WORD cGlyphs, WORD *pwLogClust, const WORD cChars, SCRIPT_GLYPHPROP *pGlyphProp); int OpenType_apply_GSUB_lookup(const void *table, unsigned int lookup_index, WORD *glyphs, - unsigned int glyph_index, int write_dir, int *glyph_count); + unsigned int glyph_index, int write_dir, int *glyph_count, int max_glyphs); unsigned int OpenType_apply_GPOS_lookup(const ScriptCache *psc, const OUTLINETEXTMETRICW *otm, const LOGFONTW *logfont, const SCRIPT_ANALYSIS *analysis, int *advance, unsigned int lookup_index, const WORD *glyphs, unsigned int glyph_index, unsigned int glyph_count, GOFFSET *goffset); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10844
From: समीर सिंह Sameer Singh <lumarzeli30@gmail.com> --- dlls/gdi32/uniscribe/opentype.c | 11 +++++++++++ dlls/gdi32/uniscribe/shape.c | 6 +++++- dlls/gdi32/uniscribe/usp10_internal.h | 1 + 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/dlls/gdi32/uniscribe/opentype.c b/dlls/gdi32/uniscribe/opentype.c index faeb3e9ddb0..918762e7773 100644 --- a/dlls/gdi32/uniscribe/opentype.c +++ b/dlls/gdi32/uniscribe/opentype.c @@ -945,6 +945,9 @@ static INT GSUB_apply_MultipleSubst(const OT_LookupTable *look, WORD *glyphs, IN offset = GET_BE_WORD(msf1->Sequence[index]); seq = (const GSUB_Sequence*)((const BYTE*)msf1+offset); sub_count = GET_BE_WORD(seq->GlyphCount); + if (sub_count-1 > max_glyphs-*glyph_count) + return GSUB_E_OUTOFMEMORY; + TRACE(" Glyph 0x%x (+%i)->",glyphs[glyph_index],(sub_count-1)); for (j = (*glyph_count)+(sub_count-1); j > glyph_index; j--) @@ -1138,6 +1141,8 @@ static INT GSUB_apply_ContextSubst(const OT_LookupList* lookup, const OT_LookupT TRACE(" SUBST: %u -> %u %u.\n", l, sequence_index, lookup_index); newIndex = GSUB_apply_lookup(lookup, lookup_index, glyphs, g, write_dir, glyph_count, max_glyphs); + if (newIndex == GSUB_E_OUTOFMEMORY) + return GSUB_E_OUTOFMEMORY; if (newIndex == GSUB_E_NOGLYPH) { ERR(" Chain failed to generate a glyph\n"); @@ -1225,6 +1230,8 @@ static INT GSUB_apply_ContextSubst(const OT_LookupList* lookup, const OT_LookupT TRACE(" SUBST: %u -> %u %u.\n", l, sequence_index, lookup_index); newIndex = GSUB_apply_lookup(lookup, lookup_index, glyphs, g, write_dir, glyph_count, max_glyphs); + if (newIndex == GSUB_E_OUTOFMEMORY) + return GSUB_E_OUTOFMEMORY; if (newIndex == GSUB_E_NOGLYPH) { ERR(" Chain failed to generate a glyph\n"); @@ -1385,6 +1392,8 @@ static INT GSUB_apply_ChainContextSubst(const OT_LookupList* lookup, const OT_Lo TRACE("SUBST: %u -> %u %u.\n", k, sequence_index, lookup_index); new_index = GSUB_apply_lookup(lookup, lookup_index, glyphs, g, write_dir, glyph_count, max_glyphs); + if (new_index == GSUB_E_OUTOFMEMORY) + return GSUB_E_OUTOFMEMORY; if (new_index == GSUB_E_NOGLYPH) ERR("Chain failed to generate a glyph.\n"); } @@ -1472,6 +1481,8 @@ static INT GSUB_apply_ChainContextSubst(const OT_LookupList* lookup, const OT_Lo TRACE("SUBST: %u -> %u %u.\n", k, sequence_index, lookup_index); new_index = GSUB_apply_lookup(lookup, lookup_index, glyphs, g, write_dir, glyph_count, max_glyphs); + if (new_index == GSUB_E_OUTOFMEMORY) + return GSUB_E_OUTOFMEMORY; if (new_index == GSUB_E_NOGLYPH) ERR("Chain failed to generate a glyph.\n"); } diff --git a/dlls/gdi32/uniscribe/shape.c b/dlls/gdi32/uniscribe/shape.c index 223fe532710..76647cda415 100644 --- a/dlls/gdi32/uniscribe/shape.c +++ b/dlls/gdi32/uniscribe/shape.c @@ -561,10 +561,12 @@ static int GSUB_apply_feature_all_lookups(const void *header, LoadedFeature *fea } if (out_index == GSUB_E_NOGLYPH) TRACE("lookups found no glyphs\n"); - else + else if (out_index != GSUB_E_OUTOFMEMORY) { int out2; out2 = GSUB_apply_feature_all_lookups(header, feature, glyphs, glyph_index, write_dir, glyph_count, max_glyphs); + if (out2==GSUB_E_OUTOFMEMORY) + return GSUB_E_OUTOFMEMORY; if (out2!=GSUB_E_NOGLYPH) out_index = out2; } @@ -850,6 +852,8 @@ static int apply_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, W INT prevCount = *pcGlyphs; nextIndex = OpenType_apply_GSUB_lookup(psc->GSUB_Table, feature->lookups[lookup_index], pwOutGlyphs, i, write_dir, pcGlyphs, cMaxGlyphs); + if (nextIndex == GSUB_E_OUTOFMEMORY) + return GSUB_E_OUTOFMEMORY; if (*pcGlyphs != prevCount) { UpdateClusters(nextIndex, *pcGlyphs - prevCount, write_dir, cChars, pwLogClust); diff --git a/dlls/gdi32/uniscribe/usp10_internal.h b/dlls/gdi32/uniscribe/usp10_internal.h index 0ce7becefa4..fa62d08cdb2 100644 --- a/dlls/gdi32/uniscribe/usp10_internal.h +++ b/dlls/gdi32/uniscribe/usp10_internal.h @@ -135,6 +135,7 @@ enum usp10_script #define GSUB_E_NOFEATURE -20 #define GSUB_E_NOGLYPH -10 +#define GSUB_E_OUTOFMEMORY -30 #define FEATURE_ALL_TABLES 0 #define FEATURE_GSUB_TABLE 1 -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10844
From: समीर सिंह Sameer Singh <lumarzeli30@gmail.com> Propagate the error from OpenType features. --- dlls/gdi32/uniscribe/shape.c | 218 +++++++++++++++++--------- dlls/gdi32/uniscribe/usp10.c | 9 +- dlls/gdi32/uniscribe/usp10_internal.h | 2 +- 3 files changed, 156 insertions(+), 73 deletions(-) diff --git a/dlls/gdi32/uniscribe/shape.c b/dlls/gdi32/uniscribe/shape.c index 76647cda415..f05feab0bb1 100644 --- a/dlls/gdi32/uniscribe/shape.c +++ b/dlls/gdi32/uniscribe/shape.c @@ -1133,7 +1133,13 @@ static HRESULT ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS INT prevCount = *pcGlyphs; /* Apply CCMP first */ - apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, cMaxGlyphs, "ccmp"); + nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, cMaxGlyphs, "ccmp"); + if (nextIndex == GSUB_E_OUTOFMEMORY) + { + free(context_shape); + free(context_type); + return E_OUTOFMEMORY; + } if (prevCount != *pcGlyphs) { @@ -1144,7 +1150,12 @@ static HRESULT ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS /* Apply the contextual feature */ nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, cMaxGlyphs, contextual_features[context_shape[char_index]]); - + if (nextIndex == GSUB_E_OUTOFMEMORY) + { + free(context_shape); + free(context_type); + return E_OUTOFMEMORY; + } if (nextIndex > GSUB_E_NOGLYPH) { UpdateClusters(glyph_index, *pcGlyphs - prevCount, dirL, cChars, pwLogClust); @@ -1404,8 +1415,13 @@ right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa))) INT prevCount = *pcGlyphs; /* Apply CCMP first */ - apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, cMaxGlyphs, "ccmp"); - + nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, cMaxGlyphs, "ccmp"); + if (nextIndex == GSUB_E_OUTOFMEMORY) + { + free(context_shape); + free(context_type); + return E_OUTOFMEMORY; + } if (prevCount != *pcGlyphs) { offset = *pcGlyphs - prevCount; @@ -1415,6 +1431,12 @@ right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa))) /* Apply the contextual feature */ nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, cMaxGlyphs, contextual_features[context_shape[char_index]]); + if (nextIndex == GSUB_E_OUTOFMEMORY) + { + free(context_shape); + free(context_type); + return E_OUTOFMEMORY; + } if (nextIndex > GSUB_E_NOGLYPH) { UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust); @@ -1553,6 +1575,11 @@ static HRESULT ContextualShape_Phags_pa(HDC hdc, ScriptCache *psc, SCRIPT_ANALYS INT nextIndex; INT prevCount = *pcGlyphs; nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, cMaxGlyphs, contextual_features[context_shape[char_index]]); + if (nextIndex == GSUB_E_OUTOFMEMORY) + { + free(context_shape); + return E_OUTOFMEMORY; + } if (nextIndex > GSUB_E_NOGLYPH) { @@ -2008,18 +2035,21 @@ static inline void shift_syllable_glyph_indices(IndicSyllable *glyph_index, INT glyph_index->pref+= shift; } -static void Apply_Indic_BasicForm(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index, LoadedFeature *feature ) +static HRESULT Apply_Indic_BasicForm(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index, LoadedFeature *feature ) { int index = glyph_index->start; if (!feature) - return; + return S_OK; while(index <= glyph_index->end) { INT nextIndex; INT prevCount = *pcGlyphs; nextIndex = GSUB_apply_feature_all_lookups(psc->GSUB_Table, feature, pwOutGlyphs, index, 1, pcGlyphs, cMaxGlyphs); + if (nextIndex == GSUB_E_OUTOFMEMORY) + return E_OUTOFMEMORY; + if (nextIndex > GSUB_E_NOGLYPH) { UpdateClusters(nextIndex, *pcGlyphs - prevCount, 1, cChars, pwLogClust); @@ -2029,6 +2059,7 @@ static void Apply_Indic_BasicForm(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *ps else index++; } + return S_OK; } static inline INT find_consonant_halant(WCHAR* pwChars, INT index, INT end, lexical_function lexical) @@ -2042,7 +2073,7 @@ static inline INT find_consonant_halant(WCHAR* pwChars, INT index, INT end, lexi return -1; } -static void Apply_Indic_PreBase(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index, const char* feature) +static HRESULT Apply_Indic_PreBase(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index, const char* feature) { INT index, nextIndex; INT count,g_offset; @@ -2055,6 +2086,8 @@ static void Apply_Indic_PreBase(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, { INT prevCount = *pcGlyphs; nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, index+glyph_index->start+g_offset, 1, pcGlyphs, cMaxGlyphs, feature); + if (nextIndex == GSUB_E_OUTOFMEMORY) + return E_OUTOFMEMORY; if (nextIndex > GSUB_E_NOGLYPH) { UpdateClusters(nextIndex, *pcGlyphs - prevCount, 1, cChars, pwLogClust); @@ -2065,9 +2098,10 @@ static void Apply_Indic_PreBase(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, index+=2; index = find_consonant_halant(&pwChars[syllable->start], index, count, lexical); } + return S_OK; } -static void Apply_Indic_Rphf(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index) +static HRESULT Apply_Indic_Rphf(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index) { INT nextIndex; INT prevCount = *pcGlyphs; @@ -2075,12 +2109,15 @@ static void Apply_Indic_Rphf(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WC if (syllable->ralf >= 0) { nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index->ralf, 1, pcGlyphs, cMaxGlyphs, "rphf"); + if (nextIndex == GSUB_E_OUTOFMEMORY) + return E_OUTOFMEMORY; if (nextIndex > GSUB_E_NOGLYPH) { UpdateClusters(nextIndex, *pcGlyphs - prevCount, 1, cChars, pwLogClust); shift_syllable_glyph_indices(glyph_index,glyph_index->ralf,*pcGlyphs - prevCount); } } + return S_OK; } static inline INT find_halant_consonant(WCHAR* pwChars, INT index, INT end, lexical_function lexical) @@ -2096,7 +2133,7 @@ static inline INT find_halant_consonant(WCHAR* pwChars, INT index, INT end, lexi return -1; } -static void Apply_Indic_PostBase(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index, BOOL modern, const char* feat) +static HRESULT Apply_Indic_PostBase(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index, BOOL modern, const char* feat) { INT index, nextIndex; INT count, g_offset=0; @@ -2123,6 +2160,8 @@ static void Apply_Indic_PostBase(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa } nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, index+glyph_index->base+g_offset, 1, pcGlyphs, cMaxGlyphs, feat); + if (nextIndex == GSUB_E_OUTOFMEMORY) + return E_OUTOFMEMORY; if (nextIndex > GSUB_E_NOGLYPH) { UpdateClusters(nextIndex, *pcGlyphs - prevCount, 1, cChars, pwLogClust); @@ -2139,9 +2178,32 @@ static void Apply_Indic_PostBase(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa index+=2; index = find_halant_consonant(&pwChars[syllable->base], index, count, lexical); } + return S_OK; } -static void ShapeIndicSyllables(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllables, INT syllable_count, WORD *pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust, lexical_function lexical, second_reorder_function second_reorder, BOOL modern) +#define APPLY_BASIC(feature) do { \ + TRACE("applying feature %s\n", #feature); \ + hr = Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], \ + pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, \ + lexical, &glyph_indices, (feature)); \ + if (FAILED(hr)) return hr; \ +} while(0) + +#define APPLY_PREBASE(feature) do { \ + hr = Apply_Indic_PreBase(hdc, psc, psa, pwChars, cChars, &syllables[c], \ + pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, \ + lexical, &glyph_indices, (feature)); \ + if (FAILED(hr)) return hr; \ +} while(0) + +#define APPLY_POSTBASE(feature) do { \ + hr = Apply_Indic_PostBase(hdc, psc, psa, pwChars, cChars, &syllables[c], \ + pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, \ + lexical, &glyph_indices, modern, (feature)); \ + if (FAILED(hr)) return hr; \ +} while(0) + +static HRESULT ShapeIndicSyllables(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllables, INT syllable_count, WORD *pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust, lexical_function lexical, second_reorder_function second_reorder, BOOL modern) { int c; int overall_shift = 0; @@ -2157,6 +2219,7 @@ static void ShapeIndicSyllables(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, BOOL blwf = (load_OT_feature(hdc, psa, psc, FEATURE_GSUB_TABLE, "blwf") != NULL); BOOL half = (load_OT_feature(hdc, psa, psc, FEATURE_GSUB_TABLE, "half") != NULL); IndicSyllable glyph_indices; + HRESULT hr = S_OK; for (c = 0; c < syllable_count; c++) { @@ -2166,61 +2229,45 @@ static void ShapeIndicSyllables(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, old_end = glyph_indices.end; if (locl) - { - TRACE("applying feature locl\n"); - Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, locl); - } + APPLY_BASIC(locl); if (nukt) - { - TRACE("applying feature nukt\n"); - Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, nukt); - } + APPLY_BASIC(nukt); if (akhn) - { - TRACE("applying feature akhn\n"); - Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, akhn); - } + APPLY_BASIC(akhn); if (rphf) - Apply_Indic_Rphf(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices); - if (rkrf) { - TRACE("applying feature rkrf\n"); - Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, rkrf); + hr = Apply_Indic_Rphf(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices); + if (FAILED(hr)) + return hr; } + if (rkrf) + APPLY_BASIC(rkrf); if (pref) - Apply_Indic_PostBase(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, modern, "pref"); + APPLY_POSTBASE("pref"); if (blwf) { if (!modern) - Apply_Indic_PreBase(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, "blwf"); + APPLY_PREBASE("blwf"); - Apply_Indic_PostBase(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, modern, "blwf"); + APPLY_POSTBASE("blwf"); } if (half) - Apply_Indic_PreBase(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, "half"); + APPLY_PREBASE("half"); if (pstf) - { - TRACE("applying feature pstf\n"); - Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, pstf); - } + APPLY_BASIC(pstf); if (vatu) - { - TRACE("applying feature vatu\n"); - Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, vatu); - } + APPLY_BASIC(vatu); if (cjct) - { - TRACE("applying feature cjct\n"); - Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, lexical, &glyph_indices, cjct); - } + APPLY_BASIC(cjct); if (second_reorder) second_reorder(pwChars, &syllables[c], pwOutGlyphs, &glyph_indices, lexical); overall_shift += glyph_indices.end - old_end; } + return hr; } static inline int unicode_lex(WCHAR c) @@ -2305,6 +2352,7 @@ static HRESULT ContextualShape_Sinhala(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSI WCHAR *input; IndicSyllable *syllables = NULL; int syllable_count = 0; + HRESULT hr; if (*pcGlyphs != cChars) { @@ -2336,11 +2384,11 @@ static HRESULT ContextualShape_Sinhala(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSI /* Step 4: Base Form application to syllables */ NtGdiGetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0); *pcGlyphs = cCount; - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, sinhala_lex, NULL, TRUE); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, sinhala_lex, NULL, TRUE); free(input); free(syllables); - return S_OK; + return hr; } static int devanagari_lex(WCHAR c) @@ -2374,6 +2422,7 @@ static HRESULT ContextualShape_Devanagari(HDC hdc, ScriptCache *psc, SCRIPT_ANAL IndicSyllable *syllables = NULL; int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); + HRESULT hr; if (*pcGlyphs != cChars) { @@ -2395,11 +2444,11 @@ static HRESULT ContextualShape_Devanagari(HDC hdc, ScriptCache *psc, SCRIPT_ANAL *pcGlyphs = cCount; /* Step 3: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, devanagari_lex, NULL, modern); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, devanagari_lex, NULL, modern); free(input); free(syllables); - return S_OK; + return hr; } static int bengali_lex(WCHAR c) @@ -2431,6 +2480,8 @@ static HRESULT ContextualShape_Bengali(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSI IndicSyllable *syllables = NULL; int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); + HRESULT hr; + INT out_index; if (*pcGlyphs != cChars) { @@ -2461,16 +2512,22 @@ static HRESULT ContextualShape_Bengali(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSI int gCount = 1; if (index > 0) index++; - apply_GSUB_feature_to_glyph(hdc, psa, psc, &pwOutGlyphs[index], 0, 1, &gCount, cMaxGlyphs, "init"); + out_index = apply_GSUB_feature_to_glyph(hdc, psa, psc, &pwOutGlyphs[index], 0, 1, &gCount, cMaxGlyphs, "init"); + if (out_index == GSUB_E_OUTOFMEMORY) + { + hr = E_OUTOFMEMORY; + goto error; + } } } /* Step 4: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, bengali_lex, NULL, modern); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, bengali_lex, NULL, modern); + error: free(input); free(syllables); - return S_OK; + return hr; } static int gurmukhi_lex(WCHAR c) @@ -2496,6 +2553,7 @@ static HRESULT ContextualShape_Gurmukhi(HDC hdc, ScriptCache *psc, SCRIPT_ANALYS IndicSyllable *syllables = NULL; int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); + HRESULT hr; if (*pcGlyphs != cChars) { @@ -2517,11 +2575,11 @@ static HRESULT ContextualShape_Gurmukhi(HDC hdc, ScriptCache *psc, SCRIPT_ANALYS *pcGlyphs = cCount; /* Step 3: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, gurmukhi_lex, NULL, modern); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, gurmukhi_lex, NULL, modern); free(input); free(syllables); - return S_OK; + return hr; } static int gujarati_lex(WCHAR c) @@ -2541,6 +2599,7 @@ static HRESULT ContextualShape_Gujarati(HDC hdc, ScriptCache *psc, SCRIPT_ANALYS IndicSyllable *syllables = NULL; int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); + HRESULT hr; if (*pcGlyphs != cChars) { @@ -2558,11 +2617,11 @@ static HRESULT ContextualShape_Gujarati(HDC hdc, ScriptCache *psc, SCRIPT_ANALYS *pcGlyphs = cCount; /* Step 2: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, gujarati_lex, NULL, modern); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, gujarati_lex, NULL, modern); free(input); free(syllables); - return S_OK; + return hr; } static int oriya_lex(WCHAR c) @@ -2593,6 +2652,7 @@ static HRESULT ContextualShape_Oriya(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS IndicSyllable *syllables = NULL; int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); + HRESULT hr; if (*pcGlyphs != cChars) { @@ -2615,11 +2675,11 @@ static HRESULT ContextualShape_Oriya(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *pcGlyphs = cCount; /* Step 3: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, oriya_lex, NULL, modern); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, oriya_lex, NULL, modern); free(input); free(syllables); - return S_OK; + return hr; } static int tamil_lex(WCHAR c) @@ -2644,6 +2704,7 @@ static HRESULT ContextualShape_Tamil(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS IndicSyllable *syllables = NULL; int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); + HRESULT hr; if (*pcGlyphs != cChars) { @@ -2666,11 +2727,11 @@ static HRESULT ContextualShape_Tamil(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *pcGlyphs = cCount; /* Step 3: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, tamil_lex, SecondReorder_Like_Tamil, modern); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, tamil_lex, SecondReorder_Like_Tamil, modern); free(input); free(syllables); - return S_OK; + return hr; } static int telugu_lex(WCHAR c) @@ -2695,6 +2756,7 @@ static HRESULT ContextualShape_Telugu(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS IndicSyllable *syllables = NULL; int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); + HRESULT hr; if (*pcGlyphs != cChars) { @@ -2716,11 +2778,11 @@ static HRESULT ContextualShape_Telugu(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *pcGlyphs = cCount; /* Step 3: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, telugu_lex, SecondReorder_Like_Telugu, modern); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, telugu_lex, SecondReorder_Like_Telugu, modern); free(input); free(syllables); - return S_OK; + return hr; } static int kannada_lex(WCHAR c) @@ -2748,6 +2810,7 @@ static HRESULT ContextualShape_Kannada(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSI IndicSyllable *syllables = NULL; int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); + HRESULT hr; if (*pcGlyphs != cChars) { @@ -2769,11 +2832,11 @@ static HRESULT ContextualShape_Kannada(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSI *pcGlyphs = cCount; /* Step 3: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, kannada_lex, SecondReorder_Like_Telugu, modern); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, kannada_lex, SecondReorder_Like_Telugu, modern); free(input); free(syllables); - return S_OK; + return hr; } static int malayalam_lex(WCHAR c) @@ -2794,6 +2857,7 @@ static HRESULT ContextualShape_Malayalam(HDC hdc, ScriptCache *psc, SCRIPT_ANALY IndicSyllable *syllables = NULL; int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); + HRESULT hr; if (*pcGlyphs != cChars) { @@ -2815,11 +2879,11 @@ static HRESULT ContextualShape_Malayalam(HDC hdc, ScriptCache *psc, SCRIPT_ANALY *pcGlyphs = cCount; /* Step 3: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, malayalam_lex, SecondReorder_Like_Tamil, modern); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, malayalam_lex, SecondReorder_Like_Tamil, modern); free(input); free(syllables); - return S_OK; + return hr; } static int khmer_lex(WCHAR c) @@ -2833,6 +2897,7 @@ static HRESULT ContextualShape_Khmer(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS WCHAR *input; IndicSyllable *syllables = NULL; int syllable_count = 0; + HRESULT hr; if (*pcGlyphs != cChars) { @@ -2850,11 +2915,11 @@ static HRESULT ContextualShape_Khmer(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *pcGlyphs = cCount; /* Step 2: Base Form application to syllables */ - ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, khmer_lex, NULL, FALSE); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, khmer_lex, NULL, FALSE); free(input); free(syllables); - return S_OK; + return hr; } static inline BOOL mongolian_wordbreak(WCHAR chr) @@ -2915,6 +2980,11 @@ static HRESULT ContextualShape_Mongolian(HDC hdc, ScriptCache *psc, SCRIPT_ANALY INT nextIndex; INT prevCount = *pcGlyphs; nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, cMaxGlyphs, contextual_features[context_shape[char_index]]); + if (nextIndex == GSUB_E_OUTOFMEMORY) + { + free(context_shape); + return E_OUTOFMEMORY; + } if (nextIndex > GSUB_E_NOGLYPH) { @@ -3426,18 +3496,19 @@ HRESULT SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, return S_OK; } -static void SHAPE_ApplyOpenTypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, INT cChars, const TEXTRANGE_PROPERTIES *rpRangeProperties, WORD *pwLogClust) +static HRESULT SHAPE_ApplyOpenTypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, INT cChars, const TEXTRANGE_PROPERTIES *rpRangeProperties, WORD *pwLogClust) { int i; INT dirL; + INT out_index; if (!rpRangeProperties) - return; + return S_OK; load_ot_tables(hdc, psc); if (!psc->GSUB_Table) - return; + return S_OK; if (scriptInformation[psa->eScript].a.fRTL && (!psa->fLogicalOrder || !psa->fRTL)) dirL = -1; @@ -3447,16 +3518,21 @@ static void SHAPE_ApplyOpenTypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYS for (i = 0; i < rpRangeProperties->cotfRecords; i++) { if (rpRangeProperties->potfRecords[i].lParameter > 0) - apply_GSUB_feature(hdc, psa, psc, pwOutGlyphs, dirL, pcGlyphs, cChars, cMaxGlyphs, (const char*)&rpRangeProperties->potfRecords[i].tagFeature, pwLogClust); + { + out_index = apply_GSUB_feature(hdc, psa, psc, pwOutGlyphs, dirL, pcGlyphs, cChars, cMaxGlyphs, (const char*)&rpRangeProperties->potfRecords[i].tagFeature, pwLogClust); + if (out_index == GSUB_E_OUTOFMEMORY) + return E_OUTOFMEMORY; + } } + return S_OK; } -void SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, INT cChars, WORD *pwLogClust) +HRESULT SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, INT cChars, WORD *pwLogClust) { const TEXTRANGE_PROPERTIES *rpRangeProperties; rpRangeProperties = &ShapingData[psa->eScript].defaultTextRange; - SHAPE_ApplyOpenTypeFeatures(hdc, psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, cChars, rpRangeProperties, pwLogClust); + return SHAPE_ApplyOpenTypeFeatures(hdc, psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, cChars, rpRangeProperties, pwLogClust); } void SHAPE_ApplyOpenTypePositions(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WORD* pwGlyphs, INT cGlyphs, int *piAdvance, GOFFSET *pGoffset ) diff --git a/dlls/gdi32/uniscribe/usp10.c b/dlls/gdi32/uniscribe/usp10.c index 2880a5f1434..262df6056b2 100644 --- a/dlls/gdi32/uniscribe/usp10.c +++ b/dlls/gdi32/uniscribe/usp10.c @@ -3192,7 +3192,14 @@ HRESULT WINAPI ScriptShapeOpenType( HDC hdc, SCRIPT_CACHE *psc, free(rChars); return hr; } - SHAPE_ApplyDefaultOpentypeFeatures(hdc, (ScriptCache *)*psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, cChars, pwLogClust); + + hr = SHAPE_ApplyDefaultOpentypeFeatures(hdc, (ScriptCache *)*psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, cChars, pwLogClust); + if (FAILED(hr)) + { + free(rChars); + return hr; + } + SHAPE_CharGlyphProp(hdc, (ScriptCache *)*psc, psa, pwcChars, cChars, pwOutGlyphs, *pcGlyphs, pwLogClust, pCharProps, pOutGlyphProps); for (i = 0; i < cChars; ++i) diff --git a/dlls/gdi32/uniscribe/usp10_internal.h b/dlls/gdi32/uniscribe/usp10_internal.h index fa62d08cdb2..7344a5b514d 100644 --- a/dlls/gdi32/uniscribe/usp10_internal.h +++ b/dlls/gdi32/uniscribe/usp10_internal.h @@ -264,7 +264,7 @@ INT BIDI_ReorderL2vLevel(int level, int *pIndices, const BYTE* plevel, int cch, HRESULT SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -void SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, +HRESULT SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD *pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, INT cChars, WORD *pwLogClust); void SHAPE_ApplyOpenTypePositions(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10844
On Tue May 19 09:47:33 2026 +0000, Huw Davies wrote:
This will need splitting into smaller commits. hi @huw did you get a chance to look at the new commits?
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10844#note_141801
participants (2)
-
समीर सिंह Sameer Singh -
समीरसिंह Sameer Singh (@ss141309)