From 992117ac9820a8c8d1174a62179c87ca7cf309ff Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Tue, 23 Feb 2021 16:07:32 +0300 Subject: [PATCH] advapi32: Handle exceptions from dereferencing invalid crypt objects' handles. Fixes crash on start in "Re:ZERO -Starting Life in Another World- The Prophecy of the Throne". Signed-off-by: Paul Gofman Signed-off-by: Alexandre Julliard --- dlls/advapi32/crypt.c | 19 +++++++++++++++---- dlls/advapi32/tests/crypt.c | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/dlls/advapi32/crypt.c b/dlls/advapi32/crypt.c index 6cdb5f3ecff..20c55558fa5 100644 --- a/dlls/advapi32/crypt.c +++ b/dlls/advapi32/crypt.c @@ -37,6 +37,7 @@ #include "winreg.h" #include "rpc.h" #include "wine/debug.h" +#include "wine/exception.h" #include "winternl.h" WINE_DEFAULT_DEBUG_CHANNEL(crypt); @@ -59,12 +60,22 @@ static HWND crypt_hWindow; static void *pointer_from_handle(UINT_PTR handle, DWORD magic) { - if (!handle || *(DWORD *)handle != magic) + void *ret = NULL; + + __TRY { - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; + if (handle && *(DWORD *)handle == magic) + ret = (void *)handle; } - return (void *)handle; + __EXCEPT_PAGE_FAULT + { + } + __ENDTRY + + if (!ret) + SetLastError(ERROR_INVALID_PARAMETER); + + return ret; } static PCRYPTPROV provider_from_handle(HCRYPTPROV handle) diff --git a/dlls/advapi32/tests/crypt.c b/dlls/advapi32/tests/crypt.c index a6e3d447ba8..6df47cd626b 100644 --- a/dlls/advapi32/tests/crypt.c +++ b/dlls/advapi32/tests/crypt.c @@ -154,6 +154,8 @@ static void test_CryptReleaseContext(void) ret = CryptContextAddRef(0, NULL, 0); ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %u\n", GetLastError()); + ret = CryptContextAddRef(0xdeadbeef, NULL, 0); + ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %u\n", GetLastError()); ret = CryptReleaseContext(prov, 0); ok(ret, "got %u\n", GetLastError()); @@ -272,6 +274,9 @@ static void test_incorrect_api_usage(void) ok (result, "%08x\n", GetLastError()); if (!result) return; + /* Looks like native handles are just pointers. */ + ok(!!*(void **)hProv, "Got zero *(void **)hProv.\n"); + result = CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash); ok (result, "%d\n", GetLastError()); if (!result) return; @@ -301,6 +306,9 @@ static void test_incorrect_api_usage(void) result = CryptDestroyHash(0); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); + result = CryptCreateHash(0xdeadbeef, CALG_SHA, 0, 0, &hHash); + ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); + result = CryptCreateHash(0, CALG_SHA, 0, 0, &hHash); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); @@ -310,13 +318,25 @@ static void test_incorrect_api_usage(void) dwLen = 1; result = CryptDecrypt(hKey, 0, TRUE, 0, &temp, &dwLen); ok (result, "%d\n", GetLastError()); + result = CryptDecrypt(hKey, 0xdeadbeef, TRUE, 0, &temp, &dwLen); + ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); result = CryptDecrypt(0, 0, TRUE, 0, &temp, &dwLen); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); + result = CryptDecrypt(0xdeadbeef, 0, TRUE, 0, &temp, &dwLen); + ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); result = CryptEncrypt(hKey, 0, TRUE, 0, &temp, &dwLen, sizeof(temp)); ok (result, "%d\n", GetLastError()); + result = CryptEncrypt(hKey, 0xdeadbeef, TRUE, 0, &temp, &dwLen, sizeof(temp)); + ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); result = CryptEncrypt(0, 0, TRUE, 0, &temp, &dwLen, sizeof(temp)); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); + result = CryptEncrypt(0xdeadbeef, 0, TRUE, 0, &temp, &dwLen, sizeof(temp)); + ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); + + dwLen = 1; + result = CryptExportKey(hKey, 0xdeadbeef, 0, 0, &temp, &dwLen); + ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); result = CryptDestroyKey(hKey); ok (result, "%d\n", GetLastError());