Module: wine Branch: master Commit: 5f70cd6509752de4cc571495e6b44222e267e000 URL: http://source.winehq.org/git/wine.git/?a=commit;h=5f70cd6509752de4cc571495e6...
Author: Andrew Nguyen anguyen@codeweavers.com Date: Mon Jan 3 21:25:29 2011 -0600
kernel32: Improve parameter validation for WriteConsoleOutputCharacterA.
---
dlls/kernel32/console.c | 24 +++++++++--- dlls/kernel32/tests/console.c | 85 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 6 deletions(-)
diff --git a/dlls/kernel32/console.c b/dlls/kernel32/console.c index 41ac019..d56ea68 100644 --- a/dlls/kernel32/console.c +++ b/dlls/kernel32/console.c @@ -640,18 +640,30 @@ BOOL WINAPI WriteConsoleOutputCharacterA( HANDLE hConsoleOutput, LPCSTR str, DWO COORD coord, LPDWORD lpNumCharsWritten ) { BOOL ret; - LPWSTR strW; - DWORD lenW; + LPWSTR strW = NULL; + DWORD lenW = 0;
TRACE("(%p,%s,%d,%dx%d,%p)\n", hConsoleOutput, debugstr_an(str, length), length, coord.X, coord.Y, lpNumCharsWritten);
- lenW = MultiByteToWideChar( GetConsoleOutputCP(), 0, str, length, NULL, 0 ); + if (length > 0) + { + if (!str) + { + SetLastError( ERROR_INVALID_ACCESS ); + return FALSE; + }
- if (lpNumCharsWritten) *lpNumCharsWritten = 0; + lenW = MultiByteToWideChar( GetConsoleOutputCP(), 0, str, length, NULL, 0 );
- if (!(strW = HeapAlloc( GetProcessHeap(), 0, lenW * sizeof(WCHAR) ))) return FALSE; - MultiByteToWideChar( GetConsoleOutputCP(), 0, str, length, strW, lenW ); + if (!(strW = HeapAlloc( GetProcessHeap(), 0, lenW * sizeof(WCHAR) ))) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return FALSE; + } + + MultiByteToWideChar( GetConsoleOutputCP(), 0, str, length, strW, lenW ); + }
ret = WriteConsoleOutputCharacterW( hConsoleOutput, strW, lenW, coord, lpNumCharsWritten ); HeapFree( GetProcessHeap(), 0, strW ); diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c index c4d51ab..79f644a 100644 --- a/dlls/kernel32/tests/console.c +++ b/dlls/kernel32/tests/console.c @@ -1401,6 +1401,90 @@ static void test_WriteConsoleInputW(HANDLE input_handle) ok(count == 1, "Expected count to be 1, got %u\n", count); }
+static void test_WriteConsoleOutputCharacterA(HANDLE output_handle) +{ + static const char output[] = {'a', 0}; + + COORD origin = {0, 0}; + DWORD count; + BOOL ret; + int i; + + const struct + { + HANDLE hConsoleOutput; + LPCSTR str; + DWORD length; + COORD coord; + LPDWORD lpNumCharsWritten; + DWORD expected_count; + DWORD last_error; + int win7_crash; + } invalid_table[] = + { + {NULL, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {NULL, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE}, + {NULL, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {NULL, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {NULL, output, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {NULL, output, 0, origin, &count, 0, ERROR_INVALID_HANDLE}, + {NULL, output, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {NULL, output, 1, origin, &count, 0, ERROR_INVALID_HANDLE}, + {INVALID_HANDLE_VALUE, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {INVALID_HANDLE_VALUE, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE}, + {INVALID_HANDLE_VALUE, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {INVALID_HANDLE_VALUE, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {INVALID_HANDLE_VALUE, output, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {INVALID_HANDLE_VALUE, output, 0, origin, &count, 0, ERROR_INVALID_HANDLE}, + {INVALID_HANDLE_VALUE, output, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {INVALID_HANDLE_VALUE, output, 1, origin, &count, 0, ERROR_INVALID_HANDLE}, + {output_handle, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {output_handle, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {output_handle, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {output_handle, output, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {output_handle, output, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + }; + + for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++) + { + if (invalid_table[i].win7_crash) + continue; + + SetLastError(0xdeadbeef); + if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef; + ret = WriteConsoleOutputCharacterA(invalid_table[i].hConsoleOutput, + invalid_table[i].str, + invalid_table[i].length, + invalid_table[i].coord, + invalid_table[i].lpNumCharsWritten); + ok(!ret, "[%d] Expected WriteConsoleOutputCharacterA to return FALSE, got %d\n", i, ret); + if (invalid_table[i].lpNumCharsWritten) + { + ok(count == invalid_table[i].expected_count, + "[%d] Expected count to be %u, got %u\n", + i, invalid_table[i].expected_count, count); + } + ok(GetLastError() == invalid_table[i].last_error, + "[%d] Expected last error to be %u, got %u\n", + i, invalid_table[i].last_error, GetLastError()); + } + + count = 0xdeadbeef; + ret = WriteConsoleOutputCharacterA(output_handle, NULL, 0, origin, &count); + ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret); + ok(count == 0, "Expected count to be 0, got %u\n", count); + + count = 0xdeadbeef; + ret = WriteConsoleOutputCharacterA(output_handle, output, 0, origin, &count); + ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret); + ok(count == 0, "Expected count to be 0, got %u\n", count); + + count = 0xdeadbeef; + ret = WriteConsoleOutputCharacterA(output_handle, output, 1, origin, &count); + ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret); + ok(count == 1, "Expected count to be 1, got %u\n", count); +} + static void test_WriteConsoleOutputCharacterW(HANDLE output_handle) { static const WCHAR outputW[] = {'a',0}; @@ -1541,5 +1625,6 @@ START_TEST(console) test_GetNumberOfConsoleInputEvents(hConIn); test_WriteConsoleInputA(hConIn); test_WriteConsoleInputW(hConIn); + test_WriteConsoleOutputCharacterA(hConOut); test_WriteConsoleOutputCharacterW(hConOut); }