mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 23:51:56 +00:00
[Sanitizer] Teach ReadFileToBuffer to distinguish empty file from inaccessible file.
Summary: This fixes https://code.google.com/p/address-sanitizer/issues/detail?id=399 (sanitizers crash with empty suppression files). Reviewers: kcc Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D11284 llvm-svn: 242594
This commit is contained in:
parent
2e309076f2
commit
e6c614d48a
@ -140,40 +140,40 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond,
|
||||
Die();
|
||||
}
|
||||
|
||||
uptr ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
|
||||
uptr max_len, error_t *errno_p) {
|
||||
bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
|
||||
uptr *read_len, uptr max_len, error_t *errno_p) {
|
||||
uptr PageSize = GetPageSizeCached();
|
||||
uptr kMinFileLen = PageSize;
|
||||
uptr read_len = 0;
|
||||
*buff = 0;
|
||||
*buff = nullptr;
|
||||
*buff_size = 0;
|
||||
*read_len = 0;
|
||||
// The files we usually open are not seekable, so try different buffer sizes.
|
||||
for (uptr size = kMinFileLen; size <= max_len; size *= 2) {
|
||||
fd_t fd = OpenFile(file_name, RdOnly, errno_p);
|
||||
if (fd == kInvalidFd) return 0;
|
||||
if (fd == kInvalidFd) return false;
|
||||
UnmapOrDie(*buff, *buff_size);
|
||||
*buff = (char*)MmapOrDie(size, __func__);
|
||||
*buff_size = size;
|
||||
*read_len = 0;
|
||||
// Read up to one page at a time.
|
||||
read_len = 0;
|
||||
bool reached_eof = false;
|
||||
while (read_len + PageSize <= size) {
|
||||
while (*read_len + PageSize <= size) {
|
||||
uptr just_read;
|
||||
if (!ReadFromFile(fd, *buff + read_len, PageSize, &just_read, errno_p)) {
|
||||
if (!ReadFromFile(fd, *buff + *read_len, PageSize, &just_read, errno_p)) {
|
||||
UnmapOrDie(*buff, *buff_size);
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
if (just_read == 0) {
|
||||
reached_eof = true;
|
||||
break;
|
||||
}
|
||||
read_len += just_read;
|
||||
*read_len += just_read;
|
||||
}
|
||||
CloseFile(fd);
|
||||
if (reached_eof) // We've read the whole file.
|
||||
break;
|
||||
}
|
||||
return read_len;
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef bool UptrComparisonFunction(const uptr &a, const uptr &b);
|
||||
|
@ -228,10 +228,12 @@ bool SupportsColoredOutput(fd_t fd);
|
||||
|
||||
// Opens the file 'file_name" and reads up to 'max_len' bytes.
|
||||
// The resulting buffer is mmaped and stored in '*buff'.
|
||||
// The size of the mmaped region is stored in '*buff_size',
|
||||
// Returns the number of read bytes or 0 if file can not be opened.
|
||||
uptr ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
|
||||
uptr max_len, error_t *errno_p = nullptr);
|
||||
// The size of the mmaped region is stored in '*buff_size'.
|
||||
// The total number of read bytes is stored in '*read_len'.
|
||||
// Returns true if file was successfully opened and read.
|
||||
bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
|
||||
uptr *read_len, uptr max_len = 1 << 26,
|
||||
error_t *errno_p = nullptr);
|
||||
// Maps given file to virtual memory, and returns pointer to it
|
||||
// (or NULL if mapping fails). Stores the size of mmaped region
|
||||
// in '*buff_size'.
|
||||
|
@ -54,11 +54,10 @@ class FlagHandlerInclude : public FlagHandlerBase {
|
||||
bool Parse(const char *value) final {
|
||||
char *data;
|
||||
uptr data_mapped_size;
|
||||
uptr len;
|
||||
error_t err;
|
||||
uptr len =
|
||||
ReadFileToBuffer(value, &data, &data_mapped_size,
|
||||
Max(kMaxIncludeSize, GetPageSizeCached()), &err);
|
||||
if (!len) {
|
||||
if (!ReadFileToBuffer(value, &data, &data_mapped_size, &len,
|
||||
Max(kMaxIncludeSize, GetPageSizeCached()), &err)) {
|
||||
Printf("Failed to read options from '%s': error %d\n", value, err);
|
||||
return false;
|
||||
}
|
||||
|
@ -375,8 +375,8 @@ const char *GetEnv(const char *name) {
|
||||
if (!inited) {
|
||||
inited = true;
|
||||
uptr environ_size;
|
||||
len = ReadFileToBuffer("/proc/self/environ",
|
||||
&environ, &environ_size, 1 << 26);
|
||||
if (!ReadFileToBuffer("/proc/self/environ", &environ, &environ_size, &len))
|
||||
environ = nullptr;
|
||||
}
|
||||
if (!environ || len == 0) return 0;
|
||||
uptr namelen = internal_strlen(name);
|
||||
@ -405,9 +405,13 @@ extern "C" {
|
||||
static void ReadNullSepFileToArray(const char *path, char ***arr,
|
||||
int arr_size) {
|
||||
char *buff;
|
||||
uptr buff_size = 0;
|
||||
uptr buff_size;
|
||||
uptr buff_len;
|
||||
*arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray");
|
||||
ReadFileToBuffer(path, &buff, &buff_size, 1024 * 1024);
|
||||
if (!ReadFileToBuffer(path, &buff, &buff_size, &buff_len, 1024 * 1024)) {
|
||||
(*arr)[0] = nullptr;
|
||||
return;
|
||||
}
|
||||
(*arr)[0] = buff;
|
||||
int count, i;
|
||||
for (count = 1, i = 1; ; i++) {
|
||||
@ -418,7 +422,7 @@ static void ReadNullSepFileToArray(const char *path, char ***arr,
|
||||
count++;
|
||||
}
|
||||
}
|
||||
(*arr)[count] = 0;
|
||||
(*arr)[count] = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -153,8 +153,9 @@ uptr MemoryMappingLayout::DumpListOfModules(LoadedModule *modules,
|
||||
void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) {
|
||||
char *smaps = 0;
|
||||
uptr smaps_cap = 0;
|
||||
uptr smaps_len = ReadFileToBuffer("/proc/self/smaps",
|
||||
&smaps, &smaps_cap, 64<<20);
|
||||
uptr smaps_len = 0;
|
||||
if (!ReadFileToBuffer("/proc/self/smaps", &smaps, &smaps_cap, &smaps_len))
|
||||
return;
|
||||
uptr start = 0;
|
||||
bool file = false;
|
||||
const char *pos = smaps;
|
||||
|
@ -18,8 +18,8 @@
|
||||
namespace __sanitizer {
|
||||
|
||||
void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {
|
||||
proc_maps->len = ReadFileToBuffer("/proc/self/maps", &proc_maps->data,
|
||||
&proc_maps->mmaped_size, 1 << 26);
|
||||
CHECK(ReadFileToBuffer("/proc/self/maps", &proc_maps->data,
|
||||
&proc_maps->mmaped_size, &proc_maps->len));
|
||||
}
|
||||
|
||||
static bool IsOneOf(char c, char c1, char c2) {
|
||||
|
@ -60,15 +60,13 @@ void SuppressionContext::ParseFromFile(const char *filename) {
|
||||
}
|
||||
|
||||
// Read the file.
|
||||
char *file_contents;
|
||||
uptr buffer_size;
|
||||
const uptr max_len = 1 << 26;
|
||||
uptr contents_size =
|
||||
ReadFileToBuffer(filename, &file_contents, &buffer_size, max_len);
|
||||
VPrintf(1, "%s: reading suppressions file at %s\n",
|
||||
SanitizerToolName, filename);
|
||||
|
||||
if (contents_size == 0) {
|
||||
char *file_contents;
|
||||
uptr buffer_size;
|
||||
uptr contents_size;
|
||||
if (!ReadFileToBuffer(filename, &file_contents, &buffer_size,
|
||||
&contents_size)) {
|
||||
Printf("%s: failed to read suppressions file '%s'\n", SanitizerToolName,
|
||||
filename);
|
||||
Die();
|
||||
|
@ -1,6 +1,10 @@
|
||||
// RUN: LSAN_BASE="use_registers=0:use_stacks=0"
|
||||
// RUN: %clangxx_lsan %s -o %t
|
||||
|
||||
// RUN: rm -f %t.supp
|
||||
// RUN: touch %t.supp
|
||||
// RUN: LSAN_OPTIONS="$LSAN_BASE:suppressions='%t.supp'" not %run %t 2>&1 | FileCheck %s --check-prefix=NOSUPP
|
||||
|
||||
// RUN: echo "leak:*LSanTestLeakingFunc*" > %t.supp
|
||||
// RUN: LSAN_OPTIONS="$LSAN_BASE:suppressions='%t.supp'" not %run %t 2>&1 | FileCheck %s
|
||||
|
||||
@ -24,3 +28,5 @@ int main() {
|
||||
// CHECK: Suppressions used:
|
||||
// CHECK: 1 666 *LSanTestLeakingFunc*
|
||||
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer: 1337 byte(s) leaked in 1 allocation(s)
|
||||
|
||||
// NOSUPP: SUMMARY: {{(Leak|Address)}}Sanitizer: 2003 byte(s) leaked in 2 allocation(s).
|
||||
|
Loading…
Reference in New Issue
Block a user