forked from OSchip/llvm-project
[compiler-rt] Fix incorrect use of snprintf
Summary: snprintf returns buffer size needed for printing. If buffer was small, calling code receives incorrectly symbolized buffer and fail. Reviewers: eugenis Subscribers: kubamracek, dberris, kcc Differential Revision: https://reviews.llvm.org/D29440 llvm-svn: 293930
This commit is contained in:
parent
357b048666
commit
89d054fc64
|
@ -356,11 +356,19 @@ const char *LLVMSymbolizer::FormatAndSendCommand(bool is_data,
|
|||
CHECK(module_name);
|
||||
const char *is_data_str = is_data ? "DATA " : "";
|
||||
if (arch == kModuleArchUnknown) {
|
||||
internal_snprintf(buffer_, kBufferSize, "%s\"%s\" 0x%zx\n", is_data_str,
|
||||
module_name, module_offset);
|
||||
if (internal_snprintf(buffer_, kBufferSize, "%s\"%s\" 0x%zx\n", is_data_str,
|
||||
module_name,
|
||||
module_offset) >= static_cast<int>(kBufferSize)) {
|
||||
Report("WARNING: Command buffer too small");
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
internal_snprintf(buffer_, kBufferSize, "%s\"%s:%s\" 0x%zx\n", is_data_str,
|
||||
module_name, ModuleArchToString(arch), module_offset);
|
||||
if (internal_snprintf(buffer_, kBufferSize, "%s\"%s:%s\" 0x%zx\n",
|
||||
is_data_str, module_name, ModuleArchToString(arch),
|
||||
module_offset) >= static_cast<int>(kBufferSize)) {
|
||||
Report("WARNING: Command buffer too small");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return symbolizer_process_->SendCommand(buffer_);
|
||||
}
|
||||
|
@ -426,6 +434,11 @@ bool SymbolizerProcess::ReadFromSymbolizer(char *buffer, uptr max_length) {
|
|||
read_len += just_read;
|
||||
if (ReachedEndOfOutput(buffer, read_len))
|
||||
break;
|
||||
if (read_len + 1 == max_length) {
|
||||
Report("WARNING: Symbolizer buffer too small");
|
||||
read_len = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
buffer[read_len] = '\0';
|
||||
return true;
|
||||
|
|
|
@ -424,7 +424,6 @@ class InternalSymbolizer : public SymbolizerTool {
|
|||
InternalSymbolizer() { }
|
||||
|
||||
static const int kBufferSize = 16 * 1024;
|
||||
static const int kMaxDemangledNameSize = 1024;
|
||||
char buffer_[kBufferSize];
|
||||
};
|
||||
#else // SANITIZER_SUPPORTS_WEAK_HOOKS
|
||||
|
|
|
@ -41,8 +41,8 @@ bool __sanitizer_symbolize_code(const char *ModuleName, uint64_t ModuleOffset,
|
|||
getDefaultSymbolizer()->symbolizeInlinedCode(ModuleName, ModuleOffset);
|
||||
Printer << (ResOrErr ? ResOrErr.get() : llvm::DIInliningInfo());
|
||||
}
|
||||
__sanitizer::internal_snprintf(Buffer, MaxLength, "%s", Result.c_str());
|
||||
return true;
|
||||
return __sanitizer::internal_snprintf(Buffer, MaxLength, "%s",
|
||||
Result.c_str()) < MaxLength;
|
||||
}
|
||||
|
||||
bool __sanitizer_symbolize_data(const char *ModuleName, uint64_t ModuleOffset,
|
||||
|
@ -55,8 +55,8 @@ bool __sanitizer_symbolize_data(const char *ModuleName, uint64_t ModuleOffset,
|
|||
getDefaultSymbolizer()->symbolizeData(ModuleName, ModuleOffset);
|
||||
Printer << (ResOrErr ? ResOrErr.get() : llvm::DIGlobal());
|
||||
}
|
||||
__sanitizer::internal_snprintf(Buffer, MaxLength, "%s", Result.c_str());
|
||||
return true;
|
||||
return __sanitizer::internal_snprintf(Buffer, MaxLength, "%s",
|
||||
Result.c_str()) < MaxLength;
|
||||
}
|
||||
|
||||
void __sanitizer_symbolize_flush() { getDefaultSymbolizer()->flush(); }
|
||||
|
@ -65,8 +65,10 @@ int __sanitizer_symbolize_demangle(const char *Name, char *Buffer,
|
|||
int MaxLength) {
|
||||
std::string Result =
|
||||
llvm::symbolize::LLVMSymbolizer::DemangleName(Name, nullptr);
|
||||
__sanitizer::internal_snprintf(Buffer, MaxLength, "%s", Result.c_str());
|
||||
return static_cast<int>(Result.size() + 1);
|
||||
return __sanitizer::internal_snprintf(Buffer, MaxLength, "%s",
|
||||
Result.c_str()) < MaxLength
|
||||
? static_cast<int>(Result.size() + 1)
|
||||
: 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// RUN: %clangxx -O0 %s -o %t && %run %t 2>&1 | FileCheck %s
|
||||
|
||||
// Test that symbolizer does not crash on frame with large function name.
|
||||
|
||||
#include <sanitizer/common_interface_defs.h>
|
||||
#include <vector>
|
||||
|
||||
template <int N> struct A {
|
||||
template <class T> void RecursiveTemplateFunction(const T &t);
|
||||
};
|
||||
|
||||
template <int N>
|
||||
template <class T>
|
||||
__attribute__((noinline)) void A<N>::RecursiveTemplateFunction(const T &) {
|
||||
std::vector<T> t;
|
||||
return A<N - 1>().RecursiveTemplateFunction(t);
|
||||
}
|
||||
|
||||
template <>
|
||||
template <class T>
|
||||
__attribute__((noinline)) void A<0>::RecursiveTemplateFunction(const T &) {
|
||||
__sanitizer_print_stack_trace();
|
||||
}
|
||||
|
||||
int main() {
|
||||
// CHECK: {{vector<.*vector<.*vector<.*vector<.*vector<}}
|
||||
A<10>().RecursiveTemplateFunction(0);
|
||||
}
|
Loading…
Reference in New Issue