[compiler-rt] [Sanitizer] Use % patterns in report paths (PR #141820)
Ellis Hoag via llvm-commits
llvm-commits at lists.llvm.org
Thu May 29 11:12:41 PDT 2025
https://github.com/ellishg updated https://github.com/llvm/llvm-project/pull/141820
>From 905e59e453e0086d63555becd8eefcdabd2c9d4f Mon Sep 17 00:00:00 2001
From: Ellis Hoag <ellishoag at meta.com>
Date: Wed, 28 May 2025 11:34:52 -0700
Subject: [PATCH 1/3] [Sanitizer] Use % patterns in report paths
---
.../lib/sanitizer_common/sanitizer_file.cpp | 69 ++++++++++++++++++-
.../Posix/sanitizer_set_report_path_fail.cpp | 19 +++++
.../Posix/sanitizer_set_report_path_test.cpp | 45 ++++++++----
3 files changed, 115 insertions(+), 18 deletions(-)
create mode 100644 compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_fail.cpp
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp
index 96af270f9d8b5..b55c4ff093c1b 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp
@@ -96,12 +96,75 @@ static void RecursiveCreateParentDirs(char *path) {
}
}
+/// Parse the report path \p pattern and copy the parsed path to \p dest.
+///
+/// * `%%` becomes `%`
+/// * `%H` expands to the environment variable `HOME`
+/// * `%t` expands to the environment variable `TMPDIR`
+/// * `%p` expands to the process ID (PID)
+static void ParseAndSetPath(const char *pattern, char *dest,
+ const uptr dest_size) {
+ CHECK(pattern);
+ CHECK(dest);
+ CHECK_GT(dest_size, 1);
+ dest[0] = '\0';
+ uptr next_substr_start_idx = 0;
+ for (uptr i = 0; i < internal_strlen(pattern) - 1; i++) {
+ if (pattern[i] != '%')
+ continue;
+ int bytes_to_copy = i - next_substr_start_idx;
+ // Copy over previous substring.
+ CHECK_LT(internal_strlcat(dest, pattern + next_substr_start_idx,
+ internal_strlen(dest) + bytes_to_copy + 1),
+ dest_size);
+ const char *str_to_concat;
+ switch (pattern[++i]) {
+ case '%':
+ str_to_concat = "%";
+ break;
+ case 'H':
+ str_to_concat = GetEnv("HOME");
+ break;
+ case 't':
+ str_to_concat = GetEnv("TMPDIR");
+ break;
+ case 'p': {
+ // Use printf directly to write the PID since it's not a static string.
+ int remaining_capacity = dest_size - internal_strlen(dest);
+ int bytes_copied =
+ internal_snprintf(dest + internal_strlen(dest), remaining_capacity,
+ "%ld", internal_getpid());
+ CHECK_GT(bytes_copied, 0);
+ CHECK_LT(bytes_copied, remaining_capacity);
+ str_to_concat = "";
+ break;
+ }
+ default: {
+ // Invalid pattern: fallback to original pattern.
+ const char *message = "ERROR: Unexpected pattern: ";
+ WriteToFile(kStderrFd, message, internal_strlen(message));
+ WriteToFile(kStderrFd, pattern, internal_strlen(pattern));
+ WriteToFile(kStderrFd, "\n", internal_strlen("\n"));
+ CHECK_LT(internal_strlcpy(dest, pattern, dest_size), dest_size);
+ return;
+ }
+ }
+ CHECK(str_to_concat);
+ CHECK_LT(internal_strlcat(dest, str_to_concat, dest_size), dest_size);
+ next_substr_start_idx = i + 1;
+ }
+ CHECK_LT(internal_strlcat(dest, pattern + next_substr_start_idx, dest_size),
+ dest_size);
+}
+
void ReportFile::SetReportPath(const char *path) {
if (path) {
uptr len = internal_strlen(path);
if (len > sizeof(path_prefix) - 100) {
- Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n", path[0], path[1],
- path[2], path[3], path[4], path[5], path[6], path[7]);
+ const char *message = "ERROR: Path is too long: ";
+ WriteToFile(kStderrFd, message, internal_strlen(message));
+ WriteToFile(kStderrFd, path, 8);
+ WriteToFile(kStderrFd, "\n", internal_strlen("\n"));
Die();
}
}
@@ -115,7 +178,7 @@ void ReportFile::SetReportPath(const char *path) {
} else if (internal_strcmp(path, "stdout") == 0) {
fd = kStdoutFd;
} else {
- internal_snprintf(path_prefix, kMaxPathLength, "%s", path);
+ ParseAndSetPath(path, path_prefix, kMaxPathLength);
RecursiveCreateParentDirs(path_prefix);
}
}
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_fail.cpp b/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_fail.cpp
new file mode 100644
index 0000000000000..c86e1e7e25522
--- /dev/null
+++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_fail.cpp
@@ -0,0 +1,19 @@
+// RUN: %clangxx -O2 %s -o %t
+// RUN: not %env %run %t 2>&1 | FileCheck %s --check-prefix=ERROR1
+// RUN: not %env %run %t A 2>&1 | FileCheck %s --check-prefix=ERROR2
+
+#include <sanitizer/common_interface_defs.h>
+#include <stdio.h>
+
+int main(int argc, char **argv) {
+ char buff[4096];
+ if (argc == 1) {
+ // Try setting again with an invalid/inaccessible directory.
+ sprintf(buff, "%s/report", argv[0]);
+ // ERROR1: Can't create directory: {{.*}}
+ } else {
+ snprintf(buff, sizeof(buff), "%04095d", 42);
+ // ERROR2: Path is too long: 00000000
+ }
+ __sanitizer_set_report_path(buff);
+}
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_test.cpp b/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_test.cpp
index ab1017a2efc07..9d7ed80b44ccb 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_test.cpp
+++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_test.cpp
@@ -1,27 +1,42 @@
// Test __sanitizer_set_report_path and __sanitizer_get_report_path:
// RUN: %clangxx -O2 %s -o %t
-// RUN: not %run %t 2>&1 | FileCheck %s
+// RUN: %env HOME=%t.homedir TMPDIR=%t.tmpdir %run %t 2>%t.err | FileCheck %s
+// RUN: FileCheck %s --input-file=%t.err --check-prefix=ERROR
-#include <assert.h>
#include <sanitizer/common_interface_defs.h>
#include <stdio.h>
#include <string.h>
-volatile int *null = 0;
-
int main(int argc, char **argv) {
- char buff[1000];
+ char buff[4096];
sprintf(buff, "%s.report_path/report", argv[0]);
__sanitizer_set_report_path(buff);
- assert(strncmp(buff, __sanitizer_get_report_path(), strlen(buff)) == 0);
+ // CHECK: {{.*}}.report_path/report.[[PID:[0-9]+]]
+ printf("%s\n", __sanitizer_get_report_path());
- // Try setting again with an invalid/inaccessible directory.
- char buff_bad[1000];
- sprintf(buff_bad, "%s/report", argv[0]);
- fprintf(stderr, "Expected bad report path: %s\n", buff_bad);
- // CHECK: Expected bad report path: [[BADPATH:.*]]/report
- __sanitizer_set_report_path(buff_bad);
- assert(strncmp(buff, __sanitizer_get_report_path(), strlen(buff)) == 0);
-}
+ strcpy(buff, "%H/foo");
+ __sanitizer_set_report_path(buff);
+ // CHECK: [[T:.*]].homedir/foo.[[PID]]
+ printf("%s\n", __sanitizer_get_report_path());
-// CHECK: ERROR: Can't create directory: [[BADPATH]]
+ strcpy(buff, "%t/foo");
+ __sanitizer_set_report_path(buff);
+ // CHECK: [[T]].tmpdir/foo.[[PID]]
+ printf("%s\n", __sanitizer_get_report_path());
+
+ strcpy(buff, "%H/%p/%%foo");
+ __sanitizer_set_report_path(buff);
+ // CHECK: [[T]].homedir/[[PID]]/%foo.[[PID]]
+ printf("%s\n", __sanitizer_get_report_path());
+
+ strcpy(buff, "%%foo%%bar");
+ __sanitizer_set_report_path(buff);
+ // CHECK: %foo%bar.[[PID]]
+ printf("%s\n", __sanitizer_get_report_path());
+
+ strcpy(buff, "%%foo%ba%%r");
+ __sanitizer_set_report_path(buff);
+ // ERROR: Unexpected pattern: %%foo%ba%%r
+ // CHECK: %%foo%ba%%r.[[PID]]
+ printf("%s\n", __sanitizer_get_report_path());
+}
>From caaa557d86b664c04c0f4a7f1e6817311cd780c9 Mon Sep 17 00:00:00 2001
From: Ellis Hoag <ellishoag at meta.com>
Date: Thu, 29 May 2025 10:33:28 -0700
Subject: [PATCH 2/3] resolve some comments
---
compiler-rt/lib/sanitizer_common/sanitizer_file.cpp | 3 ++-
.../TestCases/Posix/sanitizer_set_report_path_fail.cpp | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp
index b55c4ff093c1b..a61be71e603e2 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp
@@ -164,7 +164,8 @@ void ReportFile::SetReportPath(const char *path) {
const char *message = "ERROR: Path is too long: ";
WriteToFile(kStderrFd, message, internal_strlen(message));
WriteToFile(kStderrFd, path, 8);
- WriteToFile(kStderrFd, "\n", internal_strlen("\n"));
+ message = "...\n";
+ WriteToFile(kStderrFd, message, internal_strlen(message));
Die();
}
}
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_fail.cpp b/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_fail.cpp
index c86e1e7e25522..7c4af8b3477a0 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_fail.cpp
+++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_fail.cpp
@@ -12,8 +12,9 @@ int main(int argc, char **argv) {
sprintf(buff, "%s/report", argv[0]);
// ERROR1: Can't create directory: {{.*}}
} else {
+ // Try setting a path that is too large.
snprintf(buff, sizeof(buff), "%04095d", 42);
- // ERROR2: Path is too long: 00000000
+ // ERROR2: Path is too long: 00000000...
}
__sanitizer_set_report_path(buff);
}
>From 8933f2bc23c79d8110e40dca150e937a0cfcdca8 Mon Sep 17 00:00:00 2001
From: Ellis Hoag <ellishoag at meta.com>
Date: Thu, 29 May 2025 11:12:18 -0700
Subject: [PATCH 3/3] comment test better
---
.../TestCases/Posix/sanitizer_set_report_path_fail.cpp | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_fail.cpp b/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_fail.cpp
index 7c4af8b3477a0..782cd0218fd22 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_fail.cpp
+++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_fail.cpp
@@ -1,5 +1,9 @@
// RUN: %clangxx -O2 %s -o %t
+
+// Case 1: Try setting a path that is an invalid/inaccessible directory.
// RUN: not %env %run %t 2>&1 | FileCheck %s --check-prefix=ERROR1
+
+// Case 2: Try setting a path that is too large.
// RUN: not %env %run %t A 2>&1 | FileCheck %s --check-prefix=ERROR2
#include <sanitizer/common_interface_defs.h>
@@ -8,11 +12,11 @@
int main(int argc, char **argv) {
char buff[4096];
if (argc == 1) {
- // Try setting again with an invalid/inaccessible directory.
+ // Case 1
sprintf(buff, "%s/report", argv[0]);
// ERROR1: Can't create directory: {{.*}}
} else {
- // Try setting a path that is too large.
+ // Case 2
snprintf(buff, sizeof(buff), "%04095d", 42);
// ERROR2: Path is too long: 00000000...
}
More information about the llvm-commits
mailing list