From 4fa3ca98a249b030b8ce3a86081786f4bbb2daa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 23 Nov 2022 15:42:19 +0800 Subject: [PATCH] util/register: fix crashing when value string contains non-ascii chars We can't use RegGetValueA because RegGetValueA converts wide string to non UTF-8 string, which results in crashing when printing --- src/detection/bios/bios_windows.c | 12 ++--- src/detection/board/board_windows.c | 8 +-- src/detection/cpu/cpu_windows.c | 8 +-- src/detection/cursor/cursor_windows.c | 2 +- src/detection/host/host_windows.c | 12 ++--- .../terminalfont/terminalfont_windows.c | 6 +-- src/detection/wmtheme/wmtheme_windows.c | 10 ++-- src/util/windows/register.c | 49 ++++++++++++++----- src/util/windows/register.h | 6 +-- src/util/windows/unicode.c | 19 +++++++ src/util/windows/unicode.h | 1 + 11 files changed, 88 insertions(+), 45 deletions(-) diff --git a/src/detection/bios/bios_windows.c b/src/detection/bios/bios_windows.c index 68e51a904..e29b1cc8c 100644 --- a/src/detection/bios/bios_windows.c +++ b/src/detection/bios/bios_windows.c @@ -11,18 +11,18 @@ void ffDetectBios(FFBiosResult* bios) ffStrbufInit(&bios->biosVersion); FF_HKEY_AUTO_DESTROY hKey = NULL; - if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, &bios->error)) + if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, &bios->error)) return; - if(!ffRegReadStrbuf(hKey, "BIOSVersion", &bios->biosRelease, &bios->error)) + if(!ffRegReadStrbuf(hKey, L"BIOSVersion", &bios->biosRelease, &bios->error)) return; - ffRegReadStrbuf(hKey, "BIOSVendor", &bios->biosVendor, NULL); - ffRegReadStrbuf(hKey, "BIOSReleaseDate", &bios->biosDate, NULL); + ffRegReadStrbuf(hKey, L"BIOSVendor", &bios->biosVendor, NULL); + ffRegReadStrbuf(hKey, L"BIOSReleaseDate", &bios->biosDate, NULL); uint32_t major, minor; if( - ffRegReadUint(hKey, "BiosMajorRelease", &major, NULL) && - ffRegReadUint(hKey, "BiosMinorRelease", &minor, NULL) + ffRegReadUint(hKey, L"BiosMajorRelease", &major, NULL) && + ffRegReadUint(hKey, L"BiosMinorRelease", &minor, NULL) ) ffStrbufAppendF(&bios->biosVersion, "%u.%u", (unsigned)major, (unsigned)minor); } diff --git a/src/detection/board/board_windows.c b/src/detection/board/board_windows.c index b2464a8b6..adeae2251 100644 --- a/src/detection/board/board_windows.c +++ b/src/detection/board/board_windows.c @@ -11,11 +11,11 @@ void ffDetectBoard(FFBoardResult* board) FF_HKEY_AUTO_DESTROY hKey = NULL; - if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, &board->error)) + if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, &board->error)) return; - if(!ffRegReadStrbuf(hKey, "BaseBoardProduct", &board->boardName, &board->error)) + if(!ffRegReadStrbuf(hKey, L"BaseBoardProduct", &board->boardName, &board->error)) return; - ffRegReadStrbuf(hKey, "BaseBoardManufacturer", &board->boardVendor, NULL); - ffRegReadStrbuf(hKey, "BaseBoardVersion", &board->boardVersion, NULL); + ffRegReadStrbuf(hKey, L"BaseBoardManufacturer", &board->boardVendor, NULL); + ffRegReadStrbuf(hKey, L"BaseBoardVersion", &board->boardVersion, NULL); } diff --git a/src/detection/cpu/cpu_windows.c b/src/detection/cpu/cpu_windows.c index 6fe9065e8..a0a86d169 100644 --- a/src/detection/cpu/cpu_windows.c +++ b/src/detection/cpu/cpu_windows.c @@ -39,15 +39,15 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu, bool cached) cpu->coresLogical = (uint16_t)GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS); FF_HKEY_AUTO_DESTROY hKey; - if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL)) + if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL)) return; { uint32_t mhz; - if(ffRegReadUint(hKey, "~MHz", &mhz, NULL)) + if(ffRegReadUint(hKey, L"~MHz", &mhz, NULL)) cpu->frequencyMax = mhz / 1000.0; } - ffRegReadStrbuf(hKey, "ProcessorNameString", &cpu->name, NULL); - ffRegReadStrbuf(hKey, "VendorIdentifier", &cpu->vendor, NULL); + ffRegReadStrbuf(hKey, L"ProcessorNameString", &cpu->name, NULL); + ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL); } diff --git a/src/detection/cursor/cursor_windows.c b/src/detection/cursor/cursor_windows.c index fd3785637..c820a33e7 100644 --- a/src/detection/cursor/cursor_windows.c +++ b/src/detection/cursor/cursor_windows.c @@ -7,6 +7,6 @@ void ffDetectCursor(const FFinstance* instance, FFCursorResult* result) FF_UNUSED(instance); FF_HKEY_AUTO_DESTROY hKey; - if(ffRegOpenKeyForRead(HKEY_CURRENT_USER, "Control Panel\\Cursors", &hKey, &result->error)) + if(ffRegOpenKeyForRead(HKEY_CURRENT_USER, L"Control Panel\\Cursors", &hKey, &result->error)) ffRegReadStrbuf(hKey, NULL, &result->theme, &result->error); } diff --git a/src/detection/host/host_windows.c b/src/detection/host/host_windows.c index abb84a169..8c59eed11 100644 --- a/src/detection/host/host_windows.c +++ b/src/detection/host/host_windows.c @@ -16,12 +16,12 @@ void ffDetectHostImpl(FFHostResult* host) FF_HKEY_AUTO_DESTROY hKey = NULL; - if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, &host->error)) + if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, &host->error)) return; - ffRegReadStrbuf(hKey, "SystemProductName", &host->productName, NULL); - ffRegReadStrbuf(hKey, "SystemFamily", &host->productFamily, NULL); - ffRegReadStrbuf(hKey, "SystemVersion", &host->productVersion, NULL); - ffRegReadStrbuf(hKey, "SystemSKU", &host->productSku, NULL); - ffRegReadStrbuf(hKey, "SystemManufacturer", &host->sysVendor, NULL); + ffRegReadStrbuf(hKey, L"SystemProductName", &host->productName, NULL); + ffRegReadStrbuf(hKey, L"SystemFamily", &host->productFamily, NULL); + ffRegReadStrbuf(hKey, L"SystemVersion", &host->productVersion, NULL); + ffRegReadStrbuf(hKey, L"SystemSKU", &host->productSku, NULL); + ffRegReadStrbuf(hKey, L"SystemManufacturer", &host->sysVendor, NULL); } diff --git a/src/detection/terminalfont/terminalfont_windows.c b/src/detection/terminalfont/terminalfont_windows.c index 420419648..55da491b3 100644 --- a/src/detection/terminalfont/terminalfont_windows.c +++ b/src/detection/terminalfont/terminalfont_windows.c @@ -31,16 +31,16 @@ static void detectConhost(const FFinstance* instance, FFTerminalFontResult* term //Current font of conhost doesn't seem to be detectable, we detect default font instead FF_HKEY_AUTO_DESTROY hKey = NULL; - if(!ffRegOpenKeyForRead(HKEY_CURRENT_USER, "Console", &hKey, &terminalFont->error)) + if(!ffRegOpenKeyForRead(HKEY_CURRENT_USER, L"Console", &hKey, &terminalFont->error)) return; FF_STRBUF_AUTO_DESTROY fontName; ffStrbufInit(&fontName); - if(!ffRegReadStrbuf(hKey, "FaceName", &fontName, &terminalFont->error)) + if(!ffRegReadStrbuf(hKey, L"FaceName", &fontName, &terminalFont->error)) return; uint32_t fontSizeNum = 0; - if(!ffRegReadUint(hKey, "FontSize", &fontSizeNum, &terminalFont->error)) + if(!ffRegReadUint(hKey, L"FontSize", &fontSizeNum, &terminalFont->error)) return; char fontSize[16]; diff --git a/src/detection/wmtheme/wmtheme_windows.c b/src/detection/wmtheme/wmtheme_windows.c index c84a2c923..4e47c067a 100644 --- a/src/detection/wmtheme/wmtheme_windows.c +++ b/src/detection/wmtheme/wmtheme_windows.c @@ -7,23 +7,23 @@ bool ffDetectWmTheme(FFinstance* instance, FFstrbuf* themeOrError) FF_UNUSED(instance); FF_HKEY_AUTO_DESTROY hKey = NULL; - if(ffRegOpenKeyForRead(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", &hKey, NULL)) + if(ffRegOpenKeyForRead(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", &hKey, NULL)) { uint32_t SystemUsesLightTheme = 1; - if(!ffRegReadUint(hKey, "SystemUsesLightTheme", &SystemUsesLightTheme, themeOrError)) + if(!ffRegReadUint(hKey, L"SystemUsesLightTheme", &SystemUsesLightTheme, themeOrError)) return false; uint32_t AppsUsesLightTheme = 1; - if(!ffRegReadUint(hKey, "AppsUseLightTheme", &AppsUsesLightTheme, themeOrError)) + if(!ffRegReadUint(hKey, L"AppsUseLightTheme", &AppsUsesLightTheme, themeOrError)) return false; ffStrbufAppendF(themeOrError, "System - %s, Apps - %s", SystemUsesLightTheme ? "Light" : "Dark", AppsUsesLightTheme ? "Light" : "Dark"); return true; } - else if(ffRegOpenKeyForRead(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes", &hKey, NULL)) + else if(ffRegOpenKeyForRead(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes", &hKey, NULL)) { - if(!ffRegReadStrbuf(hKey, "CurrentTheme", themeOrError, themeOrError)) + if(!ffRegReadStrbuf(hKey, L"CurrentTheme", themeOrError, themeOrError)) return false; ffStrbufSubstrBeforeLastC(themeOrError, '.'); diff --git a/src/util/windows/register.c b/src/util/windows/register.c index f8ea9e4b1..9b0e916b0 100644 --- a/src/util/windows/register.c +++ b/src/util/windows/register.c @@ -1,4 +1,6 @@ #include "register.h" +#include "unicode.h" +#include "util/mallocHelper.h" static const char* hKey2Str(HKEY hKey) { @@ -18,41 +20,62 @@ static const char* hKey2Str(HKEY hKey) return "UNKNOWN"; } -bool ffRegOpenKeyForRead(HKEY hKey, const char* lpSubKey, HKEY* result, FFstrbuf* error) +bool ffRegOpenKeyForRead(HKEY hKey, const wchar_t* subKeyW, HKEY* result, FFstrbuf* error) { - if(RegOpenKeyExA(hKey, lpSubKey, 0, KEY_READ, result) != ERROR_SUCCESS) + if(RegOpenKeyExW(hKey, subKeyW, 0, KEY_READ, result) != ERROR_SUCCESS) { if(error) - ffStrbufAppendF(error, "RegOpenKeyExW(%s\\%s) failed", hKey2Str(hKey), lpSubKey); + { + FF_STRBUF_AUTO_DESTROY subKeyA = ffStrbufFromWchar(subKeyW); + ffStrbufAppendF(error, "RegOpenKeyExW(%s\\%s) failed", hKey2Str(hKey), subKeyA.chars); + } return false; } return true; } -bool ffRegReadStrbuf(HKEY hKey, const char* valueName, FFstrbuf* result, FFstrbuf* error) +bool ffRegReadStrbuf(HKEY hKey, const wchar_t* valueNameW, FFstrbuf* result, FFstrbuf* error) { DWORD bufSize; //with tailing '\0' - if(RegGetValueA(hKey, NULL, valueName, RRF_RT_REG_SZ, NULL, NULL, &bufSize) != ERROR_SUCCESS) + if(RegGetValueW(hKey, NULL, valueNameW, RRF_RT_REG_SZ, NULL, NULL, &bufSize) != ERROR_SUCCESS) { - if(error) ffStrbufAppendF(error, "RegGetValueA(%s, NULL, RRF_RT_REG_SZ) failed", valueName ? valueName : "(default)"); + if(error) + { + if(!valueNameW) + valueNameW = L"(default)"; + FF_STRBUF_AUTO_DESTROY valueNameA = ffStrbufFromWchar(valueNameW); + ffStrbufAppendF(error, "RegGetValueA(%s, NULL, RRF_RT_REG_SZ) failed", valueNameA.chars); + } return false; } - ffStrbufEnsureFree(result, bufSize - 1); - if(RegGetValueA(hKey, NULL, valueName, RRF_RT_REG_SZ, NULL, result->chars, &bufSize) != ERROR_SUCCESS) + wchar_t* FF_AUTO_FREE resultW = (wchar_t*)malloc(bufSize); + if(RegGetValueW(hKey, NULL, valueNameW, RRF_RT_REG_SZ, NULL, resultW, &bufSize) != ERROR_SUCCESS) { - if(error) ffStrbufAppendF(error, "RegGetValueA(%s, result, RRF_RT_REG_SZ) failed", valueName ? valueName : "(default)"); + if(error) + { + if(!valueNameW) + valueNameW = L"(default)"; + FF_STRBUF_AUTO_DESTROY valueNameA = ffStrbufFromWchar(valueNameW); + ffStrbufAppendF(error, "RegGetValueA(%s, result, RRF_RT_REG_SZ) failed", valueNameA.chars); + } return false; } - result->length = bufSize - 1; + ffWcharToUtf8(resultW, result); return true; } -bool ffRegReadUint(HKEY hKey, const char* valueName, uint32_t* result, FFstrbuf* error) +bool ffRegReadUint(HKEY hKey, const wchar_t* valueNameW, uint32_t* result, FFstrbuf* error) { DWORD bufSize = sizeof(*result); - if(RegGetValueA(hKey, NULL, valueName, RRF_RT_DWORD, NULL, result, &bufSize) != ERROR_SUCCESS) + if(RegGetValueW(hKey, NULL, valueNameW, RRF_RT_DWORD, NULL, result, &bufSize) != ERROR_SUCCESS) { - if(error) ffStrbufAppendF(error, "RegGetValueA(%s, result, RRF_RT_DWORD) failed", valueName ? valueName : "(default)"); + if(error) + { + if(!valueNameW) + valueNameW = L"(default)"; + FF_STRBUF_AUTO_DESTROY valueNameA = ffStrbufFromWchar(valueNameW); + ffStrbufAppendF(error, "RegGetValueA(%s, result, RRF_RT_DWORD) failed", valueNameA.chars); + } return false; } return true; diff --git a/src/util/windows/register.h b/src/util/windows/register.h index 25746c1f6..22aa6f9ce 100644 --- a/src/util/windows/register.h +++ b/src/util/windows/register.h @@ -16,8 +16,8 @@ static inline void wrapRegCloseKey(HKEY* phKey) #define FF_HKEY_AUTO_DESTROY HKEY __attribute__((__cleanup__(wrapRegCloseKey))) -bool ffRegOpenKeyForRead(HKEY hKey, const char* lpSubKey, HKEY* result, FFstrbuf* error); -bool ffRegReadStrbuf(HKEY hKey, const char* valueName, FFstrbuf* result, FFstrbuf* error); -bool ffRegReadUint(HKEY hKey, const char* valueName, uint32_t* result, FFstrbuf* error); +bool ffRegOpenKeyForRead(HKEY hKey, const wchar_t* subKeyW, HKEY* result, FFstrbuf* error); +bool ffRegReadStrbuf(HKEY hKey, const wchar_t* valueNameW, FFstrbuf* result, FFstrbuf* error); +bool ffRegReadUint(HKEY hKey, const wchar_t* valueNameW, uint32_t* result, FFstrbuf* error); #endif diff --git a/src/util/windows/unicode.c b/src/util/windows/unicode.c index 4f69b5474..f2ffa28cc 100644 --- a/src/util/windows/unicode.c +++ b/src/util/windows/unicode.c @@ -15,3 +15,22 @@ void ffWcharToUtf8(const wchar_t* input, FFstrbuf* result) result->length = (uint32_t)size_needed; result->chars[size_needed] = '\0'; } + +FFstrbuf ffStrbufFromWchar(const wchar_t* input) +{ + FFstrbuf result; + + int len = input ? (int)wcslen(input) : 0; + if(len <= 0) + ffStrbufInit(&result); + else + { + int size_needed = WideCharToMultiByte(CP_UTF8, 0, input, len, NULL, 0, NULL, NULL); + ffStrbufInitA(&result, (uint32_t)size_needed); + WideCharToMultiByte(CP_UTF8, 0, input, len, result.chars, size_needed, NULL, NULL); + result.length = (uint32_t)size_needed; + result.chars[size_needed] = '\0'; + } + + return result; +} diff --git a/src/util/windows/unicode.h b/src/util/windows/unicode.h index d7bd50914..d3926ff06 100644 --- a/src/util/windows/unicode.h +++ b/src/util/windows/unicode.h @@ -6,5 +6,6 @@ #include "fastfetch.h" void ffWcharToUtf8(const wchar_t* input, FFstrbuf* result); +FFstrbuf ffStrbufFromWchar(const wchar_t* input); #endif