Skip to content

Commit e9a7e06

Browse files
committed
[𝘀𝗽𝗿] initial version
Created using spr 1.3.4
2 parents 3142dff + 23159ed commit e9a7e06

File tree

5 files changed

+134
-19
lines changed

5 files changed

+134
-19
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_common.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,11 @@ class ScopedErrorReportLock {
268268
extern uptr stoptheworld_tracer_pid;
269269
extern uptr stoptheworld_tracer_ppid;
270270

271+
// Returns true if we can read a memory range.
271272
bool IsAccessibleMemoryRange(uptr beg, uptr size);
273+
// Returns true if we can read a memory range starting at `src`, and copies
274+
// content into `dest`.
275+
bool TryMemCpy(void *dest, const void *src, uptr n);
272276

273277
// Error report formatting.
274278
const char *StripPathPrefix(const char *filepath,

compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,11 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size) {
444444
return status == ZX_OK;
445445
}
446446

447+
bool TryMemCpy(void *dest, const void *src, uptr n) {
448+
// TODO: implement.
449+
return false;
450+
}
451+
447452
// FIXME implement on this platform.
448453
void GetMemoryProfile(fill_profile_f cb, uptr *stats) {}
449454

compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp

Lines changed: 68 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -288,26 +288,79 @@ 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);
301+
while (size) {
302+
// `read` from `sock_pair[0]` into a dummy buffer to free up the pipe buffer
303+
// for more `write` is slower than just recreating a pipe.
304+
int sock_pair[2];
305+
if (pipe(sock_pair))
306+
return false;
307+
308+
auto cleanup = at_scope_exit([&]() {
309+
internal_close(sock_pair[0]);
310+
internal_close(sock_pair[1]);
311+
});
312+
313+
SetNonBlock(sock_pair[1]);
314+
315+
int write_errno;
316+
uptr w = internal_write(sock_pair[1], reinterpret_cast<char *>(beg), size);
317+
if (internal_iserror(w, &write_errno)) {
318+
CHECK_EQ(EFAULT, write_errno);
319+
return false;
320+
}
321+
size -= w;
322+
beg += w;
323+
}
324+
325+
return true;
326+
}
327+
328+
bool TryMemCpy(void *dest, const void *src, uptr n) {
295329
int sock_pair[2];
296330
if (pipe(sock_pair))
297331
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);
332+
333+
auto cleanup = at_scope_exit([&]() {
334+
internal_close(sock_pair[0]);
335+
internal_close(sock_pair[1]);
336+
});
337+
338+
SetNonBlock(sock_pair[0]);
339+
SetNonBlock(sock_pair[1]);
340+
341+
char *d = static_cast<char *>(dest);
342+
const char *s = static_cast<const char *>(src);
343+
344+
while (n) {
345+
int e;
346+
uptr w = internal_write(sock_pair[1], s, n);
347+
if (internal_iserror(w, &e)) {
348+
CHECK_EQ(EFAULT, e);
349+
return false;
350+
}
351+
s += w;
352+
n -= w;
353+
354+
while (w) {
355+
uptr r = internal_read(sock_pair[0], d, w);
356+
CHECK(!internal_iserror(r, &e));
357+
358+
d += r;
359+
w -= r;
360+
}
307361
}
308-
internal_close(sock_pair[0]);
309-
internal_close(sock_pair[1]);
310-
return result;
362+
363+
return true;
311364
}
312365

313366
void PlatformPrepareForSandboxing(void *args) {

compiler-rt/lib/sanitizer_common/sanitizer_win.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,11 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size) {
968968
return true;
969969
}
970970

971+
bool TryMemCpy(void *dest, const void *src, uptr n) {
972+
// TODO: implement.
973+
return false;
974+
}
975+
971976
bool SignalContext::IsStackOverflow() const {
972977
return (DWORD)GetType() == EXCEPTION_STACK_OVERFLOW;
973978
}

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

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@
1313
#include "sanitizer_common/sanitizer_platform.h"
1414
#if SANITIZER_POSIX
1515

16-
#include "sanitizer_common/sanitizer_common.h"
17-
#include "gtest/gtest.h"
16+
# include <pthread.h>
17+
# include <sys/mman.h>
1818

19-
#include <pthread.h>
20-
#include <sys/mman.h>
19+
# include <numeric>
20+
21+
# include "gmock/gmock.h"
22+
# include "gtest/gtest.h"
23+
# include "sanitizer_common/sanitizer_common.h"
2124

2225
namespace __sanitizer {
2326

@@ -82,6 +85,51 @@ TEST(SanitizerCommon, IsAccessibleMemoryRange) {
8285
munmap((void *)mem, 3 * page_size);
8386
}
8487

88+
TEST(SanitizerCommon, IsAccessibleMemoryRangeLarge) {
89+
const int size = GetPageSize() * 10000;
90+
91+
uptr mem = (uptr)mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,
92+
-1, 0);
93+
94+
EXPECT_TRUE(IsAccessibleMemoryRange(mem, size));
95+
96+
munmap((void *)mem, size);
97+
}
98+
99+
TEST(SanitizerCommon, TryMemCpy) {
100+
std::vector<char> src(10000000);
101+
std::iota(src.begin(), src.end(), 123);
102+
std::vector<char> dst;
103+
104+
using ::testing::ElementsAreArray;
105+
106+
dst.assign(1, 0);
107+
ASSERT_TRUE(TryMemCpy(dst.data(), src.data(), dst.size()));
108+
EXPECT_THAT(dst, ElementsAreArray(src.data(), dst.size()));
109+
110+
dst.assign(100, 0);
111+
ASSERT_TRUE(TryMemCpy(dst.data(), src.data(), dst.size()));
112+
EXPECT_THAT(dst, ElementsAreArray(src.data(), dst.size()));
113+
114+
dst.assign(534, 0);
115+
ASSERT_TRUE(TryMemCpy(dst.data(), src.data(), dst.size()));
116+
EXPECT_THAT(dst, ElementsAreArray(src.data(), dst.size()));
117+
118+
dst.assign(GetPageSize(), 0);
119+
ASSERT_TRUE(TryMemCpy(dst.data(), src.data(), dst.size()));
120+
EXPECT_THAT(dst, ElementsAreArray(src.data(), dst.size()));
121+
122+
dst.assign(src.size(), 0);
123+
ASSERT_TRUE(TryMemCpy(dst.data(), src.data(), dst.size()));
124+
EXPECT_THAT(dst, ElementsAreArray(src.data(), dst.size()));
125+
126+
dst.assign(src.size() - 1, 0);
127+
ASSERT_TRUE(TryMemCpy(dst.data(), src.data(), dst.size()));
128+
EXPECT_THAT(dst, ElementsAreArray(src.data(), dst.size()));
129+
130+
EXPECT_FALSE(TryMemCpy(dst.data(), nullptr, dst.size()));
131+
}
132+
85133
} // namespace __sanitizer
86134

87135
#endif // SANITIZER_POSIX

0 commit comments

Comments
 (0)