diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c index 94dc37a2b13..5a097058e47 100644 --- a/dlls/wininet/internet.c +++ b/dlls/wininet/internet.c @@ -1092,10 +1092,17 @@ BOOL WINAPI InternetGetLastResponseInfoA(LPDWORD lpdwError, } if (lpwite) { + if (lpszBuffer == NULL || *lpdwBufferLength < strlen(lpwite->response)) + { + *lpdwBufferLength = strlen(lpwite->response); + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } *lpdwError = lpwite->dwError; - if (lpwite->dwError) + if (lpwite->dwError && *lpdwBufferLength) { memcpy(lpszBuffer, lpwite->response, *lpdwBufferLength); + lpszBuffer[*lpdwBufferLength - 1] = 0; *lpdwBufferLength = strlen(lpszBuffer); } else @@ -1134,8 +1141,14 @@ BOOL WINAPI InternetGetLastResponseInfoW(LPDWORD lpdwError, } if (lpwite) { + if (lpszBuffer == NULL || *lpdwBufferLength < strlen(lpwite->response)) + { + *lpdwBufferLength = strlen(lpwite->response); + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } *lpdwError = lpwite->dwError; - if (lpwite->dwError) + if (lpwite->dwError && *lpdwBufferLength) { MultiByteToWideChar(CP_ACP, 0, lpwite->response, -1, lpszBuffer, *lpdwBufferLength); *lpdwBufferLength = lstrlenW(lpszBuffer); diff --git a/dlls/wininet/tests/ftp.c b/dlls/wininet/tests/ftp.c index eba7c180939..16fbbcb2ed3 100644 --- a/dlls/wininet/tests/ftp.c +++ b/dlls/wininet/tests/ftp.c @@ -738,7 +738,8 @@ static void test_command(HINTERNET hFtp) for (i = 0; i < ARRAY_SIZE(command_test); i++) { - DWORD size; + DWORD size, orig_size; + char *buffer; SetLastError(0xdeadbeef); ret = pFtpCommandA(hFtp, FALSE, FTP_TRANSFER_TYPE_ASCII, command_test[i].cmd, 0, NULL); @@ -747,10 +748,35 @@ static void test_command(HINTERNET hFtp) ok(ret == command_test[i].ret, "%d: expected FtpCommandA to %s\n", i, command_test[i].ret ? "succeed" : "fail"); ok(error == command_test[i].error, "%d: expected error %u, got %u\n", i, command_test[i].error, error); + size = 0; ret = InternetGetLastResponseInfoA(&error, NULL, NULL); ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "%d: ret %d, lasterr %d\n", i, ret, GetLastError()); ret = InternetGetLastResponseInfoA(NULL, NULL, &size); ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "%d: ret %d, lasterr %d\n", i, ret, GetLastError()); + /* Zero size */ + size = 0; + ret = InternetGetLastResponseInfoA(&error, NULL, &size); + ok((ret && size == 0) || (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER), "%d: got ret %d, size %d, lasterr %d\n", i, ret, size, GetLastError()); + /* Positive size, NULL buffer */ + size++; + ret = InternetGetLastResponseInfoA(&error, NULL, &size); + ok((ret && size == 0) || (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER), "%d: got ret %d, size %u, lasterr %d\n", i, ret, size, GetLastError()); + /* When buffer is 1 char too short, it succeeds but trims the string: */ + orig_size = size; + buffer = HeapAlloc(GetProcessHeap(), 0, size); + ok(buffer != NULL, "%d: no memory\n", i); + ret = InternetGetLastResponseInfoA(&error, buffer, &size); + ok(ret, "%d: got ret %d\n", i, ret); + ok(orig_size == 0 ? size == 0 : size == orig_size - 1, "%d: got orig_size %d, size %d\n", i, orig_size, size); + ok(size == 0 || strlen(buffer) == size, "%d: size %d, buffer size %d\n", i, size, size ? strlen(buffer) : 0); + HeapFree(GetProcessHeap(), 0, buffer); + /* Long enough buffer */ + buffer = HeapAlloc(GetProcessHeap(), 0, ++size); + ok(buffer != NULL, "%d: no memory\n", i); + ret = InternetGetLastResponseInfoA(&error, buffer, &size); + ok(ret, "%d: got ret %d\n", i, ret); + ok(size == 0 || strlen(buffer) == size, "%d: size %d, buffer size %d\n", i, size, size ? strlen(buffer) : 0); + HeapFree(GetProcessHeap(), 0, buffer); } }