[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