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
This commit is contained in:
TheLastRar 2024-05-19 18:06:07 +01:00 committed by refractionpcsx2
parent 3aff833b5c
commit a6ddbdb879
3 changed files with 18 additions and 13 deletions

View File

@ -57,30 +57,34 @@ using namespace PacketReader::IP;
#ifdef _WIN32 #ifdef _WIN32
AdapterUtils::Adapter* AdapterUtils::GetAllAdapters(AdapterBuffer* buffer, bool includeHidden) AdapterUtils::Adapter* AdapterUtils::GetAllAdapters(AdapterBuffer* buffer, bool includeHidden)
{ {
int neededSize = includeHidden ? 256 : 128; // It is recommend to pre-allocate enough space to be able to call GetAdaptersAddresses just once.
std::unique_ptr<IP_ADAPTER_ADDRESSES[]> adapterInfo = std::make_unique<IP_ADAPTER_ADDRESSES[]>(neededSize); // Also provide extra space if we are including hidden adapters.
ULONG dwBufLen = sizeof(IP_ADAPTER_ADDRESSES) * neededSize; 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<std::byte[]> adapterInfo = std::make_unique_for_overwrite<std::byte[]>(neededSize);
ULONG dwBufLen = neededSize;
DWORD dwStatus = GetAdaptersAddresses( DWORD dwStatus = GetAdaptersAddresses(
AF_UNSPEC, AF_UNSPEC,
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS | (includeHidden ? GAA_FLAG_INCLUDE_ALL_INTERFACES : 0), GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS | (includeHidden ? GAA_FLAG_INCLUDE_ALL_INTERFACES : 0),
NULL, NULL,
adapterInfo.get(), reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapterInfo.get()),
&dwBufLen); &dwBufLen);
if (dwStatus == ERROR_BUFFER_OVERFLOW) if (dwStatus == ERROR_BUFFER_OVERFLOW)
{ {
DevCon.WriteLn("DEV9: GetWin32Adapter() buffer too small, resizing"); DevCon.WriteLn("DEV9: GetWin32Adapter() buffer too small, resizing");
neededSize = dwBufLen / sizeof(IP_ADAPTER_ADDRESSES) + 1; neededSize = dwBufLen + 500;
adapterInfo = std::make_unique<IP_ADAPTER_ADDRESSES[]>(neededSize); adapterInfo = std::make_unique_for_overwrite<std::byte[]>(neededSize);
dwBufLen = sizeof(IP_ADAPTER_ADDRESSES) * neededSize; dwBufLen = neededSize;
DevCon.WriteLn("DEV9: New size %i", neededSize); DevCon.WriteLn("DEV9: New size %i", neededSize);
dwStatus = GetAdaptersAddresses( dwStatus = GetAdaptersAddresses(
AF_UNSPEC, AF_UNSPEC,
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS | (includeHidden ? GAA_FLAG_INCLUDE_ALL_INTERFACES : 0), GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS | (includeHidden ? GAA_FLAG_INCLUDE_ALL_INTERFACES : 0),
NULL, NULL,
adapterInfo.get(), reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapterInfo.get()),
&dwBufLen); &dwBufLen);
} }
if (dwStatus != ERROR_SUCCESS) if (dwStatus != ERROR_SUCCESS)
@ -88,11 +92,12 @@ AdapterUtils::Adapter* AdapterUtils::GetAllAdapters(AdapterBuffer* buffer, bool
buffer->swap(adapterInfo); buffer->swap(adapterInfo);
return buffer->get(); // Trigger implicit object creation.
return std::launder(reinterpret_cast<PIP_ADAPTER_ADDRESSES>(buffer->get()));
} }
bool AdapterUtils::GetAdapter(const std::string& name, Adapter* adapter, AdapterBuffer* buffer) bool AdapterUtils::GetAdapter(const std::string& name, Adapter* adapter, AdapterBuffer* buffer)
{ {
std::unique_ptr<IP_ADAPTER_ADDRESSES[]> adapterInfo; std::unique_ptr<std::byte[]> adapterInfo;
PIP_ADAPTER_ADDRESSES pAdapter = GetAllAdapters(&adapterInfo); PIP_ADAPTER_ADDRESSES pAdapter = GetAllAdapters(&adapterInfo);
if (pAdapter == nullptr) if (pAdapter == nullptr)
return false; return false;
@ -113,7 +118,7 @@ bool AdapterUtils::GetAdapter(const std::string& name, Adapter* adapter, Adapter
} }
bool AdapterUtils::GetAdapterAuto(Adapter* adapter, AdapterBuffer* buffer) bool AdapterUtils::GetAdapterAuto(Adapter* adapter, AdapterBuffer* buffer)
{ {
std::unique_ptr<IP_ADAPTER_ADDRESSES[]> adapterInfo; std::unique_ptr<std::byte[]> adapterInfo;
PIP_ADAPTER_ADDRESSES pAdapter = GetAllAdapters(&adapterInfo); PIP_ADAPTER_ADDRESSES pAdapter = GetAllAdapters(&adapterInfo);
if (pAdapter == nullptr) if (pAdapter == nullptr)
return false; return false;

View File

@ -23,7 +23,7 @@ namespace AdapterUtils
{ {
#ifdef _WIN32 #ifdef _WIN32
typedef IP_ADAPTER_ADDRESSES Adapter; typedef IP_ADAPTER_ADDRESSES Adapter;
typedef std::unique_ptr<IP_ADAPTER_ADDRESSES[]> AdapterBuffer; typedef std::unique_ptr<std::byte[]> AdapterBuffer;
#elif defined(__POSIX__) #elif defined(__POSIX__)
typedef ifaddrs Adapter; typedef ifaddrs Adapter;
struct IfAdaptersDeleter struct IfAdaptersDeleter

View File

@ -221,7 +221,7 @@ std::vector<AdapterEntry> PCAPAdapter::GetAdapters()
entry.guid = std::string(&d->name[strlen(PCAPPREFIX)]); entry.guid = std::string(&d->name[strlen(PCAPPREFIX)]);
IP_ADAPTER_ADDRESSES adapterInfo; IP_ADAPTER_ADDRESSES adapterInfo;
std::unique_ptr<IP_ADAPTER_ADDRESSES[]> buffer; AdapterUtils::AdapterBuffer buffer;
if (AdapterUtils::GetAdapter(entry.guid, &adapterInfo, &buffer)) if (AdapterUtils::GetAdapter(entry.guid, &adapterInfo, &buffer))
entry.name = StringUtil::WideStringToUTF8String(std::wstring(adapterInfo.FriendlyName)); entry.name = StringUtil::WideStringToUTF8String(std::wstring(adapterInfo.FriendlyName));