Commit 605ecafa authored by Francois Gouget's avatar Francois Gouget Committed by Alexandre Julliard

user32: Fix a SetClipboardData() buffer overflow.

Wine would append a correctly aligned NUL Unicode character to terminate the string but overflow the buffer by one byte for odd-sized strings. Windows instead overwrites the last two buffer bytes with a NUL Unicode character which ends up being misaligned for odd-sized strings. The clipboard data has a size field anyway so match the Windows behavior. Tweak the tests to show that SetClipboardData() can overwrite half of the Unicode string's last character.
parent ee4f8cbb
...@@ -157,12 +157,13 @@ static HANDLE marshal_data( UINT format, HANDLE handle, size_t *ret_size ) ...@@ -157,12 +157,13 @@ static HANDLE marshal_data( UINT format, HANDLE handle, size_t *ret_size )
} }
case CF_UNICODETEXT: case CF_UNICODETEXT:
{ {
WCHAR *ptr; char *ptr;
if (!(size = GlobalSize( handle ))) return 0; if (!(size = GlobalSize( handle ))) return 0;
if ((data_size_t)size != size) return 0; if ((data_size_t)size != size) return 0;
if (size < sizeof(WCHAR)) return 0; if (size < sizeof(WCHAR)) return 0;
if (!(ptr = GlobalLock( handle ))) return 0; if (!(ptr = GlobalLock( handle ))) return 0;
ptr[(size + 1) / sizeof(WCHAR) - 1] = 0; /* enforce null-termination */ /* enforce nul-termination the Windows way: ignoring alignment */
*((WCHAR *)(ptr + size) - 1) = 0;
GlobalUnlock( handle ); GlobalUnlock( handle );
*ret_size = size; *ret_size = size;
return handle; return handle;
......
...@@ -2224,11 +2224,11 @@ static const struct ...@@ -2224,11 +2224,11 @@ static const struct
{ "", {}, 0 }, { "", {}, 0 },
{ "", {'f'}, 1 }, /* 5 */ { "", {'f'}, 1 }, /* 5 */
{ "", {'f'}, 2 }, { "", {'f'}, 2 },
{ "", {'f','o','o'}, 5 }, { "", {0x3b1,0x3b2,0x3b3}, 5 }, /* Alpha, beta, ... */
{ "", {'f','o','o'}, 6 }, { "", {0x3b1,0x3b2,0x3b3}, 6 },
{ "", {'f','o','o',0}, 7 }, /* 10 */ { "", {0x3b1,0x3b2,0x3b3,0}, 7 }, /* 10 */
{ "", {'f','o','o',0}, 8 }, { "", {0x3b1,0x3b2,0x3b3,0}, 8 },
{ "", {'f','o','o',0,'b'}, 9 }, { "", {0x3b1,0x3b2,0x3b3,0,0x3b4}, 9 },
{ "", {'f','o','o',0,'b','a','r'}, 7 * sizeof(WCHAR) }, { "", {'f','o','o',0,'b','a','r'}, 7 * sizeof(WCHAR) },
{ "", {'f','o','o',0,'b','a','r',0}, 8 * sizeof(WCHAR) }, { "", {'f','o','o',0,'b','a','r',0}, 8 * sizeof(WCHAR) },
}; };
...@@ -2274,7 +2274,7 @@ static void test_string_data(void) ...@@ -2274,7 +2274,7 @@ static void test_string_data(void)
{ {
ok( clip == data, "SetClipboardData() returned %p != %p\n", clip, data ); ok( clip == data, "SetClipboardData() returned %p != %p\n", clip, data );
memcpy( bufferW, test_data[i].strW, test_data[i].len ); memcpy( bufferW, test_data[i].strW, test_data[i].len );
bufferW[(test_data[i].len + 1) / sizeof(WCHAR) - 1] = 0; *((WCHAR *)((char *)bufferW + test_data[i].len) - 1) = 0;
ok( !memcmp( data, bufferW, test_data[i].len ), ok( !memcmp( data, bufferW, test_data[i].len ),
"wrong data %s\n", wine_dbgstr_an( data, test_data[i].len )); "wrong data %s\n", wine_dbgstr_an( data, test_data[i].len ));
} }
...@@ -2336,7 +2336,7 @@ static void test_string_data_process( int i ) ...@@ -2336,7 +2336,7 @@ static void test_string_data_process( int i )
len = GlobalSize( data ); len = GlobalSize( data );
ok( len == test_data[i].len, "wrong size %u / %u\n", len, test_data[i].len ); ok( len == test_data[i].len, "wrong size %u / %u\n", len, test_data[i].len );
memcpy( bufferW, test_data[i].strW, test_data[i].len ); memcpy( bufferW, test_data[i].strW, test_data[i].len );
bufferW[(test_data[i].len + 1) / sizeof(WCHAR) - 1] = 0; *((WCHAR *)((char *)bufferW + test_data[i].len) - 1) = 0;
ok( !memcmp( data, bufferW, len ), "wrong data %s\n", wine_dbgstr_an( data, len )); ok( !memcmp( data, bufferW, len ), "wrong data %s\n", wine_dbgstr_an( data, len ));
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment