diff options
author | Vitaly Buka <vitalybuka@google.com> | 2017-02-02 20:10:07 +0000 |
---|---|---|
committer | Vitaly Buka <vitalybuka@google.com> | 2017-02-02 20:10:07 +0000 |
commit | 89d054fc64612018f6e38a03c29a9593974b47bd (patch) | |
tree | 1538ef969d1a159bdfb89aa355527011030ba0d7 | |
parent | 357b048666bb213b216135d1c240393cfa4df595 (diff) | |
download | bcm5719-llvm-89d054fc64612018f6e38a03c29a9593974b47bd.tar.gz bcm5719-llvm-89d054fc64612018f6e38a03c29a9593974b47bd.zip |
[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
4 files changed, 53 insertions, 11 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc index 7c377a72963..483467090f5 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc @@ -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; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc index f50d8b1840a..d3c77b510d3 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc @@ -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 diff --git a/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cc b/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cc index bd315a0c9bd..7970786a5da 100644 --- a/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cc +++ b/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cc @@ -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" diff --git a/compiler-rt/test/sanitizer_common/TestCases/symbolize_stack.cc b/compiler-rt/test/sanitizer_common/TestCases/symbolize_stack.cc new file mode 100644 index 00000000000..e50cdb0632b --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/symbolize_stack.cc @@ -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); +} |