Skip to content

Commit 905e59e

Browse files
committed
[Sanitizer] Use % patterns in report paths
1 parent a2ce564 commit 905e59e

File tree

3 files changed

+115
-18
lines changed

3 files changed

+115
-18
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_file.cpp

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,75 @@ static void RecursiveCreateParentDirs(char *path) {
9696
}
9797
}
9898

99+
/// Parse the report path \p pattern and copy the parsed path to \p dest.
100+
///
101+
/// * `%%` becomes `%`
102+
/// * `%H` expands to the environment variable `HOME`
103+
/// * `%t` expands to the environment variable `TMPDIR`
104+
/// * `%p` expands to the process ID (PID)
105+
static void ParseAndSetPath(const char *pattern, char *dest,
106+
const uptr dest_size) {
107+
CHECK(pattern);
108+
CHECK(dest);
109+
CHECK_GT(dest_size, 1);
110+
dest[0] = '\0';
111+
uptr next_substr_start_idx = 0;
112+
for (uptr i = 0; i < internal_strlen(pattern) - 1; i++) {
113+
if (pattern[i] != '%')
114+
continue;
115+
int bytes_to_copy = i - next_substr_start_idx;
116+
// Copy over previous substring.
117+
CHECK_LT(internal_strlcat(dest, pattern + next_substr_start_idx,
118+
internal_strlen(dest) + bytes_to_copy + 1),
119+
dest_size);
120+
const char *str_to_concat;
121+
switch (pattern[++i]) {
122+
case '%':
123+
str_to_concat = "%";
124+
break;
125+
case 'H':
126+
str_to_concat = GetEnv("HOME");
127+
break;
128+
case 't':
129+
str_to_concat = GetEnv("TMPDIR");
130+
break;
131+
case 'p': {
132+
// Use printf directly to write the PID since it's not a static string.
133+
int remaining_capacity = dest_size - internal_strlen(dest);
134+
int bytes_copied =
135+
internal_snprintf(dest + internal_strlen(dest), remaining_capacity,
136+
"%ld", internal_getpid());
137+
CHECK_GT(bytes_copied, 0);
138+
CHECK_LT(bytes_copied, remaining_capacity);
139+
str_to_concat = "";
140+
break;
141+
}
142+
default: {
143+
// Invalid pattern: fallback to original pattern.
144+
const char *message = "ERROR: Unexpected pattern: ";
145+
WriteToFile(kStderrFd, message, internal_strlen(message));
146+
WriteToFile(kStderrFd, pattern, internal_strlen(pattern));
147+
WriteToFile(kStderrFd, "\n", internal_strlen("\n"));
148+
CHECK_LT(internal_strlcpy(dest, pattern, dest_size), dest_size);
149+
return;
150+
}
151+
}
152+
CHECK(str_to_concat);
153+
CHECK_LT(internal_strlcat(dest, str_to_concat, dest_size), dest_size);
154+
next_substr_start_idx = i + 1;
155+
}
156+
CHECK_LT(internal_strlcat(dest, pattern + next_substr_start_idx, dest_size),
157+
dest_size);
158+
}
159+
99160
void ReportFile::SetReportPath(const char *path) {
100161
if (path) {
101162
uptr len = internal_strlen(path);
102163
if (len > sizeof(path_prefix) - 100) {
103-
Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n", path[0], path[1],
104-
path[2], path[3], path[4], path[5], path[6], path[7]);
164+
const char *message = "ERROR: Path is too long: ";
165+
WriteToFile(kStderrFd, message, internal_strlen(message));
166+
WriteToFile(kStderrFd, path, 8);
167+
WriteToFile(kStderrFd, "\n", internal_strlen("\n"));
105168
Die();
106169
}
107170
}
@@ -115,7 +178,7 @@ void ReportFile::SetReportPath(const char *path) {
115178
} else if (internal_strcmp(path, "stdout") == 0) {
116179
fd = kStdoutFd;
117180
} else {
118-
internal_snprintf(path_prefix, kMaxPathLength, "%s", path);
181+
ParseAndSetPath(path, path_prefix, kMaxPathLength);
119182
RecursiveCreateParentDirs(path_prefix);
120183
}
121184
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %clangxx -O2 %s -o %t
2+
// RUN: not %env %run %t 2>&1 | FileCheck %s --check-prefix=ERROR1
3+
// RUN: not %env %run %t A 2>&1 | FileCheck %s --check-prefix=ERROR2
4+
5+
#include <sanitizer/common_interface_defs.h>
6+
#include <stdio.h>
7+
8+
int main(int argc, char **argv) {
9+
char buff[4096];
10+
if (argc == 1) {
11+
// Try setting again with an invalid/inaccessible directory.
12+
sprintf(buff, "%s/report", argv[0]);
13+
// ERROR1: Can't create directory: {{.*}}
14+
} else {
15+
snprintf(buff, sizeof(buff), "%04095d", 42);
16+
// ERROR2: Path is too long: 00000000
17+
}
18+
__sanitizer_set_report_path(buff);
19+
}
Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,42 @@
11
// Test __sanitizer_set_report_path and __sanitizer_get_report_path:
22
// RUN: %clangxx -O2 %s -o %t
3-
// RUN: not %run %t 2>&1 | FileCheck %s
3+
// RUN: %env HOME=%t.homedir TMPDIR=%t.tmpdir %run %t 2>%t.err | FileCheck %s
4+
// RUN: FileCheck %s --input-file=%t.err --check-prefix=ERROR
45

5-
#include <assert.h>
66
#include <sanitizer/common_interface_defs.h>
77
#include <stdio.h>
88
#include <string.h>
99

10-
volatile int *null = 0;
11-
1210
int main(int argc, char **argv) {
13-
char buff[1000];
11+
char buff[4096];
1412
sprintf(buff, "%s.report_path/report", argv[0]);
1513
__sanitizer_set_report_path(buff);
16-
assert(strncmp(buff, __sanitizer_get_report_path(), strlen(buff)) == 0);
14+
// CHECK: {{.*}}.report_path/report.[[PID:[0-9]+]]
15+
printf("%s\n", __sanitizer_get_report_path());
1716

18-
// Try setting again with an invalid/inaccessible directory.
19-
char buff_bad[1000];
20-
sprintf(buff_bad, "%s/report", argv[0]);
21-
fprintf(stderr, "Expected bad report path: %s\n", buff_bad);
22-
// CHECK: Expected bad report path: [[BADPATH:.*]]/report
23-
__sanitizer_set_report_path(buff_bad);
24-
assert(strncmp(buff, __sanitizer_get_report_path(), strlen(buff)) == 0);
25-
}
17+
strcpy(buff, "%H/foo");
18+
__sanitizer_set_report_path(buff);
19+
// CHECK: [[T:.*]].homedir/foo.[[PID]]
20+
printf("%s\n", __sanitizer_get_report_path());
2621

27-
// CHECK: ERROR: Can't create directory: [[BADPATH]]
22+
strcpy(buff, "%t/foo");
23+
__sanitizer_set_report_path(buff);
24+
// CHECK: [[T]].tmpdir/foo.[[PID]]
25+
printf("%s\n", __sanitizer_get_report_path());
26+
27+
strcpy(buff, "%H/%p/%%foo");
28+
__sanitizer_set_report_path(buff);
29+
// CHECK: [[T]].homedir/[[PID]]/%foo.[[PID]]
30+
printf("%s\n", __sanitizer_get_report_path());
31+
32+
strcpy(buff, "%%foo%%bar");
33+
__sanitizer_set_report_path(buff);
34+
// CHECK: %foo%bar.[[PID]]
35+
printf("%s\n", __sanitizer_get_report_path());
36+
37+
strcpy(buff, "%%foo%ba%%r");
38+
__sanitizer_set_report_path(buff);
39+
// ERROR: Unexpected pattern: %%foo%ba%%r
40+
// CHECK: %%foo%ba%%r.[[PID]]
41+
printf("%s\n", __sanitizer_get_report_path());
42+
}

0 commit comments

Comments
 (0)