Skip to content

Commit acaf403

Browse files
authored
[SampleProfile] Fix UB in Demangler invocation. (llvm#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 llvm#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]: https://github.com/llvm/llvm-project/blob/d7e631c7cd6d9c13b9519991ec6becf08bc6b8aa/llvm/lib/Transforms/IPO/SampleProfileMatcher.cpp#L744 [2]: https://github.com/llvm/llvm-project/blob/d7e631c7cd6d9c13b9519991ec6becf08bc6b8aa/llvm/include/llvm/Demangle/Utility.h#L50 [3]: https://github.com/llvm/llvm-project/blob/d7e631c7cd6d9c13b9519991ec6becf08bc6b8aa/llvm/include/llvm/Demangle/Demangle.h#L92-L93 [4]: https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html
1 parent 4e4c6d7 commit acaf403

File tree

1 file changed

+10
-8
lines changed

1 file changed

+10
-8
lines changed

llvm/lib/Transforms/IPO/SampleProfileMatcher.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -737,14 +737,16 @@ bool SampleProfileMatcher::functionMatchesProfileHelper(
737737
auto FunctionName = FName.str();
738738
if (Demangler.partialDemangle(FunctionName.c_str()))
739739
return std::string();
740-
constexpr size_t MaxBaseNameSize = 65536;
741-
std::vector<char> BaseNameBuf(MaxBaseNameSize, 0);
742-
size_t BaseNameSize = MaxBaseNameSize;
743-
char *BaseNamePtr =
744-
Demangler.getFunctionBaseName(BaseNameBuf.data(), &BaseNameSize);
745-
return (BaseNamePtr && BaseNameSize)
746-
? std::string(BaseNamePtr, BaseNameSize)
747-
: std::string();
740+
size_t BaseNameSize = 0;
741+
// The demangler API follows the __cxa_demangle one, and thus needs a
742+
// pointer that originates from malloc (or nullptr) and the caller is
743+
// responsible for free()-ing the buffer.
744+
char *BaseNamePtr = Demangler.getFunctionBaseName(nullptr, &BaseNameSize);
745+
std::string Result = (BaseNamePtr && BaseNameSize)
746+
? std::string(BaseNamePtr, BaseNameSize)
747+
: std::string();
748+
free(BaseNamePtr);
749+
return Result;
748750
};
749751
auto IRBaseName = GetBaseName(IRFunc.getName());
750752
auto ProfBaseName = GetBaseName(ProfFunc.stringRef());

0 commit comments

Comments
 (0)