From 5f70cd6509752de4cc571495e6b44222e267e000 Mon Sep 17 00:00:00 2001 From: Andrew Nguyen Date: Mon, 3 Jan 2011 21:25:29 -0600 Subject: [PATCH] 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 41ac019e434..d56ea68ba67 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 c4d51ab4bce..79f644a6913 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); }