From a6ddbdb879d7fa65cd4ae40be3b6ae26708288a6 Mon Sep 17 00:00:00 2001 From: TheLastRar Date: Sun, 19 May 2024 18:06:07 +0100 Subject: [PATCH] DEV9: Use correct buffer type in Win32 GetAdapter Returned data is not sequenced IP_ADAPTER_ADDRESSES entries We will use implicit object creation avoid UB --- pcsx2/DEV9/AdapterUtils.cpp | 27 ++++++++++++++++----------- pcsx2/DEV9/AdapterUtils.h | 2 +- pcsx2/DEV9/pcap_io.cpp | 2 +- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/pcsx2/DEV9/AdapterUtils.cpp b/pcsx2/DEV9/AdapterUtils.cpp index 849725ee95..6abbc4b88d 100644 --- a/pcsx2/DEV9/AdapterUtils.cpp +++ b/pcsx2/DEV9/AdapterUtils.cpp @@ -57,30 +57,34 @@ using namespace PacketReader::IP; #ifdef _WIN32 AdapterUtils::Adapter* AdapterUtils::GetAllAdapters(AdapterBuffer* buffer, bool includeHidden) { - int neededSize = includeHidden ? 256 : 128; - std::unique_ptr adapterInfo = std::make_unique(neededSize); - ULONG dwBufLen = sizeof(IP_ADAPTER_ADDRESSES) * neededSize; + // It is recommend to pre-allocate enough space to be able to call GetAdaptersAddresses just once. + // Also provide extra space if we are including hidden adapters. + int neededSize = includeHidden ? 100000 : 50000; + // Each IP_ADAPTER_ADDRESSES will have pointers other structures which are also copied into this buffer. + // Subsequent IP_ADAPTER_ADDRESSES (accessed via .Next) are also not aligned to sizeof(IP_ADAPTER_ADDRESSES) boundaries. + std::unique_ptr adapterInfo = std::make_unique_for_overwrite(neededSize); + ULONG dwBufLen = neededSize; DWORD dwStatus = GetAdaptersAddresses( AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS | (includeHidden ? GAA_FLAG_INCLUDE_ALL_INTERFACES : 0), NULL, - adapterInfo.get(), + reinterpret_cast(adapterInfo.get()), &dwBufLen); if (dwStatus == ERROR_BUFFER_OVERFLOW) { DevCon.WriteLn("DEV9: GetWin32Adapter() buffer too small, resizing"); - neededSize = dwBufLen / sizeof(IP_ADAPTER_ADDRESSES) + 1; - adapterInfo = std::make_unique(neededSize); - dwBufLen = sizeof(IP_ADAPTER_ADDRESSES) * neededSize; + neededSize = dwBufLen + 500; + adapterInfo = std::make_unique_for_overwrite(neededSize); + dwBufLen = neededSize; DevCon.WriteLn("DEV9: New size %i", neededSize); dwStatus = GetAdaptersAddresses( AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS | (includeHidden ? GAA_FLAG_INCLUDE_ALL_INTERFACES : 0), NULL, - adapterInfo.get(), + reinterpret_cast(adapterInfo.get()), &dwBufLen); } if (dwStatus != ERROR_SUCCESS) @@ -88,11 +92,12 @@ AdapterUtils::Adapter* AdapterUtils::GetAllAdapters(AdapterBuffer* buffer, bool buffer->swap(adapterInfo); - return buffer->get(); + // Trigger implicit object creation. + return std::launder(reinterpret_cast(buffer->get())); } bool AdapterUtils::GetAdapter(const std::string& name, Adapter* adapter, AdapterBuffer* buffer) { - std::unique_ptr adapterInfo; + std::unique_ptr adapterInfo; PIP_ADAPTER_ADDRESSES pAdapter = GetAllAdapters(&adapterInfo); if (pAdapter == nullptr) return false; @@ -113,7 +118,7 @@ bool AdapterUtils::GetAdapter(const std::string& name, Adapter* adapter, Adapter } bool AdapterUtils::GetAdapterAuto(Adapter* adapter, AdapterBuffer* buffer) { - std::unique_ptr adapterInfo; + std::unique_ptr adapterInfo; PIP_ADAPTER_ADDRESSES pAdapter = GetAllAdapters(&adapterInfo); if (pAdapter == nullptr) return false; diff --git a/pcsx2/DEV9/AdapterUtils.h b/pcsx2/DEV9/AdapterUtils.h index f3b859c11c..af54d8e2a9 100644 --- a/pcsx2/DEV9/AdapterUtils.h +++ b/pcsx2/DEV9/AdapterUtils.h @@ -23,7 +23,7 @@ namespace AdapterUtils { #ifdef _WIN32 typedef IP_ADAPTER_ADDRESSES Adapter; - typedef std::unique_ptr AdapterBuffer; + typedef std::unique_ptr AdapterBuffer; #elif defined(__POSIX__) typedef ifaddrs Adapter; struct IfAdaptersDeleter diff --git a/pcsx2/DEV9/pcap_io.cpp b/pcsx2/DEV9/pcap_io.cpp index ed069f3bbe..257bc64cb1 100644 --- a/pcsx2/DEV9/pcap_io.cpp +++ b/pcsx2/DEV9/pcap_io.cpp @@ -221,7 +221,7 @@ std::vector PCAPAdapter::GetAdapters() entry.guid = std::string(&d->name[strlen(PCAPPREFIX)]); IP_ADAPTER_ADDRESSES adapterInfo; - std::unique_ptr buffer; + AdapterUtils::AdapterBuffer buffer; if (AdapterUtils::GetAdapter(entry.guid, &adapterInfo, &buffer)) entry.name = StringUtil::WideStringToUTF8String(std::wstring(adapterInfo.FriendlyName));