Skip to content

Commit 844f6ef

Browse files
jkoritzinskyAaronRobinsonMSFTelinor-fung
authored
Fix use-after-free in EventPipe (#81135)
Co-authored-by: Aaron Robinson <arobins@microsoft.com> Co-authored-by: Elinor Fung <elfung@microsoft.com>
1 parent cd3f357 commit 844f6ef

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed

src/coreclr/inc/sstring.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,9 @@ class EMPTY_BASES_DECL SString : private SBuffer
518518
//Returns the unicode string, the caller is responsible for lifetime of the string
519519
WCHAR *GetCopyOfUnicodeString();
520520

521+
//Returns the UTF8 string, the caller is responsible for the lifetime of the string
522+
UTF8 *GetCopyOfUTF8String();
523+
521524
// Get the max size that can be passed to OpenUnicodeBuffer without causing allocations.
522525
COUNT_T GetUnicodeAllocation();
523526

src/coreclr/inc/sstring.inl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1648,6 +1648,28 @@ inline WCHAR *SString::GetCopyOfUnicodeString()
16481648
SS_RETURN buffer.Extract();
16491649
}
16501650

1651+
//----------------------------------------------------------------------------
1652+
// Return a copy of the underlying buffer, the caller is responsible for managing
1653+
// the returned memory
1654+
//----------------------------------------------------------------------------
1655+
inline UTF8 *SString::GetCopyOfUTF8String()
1656+
{
1657+
SS_CONTRACT(UTF8*)
1658+
{
1659+
GC_NOTRIGGER;
1660+
PRECONDITION(CheckPointer(this));
1661+
SS_POSTCONDITION(CheckPointer(buffer));
1662+
THROWS;
1663+
}
1664+
SS_CONTRACT_END;
1665+
NewArrayHolder<UTF8> buffer = NULL;
1666+
1667+
buffer = new UTF8[GetSize()];
1668+
strncpy(buffer, GetUTF8(), GetSize());
1669+
1670+
SS_RETURN buffer.Extract();
1671+
}
1672+
16511673
//----------------------------------------------------------------------------
16521674
// Return a writeable buffer that can store 'countChars'+1 ansi characters.
16531675
// Call CloseBuffer when done.
@@ -1895,6 +1917,7 @@ FORCEINLINE SString::CIterator SString::End() const
18951917
}
18961918
SS_CONTRACT_END;
18971919

1920+
ConvertToIteratable();
18981921
ConvertToIteratable();
18991922

19001923
SS_RETURN CIterator(this, GetCount());

src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,12 +1137,34 @@ ep_rt_entrypoint_assembly_name_get_utf8 (void)
11371137

11381138
// get the name from the host if we can't get assembly info, e.g., if the runtime is
11391139
// suspended before an assembly is loaded.
1140-
SString assembly_name;
1141-
if (HostInformation::GetProperty (HOST_PROPERTY_ENTRY_ASSEMBLY_NAME, assembly_name))
1142-
return assembly_name.GetUTF8 ();
1140+
// We'll cache the value in a static function global as the caller expects the lifetime of this value
1141+
// to outlast the calling function.
1142+
static const ep_char8_t* entrypoint_assembly_name = nullptr;
1143+
if (entrypoint_assembly_name == nullptr)
1144+
{
1145+
const ep_char8_t* entrypoint_assembly_name_local;
1146+
SString assembly_name;
1147+
if (HostInformation::GetProperty (HOST_PROPERTY_ENTRY_ASSEMBLY_NAME, assembly_name))
1148+
{
1149+
entrypoint_assembly_name_local = reinterpret_cast<const ep_char8_t*>(assembly_name.GetCopyOfUTF8String ());
1150+
}
1151+
else
1152+
{
1153+
// fallback to the empty string
1154+
// Allocate a new empty string here so we consistently allocate with the same allocator no matter our code-path.
1155+
entrypoint_assembly_name_local = new ep_char8_t [1] { '\0' };
1156+
}
1157+
// Try setting this entrypoint name as the cached value.
1158+
// If someone else beat us to it, free the memory we allocated.
1159+
// We want to only leak the one global copy of the entrypoint name,
1160+
// not multiple copies.
1161+
if (InterlockedCompareExchangeT(&entrypoint_assembly_name, entrypoint_assembly_name_local, nullptr) != nullptr)
1162+
{
1163+
delete[] entrypoint_assembly_name_local;
1164+
}
1165+
}
11431166

1144-
// fallback to the empty string
1145-
return reinterpret_cast<const ep_char8_t*>("");
1167+
return entrypoint_assembly_name;
11461168
}
11471169

11481170
static

0 commit comments

Comments
 (0)