summaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2013-07-11 18:51:40 +0000
committerChandler Carruth <chandlerc@gmail.com>2013-07-11 18:51:40 +0000
commit5a482cd54a75bf821fb8c61f2fe4e84ae9efb714 (patch)
tree81376dcdf5cd1d77cf7e0d25d8883265228b7d98 /lib/sanitizer_common/sanitizer_platform_limits_posix.cc
parentec29e26885a224627c2523422760e415c02cf225 (diff)
downloadcompiler-rt-5a482cd54a75bf821fb8c61f2fe4e84ae9efb714.tar.gz
compiler-rt-5a482cd54a75bf821fb8c61f2fe4e84ae9efb714.tar.bz2
compiler-rt-5a482cd54a75bf821fb8c61f2fe4e84ae9efb714.tar.xz
Fix a veritable conucopia of bugs in the readdir_r interceptors.
First, the reason I came here: I forgot to look at readdir64_r which had the exact same bug as readdir_r. However, upon applying the same quick-fix and testing it I discovered that it still didn't work at all. As a consequence, I spent some time studying the code and thinking about it and fixed several other problems. Second, the code was checking for a null entry and result pointer, but there is no indication that null pointers are viable here. Certainly, the spec makes it extremely clear that there is no non-error case where the implementation of readdir_r fails to dereference the 'result' pointer and store NULL to it. Thus, our checking for a non-null 'result' pointer before reflecting that write in the instrumentation was trivially dead. Remove it. Third, the interceptor was marking the write to the actual dirent struct by looking at the entry pointer, but nothing in the spec requires that the dirent struct written is actually written into the entry structure provided. A threadlocal buffer would be just as conforming, and the spec goes out of its way to say the pointer to the *actual* result dirent struct is stored into *result, so *that* is where the interceptor should reflect a write occuring. This also obviates the need to even consider whether the 'entry' parameter is null. Fourth, I got to the bottom of why nothing at all worked in readdir64_r -- the interceptor structure for dirent64 was completely wrong in that it was the same as dirent. I fixed this struct to be correct (64-bit inode and 64-bit offset! just a 64-bit offset isn't enough!) and added several missing tests for the size and layout of this struct. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@186109 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/sanitizer_common/sanitizer_platform_limits_posix.cc')
-rw-r--r--lib/sanitizer_common/sanitizer_platform_limits_posix.cc8
1 files changed, 8 insertions, 0 deletions
diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
index 93d0d7f8..16f12ed8 100644
--- a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
+++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
@@ -795,12 +795,20 @@ CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len);
CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);
CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type);
+COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent));
CHECK_SIZE_AND_OFFSET(dirent, d_ino);
#ifndef SANITIZER_MAC
CHECK_SIZE_AND_OFFSET(dirent, d_off);
#endif
CHECK_SIZE_AND_OFFSET(dirent, d_reclen);
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+COMPILER_CHECK(sizeof(__sanitizer_dirent64) <= sizeof(dirent64));
+CHECK_SIZE_AND_OFFSET(dirent64, d_ino);
+CHECK_SIZE_AND_OFFSET(dirent64, d_off);
+CHECK_SIZE_AND_OFFSET(dirent64, d_reclen);
+#endif
+
CHECK_TYPE_SIZE(ifconf);
CHECK_SIZE_AND_OFFSET(ifconf, ifc_len);
CHECK_SIZE_AND_OFFSET(ifconf, ifc_ifcu);