[PATCH 1/2] user32: Protect single-line edit against pasting new line character.
Rafał Harabień
rafalh1992 at o2.pl
Sun Nov 5 12:28:38 CST 2017
Signed-off-by: Rafał Harabień <rafalh1992 at o2.pl>
---
dlls/user32/edit.c | 21 ++++++++++--
dlls/user32/tests/edit.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 102 insertions(+), 3 deletions(-)
diff --git a/dlls/user32/edit.c b/dlls/user32/edit.c
index 00a7fba..3bfc54d 100644
--- a/dlls/user32/edit.c
+++ b/dlls/user32/edit.c
@@ -3077,7 +3077,8 @@ static inline BOOL EDIT_IsInsideDialog(EDITSTATE *es)
static void EDIT_WM_Paste(EDITSTATE *es)
{
HGLOBAL hsrc;
- LPWSTR src;
+ LPWSTR src, new_src, ptr;
+ int len;
/* Protect read-only edit control from modification */
if(es->style & ES_READONLY)
@@ -3086,7 +3087,23 @@ static void EDIT_WM_Paste(EDITSTATE *es)
OpenClipboard(es->hwndSelf);
if ((hsrc = GetClipboardData(CF_UNICODETEXT))) {
src = GlobalLock(hsrc);
- EDIT_EM_ReplaceSel(es, TRUE, src, TRUE, TRUE);
+
+ /* Protect single-line edit against pasting new line character */
+ ptr = NULL;
+ if (!(es->style & ES_MULTILINE))
+ ptr = strchrW(src, '\n');
+ if (ptr != NULL) {
+ len = ptr - src;
+ if (src[len - 1] == '\r')
+ --len;
+ new_src = HeapAlloc(GetProcessHeap(), 0, (len+1) * sizeof(WCHAR));
+ if (new_src != NULL) {
+ lstrcpynW(new_src, src, len+1);
+ EDIT_EM_ReplaceSel(es, TRUE, new_src, TRUE, TRUE);
+ HeapFree(GetProcessHeap(), 0, new_src);
+ }
+ } else
+ EDIT_EM_ReplaceSel(es, TRUE, src, TRUE, TRUE);
GlobalUnlock(hsrc);
}
else if (es->style & ES_PASSWORD) {
diff --git a/dlls/user32/tests/edit.c b/dlls/user32/tests/edit.c
index b9aa1c9..d842dce 100644
--- a/dlls/user32/tests/edit.c
+++ b/dlls/user32/tests/edit.c
@@ -867,7 +867,7 @@ static LRESULT CALLBACK edit3_wnd_procA(HWND hWnd, UINT msg, WPARAM wParam, LPAR
return DefWindowProcA(hWnd, msg, wParam, lParam);
}
-/* Test behaviour of WM_SETTEXT, WM_REPLACESEL and notificatisons sent in response
+/* Test behaviour of WM_SETTEXT, WM_REPLACESEL and notifications sent in response
* to these messages.
*/
static void test_edit_control_3(void)
@@ -969,6 +969,19 @@ static void test_edit_control_3(void)
ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
test_notify(1, 0, 1);
+ SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
+ zero_notify();
+ SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
+ len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
+ ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
+ test_notify(1, 0, 1);
+
+ zero_notify();
+ SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
+ len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
+ ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
+ test_notify(1, 0, 1);
+
SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
@@ -2831,6 +2844,74 @@ static void test_EM_GETHANDLE(void)
DestroyWindow(hEdit);
}
+static void test_paste(void)
+{
+ HWND hEdit, hMultilineEdit;
+ HANDLE hmem, hmem_ret;
+ char *buffer;
+ int r, len;
+ static const char *str = "this is a simple text";
+ static const char *str2 = "first line\r\nsecond line";
+
+ hEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
+ hMultilineEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE, 0);
+
+ /* Prepare clipboard data with simple text */
+ hmem = GlobalAlloc(GMEM_MOVEABLE, 255);
+ ok(hmem != NULL, "got %p (expected != NULL)\n", hmem);
+ buffer = GlobalLock(hmem);
+ ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
+ strcpy(buffer, str);
+ GlobalUnlock(hmem);
+
+ r = OpenClipboard(hEdit);
+ ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
+ r = EmptyClipboard();
+ ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
+ hmem_ret = SetClipboardData(CF_TEXT, hmem);
+ ok(hmem_ret == hmem, "expected %p, got %p\n", hmem, hmem_ret);
+ r = CloseClipboard();
+ ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
+
+ /* Paste single line */
+ SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)"");
+ r = SendMessageA(hEdit, WM_PASTE, 0, 0);
+ len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
+ ok(strlen(str) == len, "expected %d, got %d\n", strlen(str), len);
+
+ /* Prepare clipboard data with multiline text */
+ hmem = GlobalAlloc(GMEM_MOVEABLE, 255);
+ ok(hmem != NULL, "got %p (expected != NULL)\n", hmem);
+ buffer = GlobalLock(hmem);
+ ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
+ strcpy(buffer, str2);
+ GlobalUnlock(hmem);
+
+ r = OpenClipboard(hEdit);
+ ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
+ r = EmptyClipboard();
+ ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
+ hmem_ret = SetClipboardData(CF_TEXT, hmem);
+ ok(hmem_ret == hmem, "expected %p, got %p\n", hmem, hmem_ret);
+ r = CloseClipboard();
+ ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
+
+ /* Paste multiline text in singleline edit - should be cut */
+ SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)"");
+ r = SendMessageA(hEdit, WM_PASTE, 0, 0);
+ len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
+ ok(strlen("first line") == len, "expected %d, got %d\n", strlen("first line"), len);
+
+ /* Paste multiline text in multiline edit */
+ SendMessageA(hMultilineEdit, WM_SETTEXT, 0, (LPARAM)"");
+ r = SendMessageA(hMultilineEdit, WM_PASTE, 0, 0);
+ len = SendMessageA(hMultilineEdit, WM_GETTEXTLENGTH, 0, 0);
+ ok(strlen(str2) == len, "expected %d, got %d\n", strlen(str2), len);
+
+ /* Cleanup */
+ DestroyWindow(hEdit);
+ DestroyWindow(hMultilineEdit);
+}
START_TEST(edit)
{
@@ -2871,6 +2952,7 @@ START_TEST(edit)
win_skip("EndMenu is not available\n");
test_EM_GETHANDLE();
+ test_paste();
UnregisterWindowClasses();
}
--
2.7.4
More information about the wine-patches
mailing list