From 97269e143d06d75415d7d501f3ecc278608d677e Mon Sep 17 00:00:00 2001
From: pionere <[EMAIL REDACTED]>
Date: Tue, 18 Jan 2022 17:51:17 +0100
Subject: [PATCH] adjustments to ime_candidates - allocate ime_candidates on
demand - allow write to the whole allocated memory of ime_candidates - ensure
ime_candcount is set to zero in case the candidates can not be queried for
any reason
---
src/video/windows/SDL_windowskeyboard.c | 43 +++++++++++++++++--------
src/video/windows/SDL_windowsvideo.h | 3 +-
2 files changed, 31 insertions(+), 15 deletions(-)
diff --git a/src/video/windows/SDL_windowskeyboard.c b/src/video/windows/SDL_windowskeyboard.c
index bdf431f1756..6ab440dddfc 100644
--- a/src/video/windows/SDL_windowskeyboard.c
+++ b/src/video/windows/SDL_windowskeyboard.c
@@ -67,7 +67,7 @@ WIN_InitKeyboard(_THIS)
data->ime_cursor = 0;
data->ime_candlist = SDL_FALSE;
- SDL_memset(data->ime_candidates, 0, sizeof(data->ime_candidates));
+ data->ime_candidates = NULL;
data->ime_candcount = 0;
data->ime_candref = 0;
data->ime_candsel = 0;
@@ -349,7 +349,7 @@ DEFINE_GUID(IID_ITfThreadMgrEx, 0x3E90ADE3,0x7594
#define SUBLANG() SUBLANGID(LANG())
static void IME_UpdateInputLocale(SDL_VideoData *videodata);
-static void IME_ShowCandidateList(SDL_VideoData *videodata);
+static int IME_ShowCandidateList(SDL_VideoData *videodata);
static void IME_ClearComposition(SDL_VideoData *videodata);
static void IME_SetWindow(SDL_VideoData* videodata, HWND hwnd);
static void IME_SetupAPI(SDL_VideoData *videodata);
@@ -801,12 +801,14 @@ IME_SendEditingEvent(SDL_VideoData *videodata)
static void
IME_AddCandidate(SDL_VideoData *videodata, UINT i, LPCWSTR candidate)
{
- LPWSTR dst = videodata->ime_candidates[i];
+ LPWSTR dst = &videodata->ime_candidates[i * MAX_CANDLENGTH];
+ LPWSTR end = &dst[MAX_CANDLENGTH - 1];
+ SDL_COMPILE_TIME_ASSERT(IME_CANDIDATE_INDEXING_REQUIRES, MAX_CANDLIST == 10);
*dst++ = (WCHAR)(TEXT('0') + ((i + videodata->ime_candlistindexbase) % 10));
if (videodata->ime_candvertical)
*dst++ = TEXT(' ');
- while (*candidate && (SDL_arraysize(videodata->ime_candidates[i]) > (dst - videodata->ime_candidates[i])))
+ while (*candidate && dst < end)
*dst++ = *candidate++;
*dst = (WCHAR)'\0';
@@ -819,8 +821,8 @@ IME_GetCandidateList(HWND hwnd, SDL_VideoData *videodata)
DWORD size;
LPCANDIDATELIST cand_list;
- IME_ShowCandidateList(videodata);
-
+ if (IME_ShowCandidateList(videodata) < 0)
+ return;
himc = ImmGetContext(hwnd);
if (!himc)
return;
@@ -857,7 +859,6 @@ IME_GetCandidateList(HWND hwnd, SDL_VideoData *videodata)
videodata->ime_candpgsize = SDL_min(cand_list->dwPageSize == 0 ? MAX_CANDLIST : cand_list->dwPageSize, MAX_CANDLIST);
page_start = (cand_list->dwSelection / videodata->ime_candpgsize) * videodata->ime_candpgsize;
}
- SDL_memset(&videodata->ime_candidates, 0, sizeof(videodata->ime_candidates));
for (i = page_start, j = 0; (DWORD)i < cand_list->dwCount && j < videodata->ime_candpgsize; i++, j++) {
LPCWSTR candidate = (LPCWSTR)((DWORD_PTR)cand_list + cand_list->dwOffset[i]);
IME_AddCandidate(videodata, j, candidate);
@@ -873,13 +874,26 @@ IME_GetCandidateList(HWND hwnd, SDL_VideoData *videodata)
ImmReleaseContext(hwnd, himc);
}
-static void
+static int
IME_ShowCandidateList(SDL_VideoData *videodata)
{
+ void *candidates;
+
+ videodata->ime_candcount = 0;
+ candidates = SDL_realloc(videodata->ime_candidates, MAX_CANDSIZE);
+ if (candidates != NULL)
+ videodata->ime_candidates = (WCHAR *)candidates;
+
+ if (videodata->ime_candidates == NULL)
+ return -1;
+
+ SDL_memset(videodata->ime_candidates, 0, MAX_CANDSIZE);
+
videodata->ime_dirty = SDL_TRUE;
videodata->ime_candlist = SDL_TRUE;
IME_DestroyTextures(videodata);
IME_SendEditingEvent(videodata);
+ return 0;
}
static void
@@ -995,7 +1009,8 @@ IME_CloseCandidateList(SDL_VideoData *videodata)
{
IME_HideCandidateList(videodata);
videodata->ime_candcount = 0;
- SDL_memset(videodata->ime_candidates, 0, sizeof(videodata->ime_candidates));
+ SDL_free(videodata->ime_candidates);
+ videodata->ime_candidates = NULL;
}
static void
@@ -1008,13 +1023,15 @@ UILess_GetCandidateList(SDL_VideoData *videodata, ITfCandidateListUIElement *pca
DWORD pgstart = 0;
DWORD pgsize = 0;
UINT i, j;
+ if (IME_ShowCandidateList(videodata) < 0)
+ return;
+
pcandlist->lpVtbl->GetSelection(pcandlist, &selection);
pcandlist->lpVtbl->GetCount(pcandlist, &count);
pcandlist->lpVtbl->GetCurrentPage(pcandlist, &page);
videodata->ime_candsel = selection;
videodata->ime_candcount = count;
- IME_ShowCandidateList(videodata);
pcandlist->lpVtbl->GetPageIndex(pcandlist, 0, 0, &pgcount);
if (pgcount > 0) {
@@ -1032,8 +1049,6 @@ UILess_GetCandidateList(SDL_VideoData *videodata, ITfCandidateListUIElement *pca
}
videodata->ime_candpgsize = SDL_min(pgsize, MAX_CANDLIST);
videodata->ime_candsel = videodata->ime_candsel - pgstart;
-
- SDL_memset(videodata->ime_candidates, 0, sizeof(videodata->ime_candidates));
for (i = pgstart, j = 0; (DWORD)i < count && j < videodata->ime_candpgsize; i++, j++) {
BSTR bstr;
if (SUCCEEDED(pcandlist->lpVtbl->GetString(pcandlist, i, &bstr))) {
@@ -1462,7 +1477,7 @@ IME_RenderCandidateList(SDL_VideoData *videodata, HDC hdc)
SelectObject(hdc, font);
for (i = 0; i < candcount; ++i) {
- const WCHAR *s = videodata->ime_candidates[i];
+ const WCHAR *s = &videodata->ime_candidates[i * MAX_CANDLENGTH];
if (!*s)
break;
@@ -1524,7 +1539,7 @@ IME_RenderCandidateList(SDL_VideoData *videodata, HDC hdc)
SetBkMode(hdc, TRANSPARENT);
for (i = 0; i < candcount; ++i) {
- const WCHAR *s = videodata->ime_candidates[i];
+ const WCHAR *s = &videodata->ime_candidates[i * MAX_CANDLENGTH];
int left, top, right, bottom;
if (!*s)
break;
diff --git a/src/video/windows/SDL_windowsvideo.h b/src/video/windows/SDL_windowsvideo.h
index 7dae16a4ac8..daf68e6c2d6 100644
--- a/src/video/windows/SDL_windowsvideo.h
+++ b/src/video/windows/SDL_windowsvideo.h
@@ -37,6 +37,7 @@
#define MAX_CANDLIST 10
#define MAX_CANDLENGTH 256
+#define MAX_CANDSIZE (sizeof(WCHAR) * MAX_CANDLIST * MAX_CANDLENGTH)
#include "SDL_windowsclipboard.h"
#include "SDL_windowsevents.h"
@@ -157,7 +158,7 @@ typedef struct SDL_VideoData
int ime_cursor;
SDL_bool ime_candlist;
- WCHAR ime_candidates[MAX_CANDLIST][MAX_CANDLENGTH];
+ WCHAR* ime_candidates;
DWORD ime_candcount;
DWORD ime_candref;
DWORD ime_candsel;