[PATCH v8 0/2] 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 -- v8: 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
On Fri May 8 11:43:26 2026 +0000, Aric Stewart wrote:
I like this catch and think the changes are correct. I would howerver probably recommend it be a separate patch, because then it would be smaller, more surgical and easier to review and get merged in. I have noted a few places where we are possibly not catching buffer overflows, so there will likely be more patches in this area. thanks, shifted the last two commits to !10844
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10612#note_139207
Aric Stewart (@aricstewart) commented about dlls/gdi32/uniscribe/usp10.c:
+ 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; I do not think this needs to be multiplier *=2 just multiplier ++ would be more fine grained.
With *2 you start at 2, then get 4 then get 8, so at most 3 passes and seems excessive. But again that is just my opinion. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10612#note_139215
On Fri May 8 14:01:06 2026 +0000, Aric Stewart wrote:
I do not think this needs to be multiplier *=2 just multiplier ++ would be more fine grained. With *2 you start at 2, then get 4 then get 8, so at most 3 passes and seems excessive. But again that is just my opinion. I actually prefer \*2 for faster convergence. Since we have increased the buffer size from 1.5 to 2, OOM should only happen in rare cases and for those cases I would want it to resolve quickly.
Maybe we can increase the ceiling to something bigger to get more passes if you prefer? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10612#note_139217
On Fri May 8 14:13:30 2026 +0000, समीरसिंह Sameer Singh wrote:
I actually prefer \*2 for faster convergence. Since we have increased the buffer size from 1.5 to 2, OOM should only happen in rare cases and for those cases I would want it to resolve quickly. Maybe we can increase the ceiling to something bigger to get more passes if you prefer? Ok, I am not feeling strongly here so if you have that preference then that works for me.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10612#note_139219
This merge request was approved by Aric Stewart. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10612
This bug may be related if not yet on radar: https://bugs.winehq.org/show_bug.cgi?id=59680 Character (U+0065 U+0E4B): e๋ crashes notepad immediately when pasting for others wine installs but it does not crash for my Debian 13 wine 10.0 apt pkg nor my latest custom 11.8 build. It does however crash for Proton on my system which was built with different libs. Unclear if some of my system libs fix whatever is broken for others, these requests might address the bugs. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10612#note_139374
On Sun May 10 12:58:51 2026 +0000, Stian Low wrote:
This bug may be related if not yet on radar: https://bugs.winehq.org/show_bug.cgi?id=59680 Character (U+0065 U+0E4B): e๋ crashes notepad immediately when pasting for others wine installs but it does not crash for my Debian 13 wine 10.0 apt pkg nor my latest custom 11.8 build. It does however crash for Proton on my system which was built with different libs. Unclear if some of my system libs fix whatever is broken for others, these requests might address the bugs. Thanks for bringing this to my attention. I can reproduce the crash using the latest wine master. However, these MRs do not fix this issue, so I will open a separate MR addressing the problem.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10612#note_139375
On Sun May 10 12:58:51 2026 +0000, समीरसिंह Sameer Singh wrote:
Thanks for bringing this to my attention. I can reproduce the crash using the latest wine master. However, these MRs do not fix this issue, so I will open a separate MR addressing the problem. You can view the MR at !10859
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10612#note_139381
participants (4)
-
Aric Stewart (@aricstewart) -
Stian Low (@stianlow) -
समीर सिंह Sameer Singh -
समीरसिंह Sameer Singh (@ss141309)