[compiler-rt] [sanitizer] Large range support in IsAccessibleMemoryRange (PR #112665)

Florian Mayer via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 17 10:48:49 PDT 2024


================
@@ -288,26 +288,47 @@ bool SignalContext::IsStackOverflow() const {
 
 #endif  // SANITIZER_GO
 
+static void SetNonBlock(int fd) {
+  int res = fcntl(fd, F_GETFL, 0);
+  CHECK(!internal_iserror(res, nullptr));
+
+  res |= O_NONBLOCK;
+  res = fcntl(fd, F_SETFL, res);
+  CHECK(!internal_iserror(res, nullptr));
+}
+
 bool IsAccessibleMemoryRange(uptr beg, uptr size) {
-  uptr page_size = GetPageSizeCached();
-  // Checking too large memory ranges is slow.
-  CHECK_LT(size, page_size * 10);
-  int sock_pair[2];
-  if (pipe(sock_pair))
-    return false;
-  uptr bytes_written =
-      internal_write(sock_pair[1], reinterpret_cast<void *>(beg), size);
-  int write_errno;
-  bool result;
-  if (internal_iserror(bytes_written, &write_errno)) {
-    CHECK_EQ(EFAULT, write_errno);
-    result = false;
-  } else {
-    result = (bytes_written == size);
+  while (size) {
+    // `read` from `fds[0]` into a dummy buffer to free up the pipe buffer
+    // for more `write` is slower than just recreating a pipe.
+    int fds[2];
+    if (pipe(fds))
+      return false;
+
+    auto cleanup = at_scope_exit([&]() {
+      internal_close(fds[0]);
+      internal_close(fds[1]);
+    });
+
+    SetNonBlock(fds[1]);
+
+    int write_errno;
+    uptr w = internal_write(fds[1], reinterpret_cast<char *>(beg), size);
+    if (internal_iserror(w, &write_errno)) {
+      switch (write_errno) {
+        case EINTR:
+        case EAGAIN:
----------------
fmayer wrote:

I don't think EAGAIN can happen (because there should always be some buffer available), but I think if it did, this code would infinitely loop, because nothing is going to free up the buffer. Suggest CHECK-fail for EAGAIN.

https://github.com/llvm/llvm-project/pull/112665


More information about the llvm-commits mailing list