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