Skip to content

Commit 7086584

Browse files
authored
[sanitizer] Large range support in IsAccessibleMemoryRange (#112665)
The comment stated that it's slow, but likely it's a deadlock, as write can be blocked. Also we can't be sure that `page_size * 10` is appropriate size. Still most likely this is NFC, as the max `size` we use is 32, and should fit in any buffer.
1 parent 32b55f3 commit 7086584

File tree

2 files changed

+40
-18
lines changed

2 files changed

+40
-18
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -288,26 +288,42 @@ bool SignalContext::IsStackOverflow() const {
288288

289289
#endif // SANITIZER_GO
290290

291+
static void SetNonBlock(int fd) {
292+
int res = fcntl(fd, F_GETFL, 0);
293+
CHECK(!internal_iserror(res, nullptr));
294+
295+
res |= O_NONBLOCK;
296+
res = fcntl(fd, F_SETFL, res);
297+
CHECK(!internal_iserror(res, nullptr));
298+
}
299+
291300
bool IsAccessibleMemoryRange(uptr beg, uptr size) {
292-
uptr page_size = GetPageSizeCached();
293-
// Checking too large memory ranges is slow.
294-
CHECK_LT(size, page_size * 10);
295-
int sock_pair[2];
296-
if (pipe(sock_pair))
297-
return false;
298-
uptr bytes_written =
299-
internal_write(sock_pair[1], reinterpret_cast<void *>(beg), size);
300-
int write_errno;
301-
bool result;
302-
if (internal_iserror(bytes_written, &write_errno)) {
303-
CHECK_EQ(EFAULT, write_errno);
304-
result = false;
305-
} else {
306-
result = (bytes_written == size);
301+
while (size) {
302+
// `read` from `fds[0]` into a dummy buffer to free up the pipe buffer for
303+
// more `write` is slower than just recreating a pipe.
304+
int fds[2];
305+
CHECK_EQ(0, pipe(fds));
306+
307+
auto cleanup = at_scope_exit([&]() {
308+
internal_close(fds[0]);
309+
internal_close(fds[1]);
310+
});
311+
312+
SetNonBlock(fds[1]);
313+
314+
int write_errno;
315+
uptr w = internal_write(fds[1], reinterpret_cast<char *>(beg), size);
316+
if (internal_iserror(w, &write_errno)) {
317+
if (write_errno == EINTR)
318+
continue;
319+
CHECK_EQ(EFAULT, write_errno);
320+
return false;
321+
}
322+
size -= w;
323+
beg += w;
307324
}
308-
internal_close(sock_pair[0]);
309-
internal_close(sock_pair[1]);
310-
return result;
325+
326+
return true;
311327
}
312328

313329
void PlatformPrepareForSandboxing(void *args) {

compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ TEST(SanitizerCommon, IsAccessibleMemoryRange) {
8080
EXPECT_FALSE(IsAccessibleMemoryRange(0x0, 2));
8181
}
8282

83+
TEST(SanitizerCommon, IsAccessibleMemoryRangeLarge) {
84+
InternalMmapVector<char> buffer(10000 * GetPageSize());
85+
EXPECT_TRUE(IsAccessibleMemoryRange(reinterpret_cast<uptr>(buffer.data()),
86+
buffer.size()));
87+
}
88+
8389
} // namespace __sanitizer
8490

8591
#endif // SANITIZER_POSIX

0 commit comments

Comments
 (0)