[PATCH v7 0/4] MR10612: gdi32/uniscribe: Fix heap buffer overflow in ScriptStringAnalyse().
Hi, I came across this bug while solving another issue. Steps to reproduce: 1. Open wine notepad 2. Start spamming any character that requires mark_invalid_combinations() in the notepad, such as: َ (0x064e Arabic Fatha) 3. At nearly 41 inserted Fatha, notepad will crash -- v7: riched20: Increase max_glyphs size. gdi32/uniscribe: Perform bounds check in GSUB_apply_MultipleSubst(). gdi32/uniscribe: Resize the buffers if glyph count exceeds limit. gdi32/uniscribe: Perform bounds check in insert_glyph(). https://gitlab.winehq.org/wine/wine/-/merge_requests/10612
From: समीर सिंह Sameer Singh <lumarzeli30@gmail.com> Check if the current number of glyphs exceed the maximum limit and then return an E_OUTOFMEMORY. Modify the shaping functions to bubble this error so that it can be dealt with. --- dlls/gdi32/uniscribe/shape.c | 197 ++++++++++++++++---------- dlls/gdi32/uniscribe/usp10_internal.h | 2 +- 2 files changed, 124 insertions(+), 75 deletions(-) diff --git a/dlls/gdi32/uniscribe/shape.c b/dlls/gdi32/uniscribe/shape.c index 9f67b99c11d..a3c026a9982 100644 --- a/dlls/gdi32/uniscribe/shape.c +++ b/dlls/gdi32/uniscribe/shape.c @@ -24,6 +24,7 @@ #include "windef.h" #include "winbase.h" #include "ntgdi.h" +#include "winerror.h" #include "winuser.h" #include "winnls.h" #include "usp10.h" @@ -38,29 +39,29 @@ WINE_DEFAULT_DEBUG_CHANNEL(uniscribe); #define FIRST_ARABIC_CHAR 0x0600 #define LAST_ARABIC_CHAR 0x06ff -typedef VOID (*ContextualShapingProc)(HDC, ScriptCache*, SCRIPT_ANALYSIS*, +typedef HRESULT (*ContextualShapingProc)(HDC, ScriptCache*, SCRIPT_ANALYSIS*, WCHAR*, INT, WORD*, INT*, INT, WORD*); -static void ContextualShape_Control(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Hebrew(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Thaana(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Phags_pa(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Thai(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Lao(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Sinhala(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Devanagari(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Bengali(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Gurmukhi(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Gujarati(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Oriya(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Tamil(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Telugu(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Kannada(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Malayalam(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Khmer(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); -static void ContextualShape_Mongolian(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Control(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Hebrew(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Thaana(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Phags_pa(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Thai(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Lao(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Sinhala(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Devanagari(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Bengali(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Gurmukhi(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Gujarati(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Oriya(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Tamil(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Telugu(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Kannada(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Malayalam(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Khmer(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static HRESULT ContextualShape_Mongolian(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); typedef VOID (*ShapeCharGlyphPropProc)( HDC , ScriptCache*, SCRIPT_ANALYSIS*, const WCHAR*, const INT, const WORD*, const INT, WORD*, SCRIPT_CHARPROP*, SCRIPT_GLYPHPROP*); @@ -892,9 +893,11 @@ static inline BOOL get_GSUB_Indic2(SCRIPT_ANALYSIS *psa, ScriptCache *psc) return(SUCCEEDED(hr)); } -static void insert_glyph(WORD *pwGlyphs, INT *pcGlyphs, INT cChars, INT write_dir, WORD glyph, INT index, WORD *pwLogClust) +static HRESULT insert_glyph(WORD *pwGlyphs, INT *pcGlyphs, INT cChars, INT write_dir, WORD glyph, INT index, WORD *pwLogClust, INT maxGlyphs) { int i; + if (*pcGlyphs+1 >= maxGlyphs) + return E_OUTOFMEMORY; for (i = *pcGlyphs; i>=index; i--) pwGlyphs[i+1] = pwGlyphs[i]; pwGlyphs[index] = glyph; @@ -903,14 +906,16 @@ static void insert_glyph(WORD *pwGlyphs, INT *pcGlyphs, INT cChars, INT write_di UpdateClusters(index-3, 1, write_dir, cChars, pwLogClust); else UpdateClusters(index, 1, write_dir, cChars, pwLogClust); + return S_OK; } -static void mark_invalid_combinations(HDC hdc, const WCHAR* pwcChars, INT cChars, WORD *pwGlyphs, INT *pcGlyphs, INT write_dir, WORD *pwLogClust, combining_lexical_function lex) +static HRESULT mark_invalid_combinations(HDC hdc, const WCHAR* pwcChars, INT cChars, WORD *pwGlyphs, INT *pcGlyphs, INT write_dir, WORD *pwLogClust, INT maxGlyphs, combining_lexical_function lex) { CHAR *context_type; int i,g; WCHAR invalid = 0x25cc; WORD invalid_glyph; + HRESULT hr = S_OK; context_type = malloc(cChars); @@ -923,15 +928,18 @@ static void mark_invalid_combinations(HDC hdc, const WCHAR* pwcChars, INT cChars { if (context_type[i] != 0 && context_type[i+write_dir]==context_type[i]) { - insert_glyph(pwGlyphs, pcGlyphs, cChars, write_dir, invalid_glyph, g, pwLogClust); + hr = insert_glyph(pwGlyphs, pcGlyphs, cChars, write_dir, invalid_glyph, g, pwLogClust, maxGlyphs); + if (FAILED(hr)) + break; g++; } } free(context_type); + return hr; } -static void ContextualShape_Control(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Control(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { int i; for (i=0; i < cChars; i++) @@ -949,6 +957,7 @@ static void ContextualShape_Control(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS * pwOutGlyphs[i] = psc->sfp.wgBlank; } } + return S_OK; } static WCHAR neighbour_char(int i, int delta, const WCHAR* chars, INT cchLen) @@ -1054,7 +1063,7 @@ static int combining_lexical_Arabic(WCHAR c) /* * ContextualShape_Arabic */ -static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { CHAR *context_type; INT *context_shape; @@ -1062,11 +1071,12 @@ static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p int i; int char_index; int glyph_index; + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } if (psa->fLogicalOrder && psa->fRTL) @@ -1176,7 +1186,8 @@ static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p free(context_shape); free(context_type); - mark_invalid_combinations(hdc, pwcChars, cChars, pwOutGlyphs, pcGlyphs, dirL, pwLogClust, combining_lexical_Arabic); + hr = mark_invalid_combinations(hdc, pwcChars, cChars, pwOutGlyphs, pcGlyphs, dirL, pwLogClust, cMaxGlyphs, combining_lexical_Arabic); + return hr; } static int combining_lexical_Hebrew(WCHAR c) @@ -1236,14 +1247,15 @@ static int combining_lexical_Hebrew(WCHAR c) } } -static void ContextualShape_Hebrew(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Hebrew(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { INT dirL; + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } if (!psa->fLogicalOrder && psa->fRTL) @@ -1251,7 +1263,8 @@ static void ContextualShape_Hebrew(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p else dirL = 1; - mark_invalid_combinations(hdc, pwcChars, cChars, pwOutGlyphs, pcGlyphs, dirL, pwLogClust, combining_lexical_Hebrew); + hr = mark_invalid_combinations(hdc, pwcChars, cChars, pwOutGlyphs, pcGlyphs, dirL, pwLogClust, cMaxGlyphs, combining_lexical_Hebrew); + return hr; } /* @@ -1310,7 +1323,7 @@ static int combining_lexical_Syriac(WCHAR c) #define DALATH 0x715 #define RISH 0x72A -static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { CHAR *context_type; INT *context_shape; @@ -1318,11 +1331,12 @@ static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p int i; int char_index; int glyph_index; + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } if (!psa->fLogicalOrder && psa->fRTL) @@ -1339,7 +1353,7 @@ static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p load_ot_tables(hdc, psc); if (!psc->GSUB_Table) - return; + return E_INVALIDARG; context_type = malloc(cChars); context_shape = malloc(cChars * sizeof(*context_shape)); @@ -1424,7 +1438,8 @@ right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa))) free(context_shape); free(context_type); - mark_invalid_combinations(hdc, pwcChars, cChars, pwOutGlyphs, pcGlyphs, dirL, pwLogClust, combining_lexical_Syriac); + hr = mark_invalid_combinations(hdc, pwcChars, cChars, pwOutGlyphs, pcGlyphs, dirL, pwLogClust, cMaxGlyphs, combining_lexical_Syriac); + return hr; } static int combining_lexical_Thaana(WCHAR c) @@ -1447,14 +1462,15 @@ static int combining_lexical_Thaana(WCHAR c) } } -static void ContextualShape_Thaana(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Thaana(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { INT dirL; + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } if (!psa->fLogicalOrder && psa->fRTL) @@ -1462,7 +1478,8 @@ static void ContextualShape_Thaana(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p else dirL = 1; - mark_invalid_combinations(hdc, pwcChars, cChars, pwOutGlyphs, pcGlyphs, dirL, pwLogClust, combining_lexical_Thaana); + hr = mark_invalid_combinations(hdc, pwcChars, cChars, pwOutGlyphs, pcGlyphs, dirL, pwLogClust, cMaxGlyphs, combining_lexical_Thaana); + return hr; } /* @@ -1473,18 +1490,19 @@ static void ContextualShape_Thaana(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p #define phags_pa_START 0xA840 #define phags_pa_END 0xA87F -static void ContextualShape_Phags_pa(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Phags_pa(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { INT *context_shape; INT dirR, dirL; int i; int char_index; int glyph_index; + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } if (!psa->fLogicalOrder && psa->fRTL) @@ -1501,7 +1519,7 @@ static void ContextualShape_Phags_pa(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS load_ot_tables(hdc, psc); if (!psc->GSUB_Table) - return; + return E_INVALIDARG; context_shape = malloc(cChars * sizeof(*context_shape)); @@ -1561,6 +1579,7 @@ static void ContextualShape_Phags_pa(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS } free(context_shape); + return hr; } static int combining_lexical_Thai(WCHAR c) @@ -1590,14 +1609,15 @@ static int combining_lexical_Thai(WCHAR c) } } -static void ContextualShape_Thai(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Thai(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { INT dirL; + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } if (!psa->fLogicalOrder && psa->fRTL) @@ -1605,7 +1625,8 @@ static void ContextualShape_Thai(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa else dirL = 1; - mark_invalid_combinations(hdc, pwcChars, cChars, pwOutGlyphs, pcGlyphs, dirL, pwLogClust, combining_lexical_Thai); + hr = mark_invalid_combinations(hdc, pwcChars, cChars, pwOutGlyphs, pcGlyphs, dirL, pwLogClust, cMaxGlyphs, combining_lexical_Thai); + return hr; } static int combining_lexical_Lao(WCHAR c) @@ -1634,14 +1655,15 @@ static int combining_lexical_Lao(WCHAR c) } } -static void ContextualShape_Lao(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Lao(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { INT dirL; + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } if (!psa->fLogicalOrder && psa->fRTL) @@ -1649,7 +1671,8 @@ static void ContextualShape_Lao(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, else dirL = 1; - mark_invalid_combinations(hdc, pwcChars, cChars, pwOutGlyphs, pcGlyphs, dirL, pwLogClust, combining_lexical_Lao); + hr = mark_invalid_combinations(hdc, pwcChars, cChars, pwOutGlyphs, pcGlyphs, dirL, pwLogClust, cMaxGlyphs, combining_lexical_Lao); + return hr; } static void ReplaceInsertChars(HDC hdc, INT cWalk, INT* pcChars, WCHAR *pwOutChars, const WCHAR *replacements) @@ -2284,18 +2307,19 @@ static const VowelComponents Sinhala_vowels[] = { {0x0DDE, {0x0DD9,0x0DDE,0x0}}, {0x0000, {0x0000,0x0000,0x0}}}; -static void ContextualShape_Sinhala(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Sinhala(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { int cCount = cChars; int i; WCHAR *input; IndicSyllable *syllables = NULL; int syllable_count = 0; + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } input = malloc(3 * cChars * sizeof(*input)); @@ -2326,6 +2350,7 @@ static void ContextualShape_Sinhala(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS * free(input); free(syllables); + return hr; } static int devanagari_lex(WCHAR c) @@ -2352,18 +2377,19 @@ static const ConsonantComponents Devanagari_consonants[] ={ {{0x092F, 0x093C, 0x00000}, 0x095F}, {{0x0000, 0x0000, 0x00000}, 0x0000}}; -static void ContextualShape_Devanagari(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Devanagari(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { int cCount = cChars; WCHAR *input; IndicSyllable *syllables = NULL; int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } input = malloc(cChars * sizeof(*input)); @@ -2384,6 +2410,7 @@ static void ContextualShape_Devanagari(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSI free(input); free(syllables); + return hr; } static int bengali_lex(WCHAR c) @@ -2408,18 +2435,19 @@ static const ConsonantComponents Bengali_consonants[] = { {{0x09AF,0x09BC,0x0000}, 0x09DF}, {{0x0000,0x0000,0x0000}, 0x0000}}; -static void ContextualShape_Bengali(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Bengali(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { int cCount = cChars; WCHAR *input; IndicSyllable *syllables = NULL; int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } input = malloc(2 * cChars * sizeof(*input)); @@ -2454,6 +2482,7 @@ static void ContextualShape_Bengali(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS * free(input); free(syllables); + return hr; } static int gurmukhi_lex(WCHAR c) @@ -2472,18 +2501,19 @@ static const ConsonantComponents Gurmukhi_consonants[] = { {{0x0A2B,0x0A3C,0x0000}, 0x0A5E}, {{0x0000,0x0000,0x0000}, 0x0000}}; -static void ContextualShape_Gurmukhi(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Gurmukhi(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { int cCount = cChars; WCHAR *input; IndicSyllable *syllables = NULL; int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } input = malloc(cChars * sizeof(*input)); @@ -2504,6 +2534,7 @@ static void ContextualShape_Gurmukhi(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS free(input); free(syllables); + return hr; } static int gujarati_lex(WCHAR c) @@ -2516,18 +2547,19 @@ static int gujarati_lex(WCHAR c) } } -static void ContextualShape_Gujarati(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Gujarati(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { int cCount = cChars; WCHAR *input; IndicSyllable *syllables = NULL; int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } input = malloc(cChars * sizeof(*input)); @@ -2544,6 +2576,7 @@ static void ContextualShape_Gujarati(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS free(input); free(syllables); + return hr; } static int oriya_lex(WCHAR c) @@ -2567,18 +2600,19 @@ static const ConsonantComponents Oriya_consonants[] = { {{0x0B22,0x0B3C,0x0000}, 0x0B5D}, {{0x0000,0x0000,0x0000}, 0x0000}}; -static void ContextualShape_Oriya(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Oriya(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { int cCount = cChars; WCHAR *input; IndicSyllable *syllables = NULL; int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } input = malloc(2 * cChars * sizeof(*input)); @@ -2600,6 +2634,7 @@ static void ContextualShape_Oriya(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *ps free(input); free(syllables); + return hr; } static int tamil_lex(WCHAR c) @@ -2617,18 +2652,19 @@ static const ConsonantComponents Tamil_consonants[] = { {{0x0B92,0x0BD7,0x0000}, 0x0B94}, {{0x0000,0x0000,0x0000}, 0x0000}}; -static void ContextualShape_Tamil(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Tamil(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { int cCount = cChars; WCHAR *input; IndicSyllable *syllables = NULL; int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } input = malloc(2 * cChars * sizeof(*input)); @@ -2650,6 +2686,7 @@ static void ContextualShape_Tamil(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *ps free(input); free(syllables); + return hr; } static int telugu_lex(WCHAR c) @@ -2667,18 +2704,19 @@ static const VowelComponents Telugu_vowels[] = { {0x0C48, {0x0C46,0x0C56,0x0000}}, {0x0000, {0x0000,0x0000,0x0000}}}; -static void ContextualShape_Telugu(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Telugu(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { int cCount = cChars; WCHAR *input; IndicSyllable *syllables = NULL; int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } input = malloc(2 * cChars * sizeof(*input)); @@ -2699,6 +2737,7 @@ static void ContextualShape_Telugu(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p free(input); free(syllables); + return hr; } static int kannada_lex(WCHAR c) @@ -2719,18 +2758,19 @@ static const VowelComponents Kannada_vowels[] = { {0x0CCB, {0x0CC6,0x0CC2,0x0CD5}}, {0x0000, {0x0000,0x0000,0x0000}}}; -static void ContextualShape_Kannada(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Kannada(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { int cCount = cChars; WCHAR *input; IndicSyllable *syllables = NULL; int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } input = malloc(3 * cChars * sizeof(*input)); @@ -2751,6 +2791,7 @@ static void ContextualShape_Kannada(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS * free(input); free(syllables); + return hr; } static int malayalam_lex(WCHAR c) @@ -2764,18 +2805,19 @@ static const VowelComponents Malayalam_vowels[] = { {0x0D4C, {0x0D46,0x0D57,0x0000}}, {0x0000, {0x0000,0x0000,0x0000}}}; -static void ContextualShape_Malayalam(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Malayalam(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { int cCount = cChars; WCHAR *input; IndicSyllable *syllables = NULL; int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } input = malloc(2 * cChars * sizeof(*input)); @@ -2796,6 +2838,7 @@ static void ContextualShape_Malayalam(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS free(input); free(syllables); + return hr; } static int khmer_lex(WCHAR c) @@ -2803,17 +2846,18 @@ static int khmer_lex(WCHAR c) return unicode_lex(c); } -static void ContextualShape_Khmer(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Khmer(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { int cCount = cChars; WCHAR *input; IndicSyllable *syllables = NULL; int syllable_count = 0; + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } input = malloc(cChars * sizeof(*input)); @@ -2830,6 +2874,7 @@ static void ContextualShape_Khmer(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *ps free(input); free(syllables); + return hr; } static inline BOOL mongolian_wordbreak(WCHAR chr) @@ -2837,18 +2882,19 @@ static inline BOOL mongolian_wordbreak(WCHAR chr) return ((chr == 0x0020) || (chr == 0x200C) || (chr == 0x202F) || (chr == 0x180E) || (chr == 0x1800) || (chr == 0x1802) || (chr == 0x1803) || (chr == 0x1805) || (chr == 0x1808) || (chr == 0x1809) || (chr == 0x1807)); } -static void ContextualShape_Mongolian(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +static HRESULT ContextualShape_Mongolian(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { INT *context_shape; INT dirL; int i; int char_index; int glyph_index; + HRESULT hr = S_OK; if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); - return; + return E_INVALIDARG; } if (!psa->fLogicalOrder && psa->fRTL) @@ -2857,7 +2903,7 @@ static void ContextualShape_Mongolian(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS dirL = 1; if (!psc->GSUB_Table) - return; + return E_INVALIDARG; context_shape = malloc(cChars * sizeof(*context_shape)); @@ -2905,6 +2951,7 @@ static void ContextualShape_Mongolian(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS } free(context_shape); + return hr; } static void ShapeCharGlyphProp_Default( ScriptCache* psc, SCRIPT_ANALYSIS* psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD* pwLogClust, SCRIPT_CHARPROP* pCharProp, SCRIPT_GLYPHPROP* pGlyphProp) @@ -3391,12 +3438,14 @@ void SHAPE_CharGlyphProp(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const ShapeCharGlyphProp_Default(psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp); } -void SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +HRESULT SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { + HRESULT hr = S_OK; load_ot_tables(hdc, psc); if (ShapingData[psa->eScript].contextProc) - ShapingData[psa->eScript].contextProc(hdc, psc, psa, pwcChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust); + hr = ShapingData[psa->eScript].contextProc(hdc, psc, psa, pwcChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust); + return hr; } 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) diff --git a/dlls/gdi32/uniscribe/usp10_internal.h b/dlls/gdi32/uniscribe/usp10_internal.h index b8ae1fb1a57..d14464796c4 100644 --- a/dlls/gdi32/uniscribe/usp10_internal.h +++ b/dlls/gdi32/uniscribe/usp10_internal.h @@ -260,7 +260,7 @@ BOOL BIDI_GetStrengths(const WCHAR *string, unsigned int count, const SCRIPT_CONTROL *c, WORD *strength); INT BIDI_ReorderV2lLevel(int level, int *pIndices, const BYTE* plevel, int cch, BOOL fReverse); INT BIDI_ReorderL2vLevel(int level, int *pIndices, const BYTE* plevel, int cch, BOOL fReverse); -void SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, +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, -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10612
From: समीर सिंह Sameer Singh <lumarzeli30@gmail.com> --- dlls/gdi32/uniscribe/usp10.c | 85 +++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 21 deletions(-) diff --git a/dlls/gdi32/uniscribe/usp10.c b/dlls/gdi32/uniscribe/usp10.c index 43afbaac125..2880a5f1434 100644 --- a/dlls/gdi32/uniscribe/usp10.c +++ b/dlls/gdi32/uniscribe/usp10.c @@ -32,6 +32,7 @@ #include "winbase.h" #include "ntgdi.h" #include "ntuser.h" +#include "winerror.h" #include "winuser.h" #include "winnls.h" #include "winreg.h" @@ -1904,7 +1905,7 @@ HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const void *pString, int cString, SCRIPT_CONTROL sControl; SCRIPT_STATE sState; int i, num_items = cString + 1; - BYTE *BidiLevel; + BYTE *BidiLevel = NULL; WCHAR *iString = NULL; SCRIPT_ITEM *items; @@ -1985,21 +1986,19 @@ HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const void *pString, int cString, int tab_x = 0; if (!(analysis->glyphs = calloc(analysis->numItems, sizeof(*analysis->glyphs)))) - { - free(BidiLevel); goto error; - } for (i = 0; i < analysis->numItems; i++) { SCRIPT_CACHE *sc = (SCRIPT_CACHE*)&analysis->glyphs[i].sc; int cChar = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos; - int numGlyphs = 1.5 * cChar + 16; - WORD *glyphs = calloc(numGlyphs, sizeof(*glyphs)); + int multiplier = 2; + int numGlyphs; + WORD *glyphs = NULL; WORD *pwLogClust = calloc(cChar, sizeof(*pwLogClust)); - int *piAdvance = calloc(numGlyphs, sizeof(*piAdvance)); - SCRIPT_VISATTR *psva = calloc(numGlyphs, sizeof(*psva)); - GOFFSET *pGoffset = calloc(numGlyphs, sizeof(*pGoffset)); + int *piAdvance = NULL; + SCRIPT_VISATTR *psva = NULL; + GOFFSET *pGoffset = NULL; int numGlyphsReturned; HFONT originalFont = 0x0; @@ -2007,14 +2006,8 @@ HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const void *pString, int cString, const WCHAR* pStr = (const WCHAR*)pString; analysis->glyphs[i].fallbackFont = NULL; - if (!glyphs || !pwLogClust || !piAdvance || !psva || !pGoffset) + if (!pwLogClust) { - free(BidiLevel); - free(glyphs); - free(pwLogClust); - free(piAdvance); - free(psva); - free(pGoffset); hr = E_OUTOFMEMORY; goto error; } @@ -2044,13 +2037,57 @@ HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const void *pString, int cString, if ((dwFlags & SSA_LINK) && !analysis->glyphs[i].fallbackFont && !scriptInformation[analysis->pItem[i].a.eScript].props.fComplex && !analysis->pItem[i].a.fRTL) analysis->pItem[i].a.fNoGlyphIndex = TRUE; - ScriptShape(hdc, sc, &pStr[analysis->pItem[i].iCharPos], cChar, numGlyphs, - &analysis->pItem[i].a, glyphs, pwLogClust, psva, &numGlyphsReturned); - hr = ScriptPlace(hdc, sc, glyphs, numGlyphsReturned, psva, &analysis->pItem[i].a, - piAdvance, pGoffset, &analysis->glyphs[i].abc); + while (TRUE) + { + if (multiplier > 8) + { + hr = E_OUTOFMEMORY; + break; + } + + free(glyphs); + free(piAdvance); + free(psva); + free(pGoffset); + + numGlyphs = multiplier * cChar + 16; + glyphs = calloc(numGlyphs, sizeof(*glyphs)); + piAdvance = calloc(numGlyphs, sizeof(*piAdvance)); + psva = calloc(numGlyphs, sizeof(*psva)); + pGoffset = calloc(numGlyphs, sizeof(*pGoffset)); + + if (!glyphs || !piAdvance || !psva || !pGoffset) + { + hr = E_OUTOFMEMORY; + break; + } + + hr = ScriptShape(hdc, sc, &pStr[analysis->pItem[i].iCharPos], cChar, numGlyphs, + &analysis->pItem[i].a, glyphs, pwLogClust, psva, &numGlyphsReturned); + if (hr == E_OUTOFMEMORY) + { + multiplier *= 2; + continue; + } + + hr = ScriptPlace(hdc, sc, glyphs, numGlyphsReturned, psva, &analysis->pItem[i].a, + piAdvance, pGoffset, &analysis->glyphs[i].abc); + break; + } + if (originalFont) SelectObject(hdc,originalFont); + if (FAILED(hr)) + { + free(glyphs); + free(pwLogClust); + free(piAdvance); + free(psva); + free(pGoffset); + goto error; + } + if (dwFlags & SSA_TAB) { int tabi = 0; @@ -2088,6 +2125,7 @@ HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const void *pString, int cString, error: free(iString); + free(BidiLevel); free(analysis->glyphs); free(analysis->logattrs); free(analysis->pItem); @@ -3148,7 +3186,12 @@ HRESULT WINAPI ScriptShapeOpenType( HDC hdc, SCRIPT_CACHE *psc, } *pcGlyphs = g; - SHAPE_ContextualShaping(hdc, (ScriptCache *)*psc, psa, rChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust); + hr = SHAPE_ContextualShaping(hdc, (ScriptCache *)*psc, psa, rChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust); + if (FAILED(hr)) + { + free(rChars); + return hr; + } SHAPE_ApplyDefaultOpentypeFeatures(hdc, (ScriptCache *)*psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, cChars, pwLogClust); SHAPE_CharGlyphProp(hdc, (ScriptCache *)*psc, psa, pwcChars, cChars, pwOutGlyphs, *pcGlyphs, pwLogClust, pCharProps, pOutGlyphProps); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10612
From: समीर सिंह Sameer Singh <lumarzeli30@gmail.com> 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. --- dlls/gdi32/uniscribe/opentype.c | 39 +++-- dlls/gdi32/uniscribe/shape.c | 205 ++++++++++++++++---------- dlls/gdi32/uniscribe/usp10.c | 9 +- dlls/gdi32/uniscribe/usp10_internal.h | 5 +- 4 files changed, 164 insertions(+), 94 deletions(-) diff --git a/dlls/gdi32/uniscribe/opentype.c b/dlls/gdi32/uniscribe/opentype.c index b2a72b8c3ff..918762e7773 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"); @@ -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--) @@ -1070,7 +1073,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 +1140,9 @@ 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_OUTOFMEMORY) + return GSUB_E_OUTOFMEMORY; if (newIndex == GSUB_E_NOGLYPH) { ERR(" Chain failed to generate a glyph\n"); @@ -1224,7 +1229,9 @@ 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_OUTOFMEMORY) + return GSUB_E_OUTOFMEMORY; if (newIndex == GSUB_E_NOGLYPH) { ERR(" Chain failed to generate a glyph\n"); @@ -1241,7 +1248,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 +1391,9 @@ 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_OUTOFMEMORY) + return GSUB_E_OUTOFMEMORY; if (new_index == GSUB_E_NOGLYPH) ERR("Chain failed to generate a glyph.\n"); } @@ -1471,7 +1480,9 @@ 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_OUTOFMEMORY) + return GSUB_E_OUTOFMEMORY; if (new_index == GSUB_E_NOGLYPH) ERR("Chain failed to generate a glyph.\n"); } @@ -1481,7 +1492,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 +1529,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 +1548,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 a3c026a9982..ec7f5652fef 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,16 +555,18 @@ 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; } 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); + 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; } @@ -654,7 +656,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 +665,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 +726,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 +825,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 +851,9 @@ 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 (nextIndex == GSUB_E_OUTOFMEMORY) + return GSUB_E_OUTOFMEMORY; if (*pcGlyphs != prevCount) { UpdateClusters(nextIndex, *pcGlyphs - prevCount, write_dir, cChars, pwLogClust); @@ -1130,7 +1134,9 @@ 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"); + hr = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, cMaxGlyphs, "ccmp"); + if (hr == GSUB_E_OUTOFMEMORY) + return E_OUTOFMEMORY; if (prevCount != *pcGlyphs) { @@ -1140,8 +1146,9 @@ 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_OUTOFMEMORY) + return E_OUTOFMEMORY; if (nextIndex > GSUB_E_NOGLYPH) { UpdateClusters(glyph_index, *pcGlyphs - prevCount, dirL, cChars, pwLogClust); @@ -1405,8 +1412,9 @@ 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"); - + nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, cMaxGlyphs, "ccmp"); + if (nextIndex == GSUB_E_OUTOFMEMORY) + return E_OUTOFMEMORY; if (prevCount != *pcGlyphs) { offset = *pcGlyphs - prevCount; @@ -1415,7 +1423,9 @@ 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_OUTOFMEMORY) + return E_OUTOFMEMORY; if (nextIndex > GSUB_E_NOGLYPH) { UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust); @@ -1557,7 +1567,9 @@ 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_OUTOFMEMORY) + return E_OUTOFMEMORY; if (nextIndex > GSUB_E_NOGLYPH) { @@ -2017,18 +2029,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, 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); + 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); @@ -2038,6 +2053,8 @@ 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) @@ -2051,7 +2068,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 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; @@ -2063,7 +2080,9 @@ 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_OUTOFMEMORY) + return E_OUTOFMEMORY; if (nextIndex > GSUB_E_NOGLYPH) { UpdateClusters(nextIndex, *pcGlyphs - prevCount, 1, cChars, pwLogClust); @@ -2074,22 +2093,26 @@ 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, 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; 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_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) @@ -2105,7 +2128,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 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; @@ -2131,7 +2154,9 @@ 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_OUTOFMEMORY) + return E_OUTOFMEMORY; if (nextIndex > GSUB_E_NOGLYPH) { UpdateClusters(nextIndex, *pcGlyphs - prevCount, 1, cChars, pwLogClust); @@ -2148,9 +2173,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, 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; @@ -2166,6 +2214,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++) { @@ -2175,61 +2224,46 @@ 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, 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, 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, pwLogClust, lexical, &glyph_indices, akhn); - } + APPLY_BASIC(akhn); if (rphf) - Apply_Indic_Rphf(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, 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); + 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, 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, pwLogClust, lexical, &glyph_indices, "blwf"); + APPLY_PREBASE("blwf"); - Apply_Indic_PostBase(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indices, modern, "blwf"); + APPLY_POSTBASE("blwf"); } if (half) - Apply_Indic_PreBase(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, 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, 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, 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, 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) @@ -2346,7 +2380,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); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, sinhala_lex, NULL, TRUE); free(input); free(syllables); @@ -2406,7 +2440,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); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, devanagari_lex, NULL, modern); free(input); free(syllables); @@ -2443,6 +2477,7 @@ static HRESULT ContextualShape_Bengali(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSI int syllable_count = 0; BOOL modern = get_GSUB_Indic2(psa, psc); HRESULT hr = S_OK; + INT out_index; if (*pcGlyphs != cChars) { @@ -2473,13 +2508,19 @@ 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"); + 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, 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 hr; @@ -2530,7 +2571,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); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, gurmukhi_lex, NULL, modern); free(input); free(syllables); @@ -2572,7 +2613,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); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, gujarati_lex, NULL, modern); free(input); free(syllables); @@ -2630,7 +2671,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); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, oriya_lex, NULL, modern); free(input); free(syllables); @@ -2682,7 +2723,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); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, tamil_lex, SecondReorder_Like_Tamil, modern); free(input); free(syllables); @@ -2733,7 +2774,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); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, telugu_lex, SecondReorder_Like_Telugu, modern); free(input); free(syllables); @@ -2787,7 +2828,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); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, kannada_lex, SecondReorder_Like_Telugu, modern); free(input); free(syllables); @@ -2834,7 +2875,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); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, malayalam_lex, SecondReorder_Like_Tamil, modern); free(input); free(syllables); @@ -2870,7 +2911,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); + hr = ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust, khmer_lex, NULL, FALSE); free(input); free(syllables); @@ -2935,7 +2976,9 @@ 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_OUTOFMEMORY) + return E_OUTOFMEMORY; if (nextIndex > GSUB_E_NOGLYPH) { @@ -3448,18 +3491,19 @@ HRESULT SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, return hr; } -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; @@ -3469,16 +3513,23 @@ 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); + { + 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) { +HRESULT hr = S_OK; const TEXTRANGE_PROPERTIES *rpRangeProperties; rpRangeProperties = &ShapingData[psa->eScript].defaultTextRange; - SHAPE_ApplyOpenTypeFeatures(hdc, psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, cChars, rpRangeProperties, pwLogClust); + hr = SHAPE_ApplyOpenTypeFeatures(hdc, psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, cChars, rpRangeProperties, pwLogClust); + return hr; } 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 d14464796c4..7344a5b514d 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 @@ -263,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, @@ -297,7 +298,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/10612
From: समीर सिंह Sameer Singh <lumarzeli30@gmail.com> This is to accommodate GSUB substitutions done by complex fonts such as Noto Nastaliq Urdu. --- dlls/riched20/wrap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/riched20/wrap.c b/dlls/riched20/wrap.c index a4d638aec3d..49cbe2eea24 100644 --- a/dlls/riched20/wrap.c +++ b/dlls/riched20/wrap.c @@ -68,7 +68,7 @@ static HRESULT shape_run( ME_Context *c, ME_Run *run ) if (!run->glyphs) { - run->max_glyphs = 1.5 * run->len + 16; /* This is suggested in the uniscribe documentation */ + run->max_glyphs = 2 * run->len + 16; run->max_glyphs = (run->max_glyphs + 7) & ~7; /* Keep alignment simple */ get_run_glyph_buffers( run ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10612
Fiddling with the wordpad and riched led me to find another crash. To reproduce this paste a large block of arabic text in wordpad and try changing its font to "Noto Nastaliq Urdu". This will lead to a crash. Now in wrap.c there is a mechanism to grow the buffer in case of OOM. But there was a bounds check missing in `GSUB_apply_MultipleSubst` . If the patch seems busy, then tell me. I will try to think of something better. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10612#note_138563
participants (2)
-
समीर सिंह Sameer Singh -
समीरसिंह Sameer Singh (@ss141309)