[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:
Vitaly Buka 2017-02-02 20:10:07 +00:00
parent 357b048666
commit 89d054fc64
4 changed files with 53 additions and 11 deletions

View File

@ -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;

View File

@ -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

View File

@ -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"

View File

@ -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);
}