mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 12:26:52 +08:00
[SampleProfile] Fix UB in Demangler invocation. (#137659)
Currently the backing buffer of a `std::vector<char>` is passed[1] to `Demangler.getFunctionBaseName`. However, deeply inside the call stack `OutputBuffer::grow` will call[2] `std::realloc` if it needs to grow the buffer, leading to UB. The demangler APIs specify[3] that "`Buf` and `N` behave like the second and third parameters to `__cxa_demangle`" and the docs for the latter say[4] that the output buffer must be allocated with `malloc` (but can also be `NULL` and will then be realloced accordingly). Note: PR #135863 changed this from a stack array to a `std::vector` and increased the size to 65K, but this can still lead to a crash if the demangled name is longer than that - yes, I'm surprised that a >65K-long function name happens in practice... [1]:d7e631c7cd/llvm/lib/Transforms/IPO/SampleProfileMatcher.cpp (L744)[2]:d7e631c7cd/llvm/include/llvm/Demangle/Utility.h (L50)[3]:d7e631c7cd/llvm/include/llvm/Demangle/Demangle.h (L92-L93)[4]: https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html
This commit is contained in:
committed by
GitHub
parent
4e4c6d7e27
commit
acaf403c63
@@ -737,14 +737,16 @@ bool SampleProfileMatcher::functionMatchesProfileHelper(
|
||||
auto FunctionName = FName.str();
|
||||
if (Demangler.partialDemangle(FunctionName.c_str()))
|
||||
return std::string();
|
||||
constexpr size_t MaxBaseNameSize = 65536;
|
||||
std::vector<char> BaseNameBuf(MaxBaseNameSize, 0);
|
||||
size_t BaseNameSize = MaxBaseNameSize;
|
||||
char *BaseNamePtr =
|
||||
Demangler.getFunctionBaseName(BaseNameBuf.data(), &BaseNameSize);
|
||||
return (BaseNamePtr && BaseNameSize)
|
||||
? std::string(BaseNamePtr, BaseNameSize)
|
||||
: std::string();
|
||||
size_t BaseNameSize = 0;
|
||||
// The demangler API follows the __cxa_demangle one, and thus needs a
|
||||
// pointer that originates from malloc (or nullptr) and the caller is
|
||||
// responsible for free()-ing the buffer.
|
||||
char *BaseNamePtr = Demangler.getFunctionBaseName(nullptr, &BaseNameSize);
|
||||
std::string Result = (BaseNamePtr && BaseNameSize)
|
||||
? std::string(BaseNamePtr, BaseNameSize)
|
||||
: std::string();
|
||||
free(BaseNamePtr);
|
||||
return Result;
|
||||
};
|
||||
auto IRBaseName = GetBaseName(IRFunc.getName());
|
||||
auto ProfBaseName = GetBaseName(ProfFunc.stringRef());
|
||||
|
||||
Reference in New Issue
Block a user