[PATCH v4 0/3] 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 -- v4: gdi32/uniscribe: Resize the buffers if glyph count exceeds limit. gdi32/uniscribe: Perform bounds check in insert_glyph(). gdi32/uniscribe: Fix heap buffer overflow in ScriptStringAnalyse(). https://gitlab.winehq.org/wine/wine/-/merge_requests/10612
From: समीर सिंह Sameer Singh <lumarzeli30@gmail.com> Increase the glyph buffer allocation to 2 * cChar + 16 to accommodate the worst case scenario in mark_invalid_combinations() where every character in a run requires an inserted dotted circle. --- dlls/gdi32/uniscribe/usp10.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/gdi32/uniscribe/usp10.c b/dlls/gdi32/uniscribe/usp10.c index 43afbaac125..3aea03b81f0 100644 --- a/dlls/gdi32/uniscribe/usp10.c +++ b/dlls/gdi32/uniscribe/usp10.c @@ -1994,7 +1994,7 @@ HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const void *pString, int cString, { 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; + int numGlyphs = 2 * cChar + 16; WORD *glyphs = calloc(numGlyphs, sizeof(*glyphs)); WORD *pwLogClust = calloc(cChar, sizeof(*pwLogClust)); int *piAdvance = calloc(numGlyphs, sizeof(*piAdvance)); -- 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 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 b0bd0c5a473..3a86cf7fc3e 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 | 87 +++++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 21 deletions(-) diff --git a/dlls/gdi32/uniscribe/usp10.c b/dlls/gdi32/uniscribe/usp10.c index 3aea03b81f0..394ec5f1ed6 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,18 @@ 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 = 2 * cChar + 16; - WORD *glyphs = calloc(numGlyphs, sizeof(*glyphs)); + 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,16 +2005,10 @@ 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; + goto cleanup_iter; } if ((dwFlags & SSA_FALLBACK) && requires_fallback(hdc, sc, &analysis->pItem[i].a, &pStr[analysis->pItem[i].iCharPos], cChar)) @@ -2044,10 +2036,46 @@ 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 (numGlyphs > 8 * cChar + 16) + { + hr = E_OUTOFMEMORY; + goto cleanup_iter; + } + + free(glyphs); + free(piAdvance); + free(psva); + free(pGoffset); + + 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; + goto cleanup_iter; + } + + hr = ScriptShape(hdc, sc, &pStr[analysis->pItem[i].iCharPos], cChar, numGlyphs, + &analysis->pItem[i].a, glyphs, pwLogClust, psva, &numGlyphsReturned); + if (hr == E_OUTOFMEMORY) + { + numGlyphs *= 2; + continue; + } + + hr = ScriptPlace(hdc, sc, glyphs, numGlyphsReturned, psva, &analysis->pItem[i].a, + piAdvance, pGoffset, &analysis->glyphs[i].abc); + if (FAILED(hr)) + goto cleanup_iter; + + break; + } + if (originalFont) SelectObject(hdc,originalFont); @@ -2071,6 +2099,17 @@ HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const void *pString, int cString, analysis->glyphs[i].iMaxPosX= -1; BidiLevel[i] = analysis->pItem[i].a.s.uBidiLevel; + continue; + + cleanup_iter: + if (originalFont) + SelectObject(hdc, originalFont); + free(glyphs); + free(pwLogClust); + free(piAdvance); + free(psva); + free(pGoffset); + goto error; } } else @@ -2088,6 +2127,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 +3188,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
I have made the new changes. Please review. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10612#note_137400
Aric Stewart (@aricstewart) commented about dlls/gdi32/uniscribe/usp10.c:
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 (numGlyphs > 8 * cChar + 16)
Why this magic number? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10612#note_137753
On Mon Apr 27 14:59:29 2026 +0000, Aric Stewart wrote:
Why this magic number? So we start with 2 * cChars + 16, and then you double below. 16 characters would be something like `2*16+16=48 ` doubled => `2*(2*16+16)=96` doubled again => `2*2*(2*16+16)=192`
Your boundry is `8 * 16 + 16 => 144` So you would get 2 passes out of this code really no matter what but it is strangely opaque. What may be more clear is to have a multiplier that starts at 2, Then above you can have `int numGlyphs = 2 * cChar + 16;` be `int numGlyphs = multiplier * cChar + 16;` Then in your look you iterate increasing multiplayer to something like 4. If above 4 then bail out. I think that would make this loop clearer -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10612#note_137755
On Mon Apr 27 15:12:03 2026 +0000, Aric Stewart wrote:
So we start with 2 * cChars + 16, and then you double below. 16 characters would be something like `2*16+16=48 ` doubled => `2*(2*16+16)=96` doubled again => `2*2*(2*16+16)=192` Your boundry is `8 * 16 + 16 => 144` So you would get 2 passes out of this code really no matter what but it is strangely opaque. What may be more clear is to have a multiplier that starts at 2, Then above you can have `int numGlyphs = 2 * cChar + 16;` be `int numGlyphs = multiplier * cChar + 16;` Then in your look you iterate increasing multiplayer to something like 4. If above 4 then bail out. I think that would make this loop clearer good point, I will do that.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10612#note_137759
participants (3)
-
Aric Stewart (@aricstewart) -
समीर सिंह Sameer Singh -
समीरसिंह Sameer Singh (@ss141309)