annotate libsanitizer/sanitizer_common/sanitizer_file.cc @ 144:8f4e72ab4e11

fix segmentation fault caused by nothing next cur_op to end
author Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Sun, 23 Dec 2018 21:23:56 +0900
parents 04ced10e8804
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 //===-- sanitizer_file.cc ------------------------------------------------===//
kono
parents:
diff changeset
2 //
kono
parents:
diff changeset
3 // This file is distributed under the University of Illinois Open Source
kono
parents:
diff changeset
4 // License. See LICENSE.TXT for details.
kono
parents:
diff changeset
5 //
kono
parents:
diff changeset
6 //===---------------------------------------------------------------------===//
kono
parents:
diff changeset
7 //
kono
parents:
diff changeset
8 // This file is shared between AddressSanitizer and ThreadSanitizer
kono
parents:
diff changeset
9 // run-time libraries. It defines filesystem-related interfaces. This
kono
parents:
diff changeset
10 // is separate from sanitizer_common.cc so that it's simpler to disable
kono
parents:
diff changeset
11 // all the filesystem support code for a port that doesn't use it.
kono
parents:
diff changeset
12 //
kono
parents:
diff changeset
13 //===---------------------------------------------------------------------===//
kono
parents:
diff changeset
14
kono
parents:
diff changeset
15 #include "sanitizer_platform.h"
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 #if !SANITIZER_FUCHSIA
kono
parents:
diff changeset
18
kono
parents:
diff changeset
19 #include "sanitizer_common.h"
kono
parents:
diff changeset
20 #include "sanitizer_file.h"
kono
parents:
diff changeset
21
kono
parents:
diff changeset
22 namespace __sanitizer {
kono
parents:
diff changeset
23
kono
parents:
diff changeset
24 void CatastrophicErrorWrite(const char *buffer, uptr length) {
kono
parents:
diff changeset
25 WriteToFile(kStderrFd, buffer, length);
kono
parents:
diff changeset
26 }
kono
parents:
diff changeset
27
kono
parents:
diff changeset
28 StaticSpinMutex report_file_mu;
kono
parents:
diff changeset
29 ReportFile report_file = {&report_file_mu, kStderrFd, "", "", 0};
kono
parents:
diff changeset
30
kono
parents:
diff changeset
31 void RawWrite(const char *buffer) {
kono
parents:
diff changeset
32 report_file.Write(buffer, internal_strlen(buffer));
kono
parents:
diff changeset
33 }
kono
parents:
diff changeset
34
kono
parents:
diff changeset
35 void ReportFile::ReopenIfNecessary() {
kono
parents:
diff changeset
36 mu->CheckLocked();
kono
parents:
diff changeset
37 if (fd == kStdoutFd || fd == kStderrFd) return;
kono
parents:
diff changeset
38
kono
parents:
diff changeset
39 uptr pid = internal_getpid();
kono
parents:
diff changeset
40 // If in tracer, use the parent's file.
kono
parents:
diff changeset
41 if (pid == stoptheworld_tracer_pid)
kono
parents:
diff changeset
42 pid = stoptheworld_tracer_ppid;
kono
parents:
diff changeset
43 if (fd != kInvalidFd) {
kono
parents:
diff changeset
44 // If the report file is already opened by the current process,
kono
parents:
diff changeset
45 // do nothing. Otherwise the report file was opened by the parent
kono
parents:
diff changeset
46 // process, close it now.
kono
parents:
diff changeset
47 if (fd_pid == pid)
kono
parents:
diff changeset
48 return;
kono
parents:
diff changeset
49 else
kono
parents:
diff changeset
50 CloseFile(fd);
kono
parents:
diff changeset
51 }
kono
parents:
diff changeset
52
kono
parents:
diff changeset
53 const char *exe_name = GetProcessName();
kono
parents:
diff changeset
54 if (common_flags()->log_exe_name && exe_name) {
kono
parents:
diff changeset
55 internal_snprintf(full_path, kMaxPathLength, "%s.%s.%zu", path_prefix,
kono
parents:
diff changeset
56 exe_name, pid);
kono
parents:
diff changeset
57 } else {
kono
parents:
diff changeset
58 internal_snprintf(full_path, kMaxPathLength, "%s.%zu", path_prefix, pid);
kono
parents:
diff changeset
59 }
kono
parents:
diff changeset
60 fd = OpenFile(full_path, WrOnly);
kono
parents:
diff changeset
61 if (fd == kInvalidFd) {
kono
parents:
diff changeset
62 const char *ErrorMsgPrefix = "ERROR: Can't open file: ";
kono
parents:
diff changeset
63 WriteToFile(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix));
kono
parents:
diff changeset
64 WriteToFile(kStderrFd, full_path, internal_strlen(full_path));
kono
parents:
diff changeset
65 Die();
kono
parents:
diff changeset
66 }
kono
parents:
diff changeset
67 fd_pid = pid;
kono
parents:
diff changeset
68 }
kono
parents:
diff changeset
69
kono
parents:
diff changeset
70 void ReportFile::SetReportPath(const char *path) {
kono
parents:
diff changeset
71 if (!path)
kono
parents:
diff changeset
72 return;
kono
parents:
diff changeset
73 uptr len = internal_strlen(path);
kono
parents:
diff changeset
74 if (len > sizeof(path_prefix) - 100) {
kono
parents:
diff changeset
75 Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n",
kono
parents:
diff changeset
76 path[0], path[1], path[2], path[3],
kono
parents:
diff changeset
77 path[4], path[5], path[6], path[7]);
kono
parents:
diff changeset
78 Die();
kono
parents:
diff changeset
79 }
kono
parents:
diff changeset
80
kono
parents:
diff changeset
81 SpinMutexLock l(mu);
kono
parents:
diff changeset
82 if (fd != kStdoutFd && fd != kStderrFd && fd != kInvalidFd)
kono
parents:
diff changeset
83 CloseFile(fd);
kono
parents:
diff changeset
84 fd = kInvalidFd;
kono
parents:
diff changeset
85 if (internal_strcmp(path, "stdout") == 0) {
kono
parents:
diff changeset
86 fd = kStdoutFd;
kono
parents:
diff changeset
87 } else if (internal_strcmp(path, "stderr") == 0) {
kono
parents:
diff changeset
88 fd = kStderrFd;
kono
parents:
diff changeset
89 } else {
kono
parents:
diff changeset
90 internal_snprintf(path_prefix, kMaxPathLength, "%s", path);
kono
parents:
diff changeset
91 }
kono
parents:
diff changeset
92 }
kono
parents:
diff changeset
93
kono
parents:
diff changeset
94 bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
kono
parents:
diff changeset
95 uptr *read_len, uptr max_len, error_t *errno_p) {
kono
parents:
diff changeset
96 uptr PageSize = GetPageSizeCached();
kono
parents:
diff changeset
97 uptr kMinFileLen = PageSize;
kono
parents:
diff changeset
98 *buff = nullptr;
kono
parents:
diff changeset
99 *buff_size = 0;
kono
parents:
diff changeset
100 *read_len = 0;
kono
parents:
diff changeset
101 // The files we usually open are not seekable, so try different buffer sizes.
kono
parents:
diff changeset
102 for (uptr size = kMinFileLen; size <= max_len; size *= 2) {
kono
parents:
diff changeset
103 fd_t fd = OpenFile(file_name, RdOnly, errno_p);
kono
parents:
diff changeset
104 if (fd == kInvalidFd) return false;
kono
parents:
diff changeset
105 UnmapOrDie(*buff, *buff_size);
kono
parents:
diff changeset
106 *buff = (char*)MmapOrDie(size, __func__);
kono
parents:
diff changeset
107 *buff_size = size;
kono
parents:
diff changeset
108 *read_len = 0;
kono
parents:
diff changeset
109 // Read up to one page at a time.
kono
parents:
diff changeset
110 bool reached_eof = false;
kono
parents:
diff changeset
111 while (*read_len + PageSize <= size) {
kono
parents:
diff changeset
112 uptr just_read;
kono
parents:
diff changeset
113 if (!ReadFromFile(fd, *buff + *read_len, PageSize, &just_read, errno_p)) {
kono
parents:
diff changeset
114 UnmapOrDie(*buff, *buff_size);
kono
parents:
diff changeset
115 return false;
kono
parents:
diff changeset
116 }
kono
parents:
diff changeset
117 if (just_read == 0) {
kono
parents:
diff changeset
118 reached_eof = true;
kono
parents:
diff changeset
119 break;
kono
parents:
diff changeset
120 }
kono
parents:
diff changeset
121 *read_len += just_read;
kono
parents:
diff changeset
122 }
kono
parents:
diff changeset
123 CloseFile(fd);
kono
parents:
diff changeset
124 if (reached_eof) // We've read the whole file.
kono
parents:
diff changeset
125 break;
kono
parents:
diff changeset
126 }
kono
parents:
diff changeset
127 return true;
kono
parents:
diff changeset
128 }
kono
parents:
diff changeset
129
kono
parents:
diff changeset
130 static const char kPathSeparator = SANITIZER_WINDOWS ? ';' : ':';
kono
parents:
diff changeset
131
kono
parents:
diff changeset
132 char *FindPathToBinary(const char *name) {
kono
parents:
diff changeset
133 if (FileExists(name)) {
kono
parents:
diff changeset
134 return internal_strdup(name);
kono
parents:
diff changeset
135 }
kono
parents:
diff changeset
136
kono
parents:
diff changeset
137 const char *path = GetEnv("PATH");
kono
parents:
diff changeset
138 if (!path)
kono
parents:
diff changeset
139 return nullptr;
kono
parents:
diff changeset
140 uptr name_len = internal_strlen(name);
kono
parents:
diff changeset
141 InternalScopedBuffer<char> buffer(kMaxPathLength);
kono
parents:
diff changeset
142 const char *beg = path;
kono
parents:
diff changeset
143 while (true) {
kono
parents:
diff changeset
144 const char *end = internal_strchrnul(beg, kPathSeparator);
kono
parents:
diff changeset
145 uptr prefix_len = end - beg;
kono
parents:
diff changeset
146 if (prefix_len + name_len + 2 <= kMaxPathLength) {
kono
parents:
diff changeset
147 internal_memcpy(buffer.data(), beg, prefix_len);
kono
parents:
diff changeset
148 buffer[prefix_len] = '/';
kono
parents:
diff changeset
149 internal_memcpy(&buffer[prefix_len + 1], name, name_len);
kono
parents:
diff changeset
150 buffer[prefix_len + 1 + name_len] = '\0';
kono
parents:
diff changeset
151 if (FileExists(buffer.data()))
kono
parents:
diff changeset
152 return internal_strdup(buffer.data());
kono
parents:
diff changeset
153 }
kono
parents:
diff changeset
154 if (*end == '\0') break;
kono
parents:
diff changeset
155 beg = end + 1;
kono
parents:
diff changeset
156 }
kono
parents:
diff changeset
157 return nullptr;
kono
parents:
diff changeset
158 }
kono
parents:
diff changeset
159
kono
parents:
diff changeset
160 } // namespace __sanitizer
kono
parents:
diff changeset
161
kono
parents:
diff changeset
162 using namespace __sanitizer; // NOLINT
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164 extern "C" {
kono
parents:
diff changeset
165 void __sanitizer_set_report_path(const char *path) {
kono
parents:
diff changeset
166 report_file.SetReportPath(path);
kono
parents:
diff changeset
167 }
kono
parents:
diff changeset
168
kono
parents:
diff changeset
169 void __sanitizer_set_report_fd(void *fd) {
kono
parents:
diff changeset
170 report_file.fd = (fd_t)reinterpret_cast<uptr>(fd);
kono
parents:
diff changeset
171 report_file.fd_pid = internal_getpid();
kono
parents:
diff changeset
172 }
kono
parents:
diff changeset
173 } // extern "C"
kono
parents:
diff changeset
174
kono
parents:
diff changeset
175 #endif // !SANITIZER_FUCHSIA