Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions src/coreclr/debug/dbgutil/dbgutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -446,12 +446,21 @@ HRESULT ReadFromDataTarget(ICorDebugDataTarget* pDataTarget,
extern "C" bool
TryGetSymbol(ICorDebugDataTarget* dataTarget, uint64_t baseAddress, const char* symbolName, uint64_t* symbolAddress)
{
*symbolAddress = 0;

DWORD exportTableRva;
Comment on lines 447 to 451
if (FAILED(GetMachineAndDirectoryAddress(dataTarget, baseAddress, IMAGE_DIRECTORY_ENTRY_EXPORT, nullptr, &exportTableRva)))
{
return false;
}

// A module with no export directory reports a zero RVA here; there is nothing to search and
// reading at baseAddress would parse the PE headers as an IMAGE_EXPORT_DIRECTORY.
if (exportTableRva == 0)
{
return false;
}

// Manually read the export directory from the target to find the requested symbol.
IMAGE_EXPORT_DIRECTORY exportDir{};
if (FAILED(ReadFromDataTarget(dataTarget, baseAddress + exportTableRva, (BYTE*)&exportDir, sizeof(exportDir))))
Expand All @@ -460,6 +469,7 @@ TryGetSymbol(ICorDebugDataTarget* dataTarget, uint64_t baseAddress, const char*
}

uint32_t namePointerCount = VAL32(exportDir.NumberOfNames);
uint32_t exportAddressCount = VAL32(exportDir.NumberOfFunctions);
uint32_t addressTableRVA = VAL32(exportDir.AddressOfFunctions);
uint32_t ordinalTableRVA = VAL32(exportDir.AddressOfNameOrdinals);
uint32_t nameTableRVA = VAL32(exportDir.AddressOfNames);
Expand All @@ -481,7 +491,7 @@ TryGetSymbol(ICorDebugDataTarget* dataTarget, uint64_t baseAddress, const char*
}
// Allocate a buffer for the memory that we'll read out of the target image.
// We can allocate as much space as the target symbol name as we gracefully handle reading
// inaccessable memory.
// inaccessible memory.
std::unique_ptr<char[]> namePointer(new char[symbolNameLength + 1]);
// If we fail to read the memory or the name doesn't match, then we don't have the right export.
if (SUCCEEDED(ReadFromDataTarget(dataTarget, baseAddress + namePointerRVA, (BYTE*)namePointer.get(), (UINT32)symbolNameLength + 1))
Expand All @@ -493,6 +503,12 @@ TryGetSymbol(ICorDebugDataTarget* dataTarget, uint64_t baseAddress, const char*
{
return false;
}
// The ordinal indexes the export address table; reject an out-of-range value from
// untrusted image data before using it to compute a read offset.
if (ordinalForNamedExport >= exportAddressCount)
{
return false;
}
// If the name matches, we should be able to get the export
uint32_t exportRVA = 0;
if (FAILED(ReadFromDataTarget(dataTarget, baseAddress + addressTableRVA + sizeof(uint32_t) * ordinalForNamedExport, (BYTE*)&exportRVA, sizeof(exportRVA))))
Expand All @@ -505,7 +521,6 @@ TryGetSymbol(ICorDebugDataTarget* dataTarget, uint64_t baseAddress, const char*
}
}

*symbolAddress = 0;
return false;
}
#endif
Loading