libc fortify: make unistd.h use diagnose_if
Also: - remove a NULL check. The bug that's been working around has been fixed since clang r298431, and our compiler is built from r300080, and - unwrap some function prototypes, per b/36984245. If you're interested, here's what a new error versus an old one looks like: https://drive.google.com/file/d/0B-8OBPboNJ_4MVdlYXdJbUFBYUk/view Bug: 12231437 Test: m checkbuild on bullhead internal master; CtsBionicTestCases show no new failures. Change-Id: Ibafe61198988b4c8bee8391bcdf01bcbc04233de
This commit is contained in:
parent
c2a10f7f1b
commit
16c173935f
2 changed files with 44 additions and 120 deletions
|
@ -60,34 +60,21 @@ ssize_t __readlinkat_chk(int dirfd, const char*, char*, size_t, size_t) __INTROD
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
#define __error_if_overflows_ssizet(what) \
|
#define __error_if_overflows_ssizet(what, fn) \
|
||||||
__enable_if(what > SSIZE_MAX, #what " must be <= SSIZE_MAX") \
|
__clang_error_if((what) > SSIZE_MAX, "in call to '" #fn "', '" #what "' must be <= SSIZE_MAX")
|
||||||
__errorattr(#what " must be <= SSIZE_MAX")
|
|
||||||
|
|
||||||
#define __enable_if_no_overflow_ssizet(what) \
|
#define __error_if_overflows_objectsize(what, objsize, fn) \
|
||||||
__enable_if((what) <= SSIZE_MAX, "enabled if " #what " <= SSIZE_MAX")
|
__clang_error_if((objsize) != __BIONIC_FORTIFY_UNKNOWN_SIZE && (what) > (objsize), \
|
||||||
|
"in call to '" #fn "', '" #what "' bytes overflows the given object")
|
||||||
#define __error_if_overflows_objectsize(what, objsize) \
|
|
||||||
__enable_if((objsize) != __BIONIC_FORTIFY_UNKNOWN_SIZE && \
|
|
||||||
(what) > (objsize), \
|
|
||||||
"'" #what "' bytes overflows the given object") \
|
|
||||||
__errorattr("'" #what "' bytes overflows the given object")
|
|
||||||
|
|
||||||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
|
||||||
char* getcwd(char* buf, size_t size) __overloadable
|
|
||||||
__error_if_overflows_objectsize(size, __bos(buf));
|
|
||||||
|
|
||||||
#if __ANDROID_API__ >= __ANDROID_API_N__
|
#if __ANDROID_API__ >= __ANDROID_API_N__
|
||||||
__BIONIC_FORTIFY_INLINE
|
__BIONIC_FORTIFY_INLINE
|
||||||
char* getcwd(char* const __pass_object_size buf, size_t size) __overloadable {
|
char* getcwd(char* const __pass_object_size buf, size_t size)
|
||||||
|
__overloadable
|
||||||
|
__error_if_overflows_objectsize(size, __bos(buf), getcwd) {
|
||||||
size_t bos = __bos(buf);
|
size_t bos = __bos(buf);
|
||||||
|
|
||||||
/*
|
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||||
* Clang responds bos==0 if buf==NULL
|
|
||||||
* (https://llvm.org/bugs/show_bug.cgi?id=23277). Given that NULL is a valid
|
|
||||||
* value, we need to handle that.
|
|
||||||
*/
|
|
||||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE || buf == NULL) {
|
|
||||||
return __call_bypassing_fortify(getcwd)(buf, size);
|
return __call_bypassing_fortify(getcwd)(buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,18 +83,11 @@ char* getcwd(char* const __pass_object_size buf, size_t size) __overloadable {
|
||||||
#endif /* __ANDROID_API__ >= __ANDROID_API_N__ */
|
#endif /* __ANDROID_API__ >= __ANDROID_API_N__ */
|
||||||
|
|
||||||
#if __ANDROID_API__ >= __ANDROID_API_M__
|
#if __ANDROID_API__ >= __ANDROID_API_M__
|
||||||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
|
||||||
ssize_t pread(int fd, void* buf, size_t count, off_t offset) __overloadable
|
|
||||||
__error_if_overflows_ssizet(count);
|
|
||||||
|
|
||||||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
|
||||||
ssize_t pread(int fd, void* buf, size_t count, off_t offset) __overloadable
|
|
||||||
__enable_if_no_overflow_ssizet(count)
|
|
||||||
__error_if_overflows_objectsize(count, __bos0(buf));
|
|
||||||
|
|
||||||
__BIONIC_FORTIFY_INLINE
|
__BIONIC_FORTIFY_INLINE
|
||||||
ssize_t pread(int fd, void* const __pass_object_size0 buf, size_t count,
|
ssize_t pread(int fd, void* const __pass_object_size0 buf, size_t count, off_t offset)
|
||||||
off_t offset) __overloadable {
|
__overloadable
|
||||||
|
__error_if_overflows_ssizet(count, pread)
|
||||||
|
__error_if_overflows_objectsize(count, __bos0(buf), pread) {
|
||||||
size_t bos = __bos0(buf);
|
size_t bos = __bos0(buf);
|
||||||
|
|
||||||
if (count == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
if (count == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||||
|
@ -117,18 +97,11 @@ ssize_t pread(int fd, void* const __pass_object_size0 buf, size_t count,
|
||||||
return __PREAD_PREFIX(chk)(fd, buf, count, offset, bos);
|
return __PREAD_PREFIX(chk)(fd, buf, count, offset, bos);
|
||||||
}
|
}
|
||||||
|
|
||||||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
|
||||||
ssize_t pread64(int fd, void* buf, size_t count, off64_t offset) __overloadable
|
|
||||||
__error_if_overflows_ssizet(count);
|
|
||||||
|
|
||||||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
|
||||||
ssize_t pread64(int fd, void* buf, size_t count, off64_t offset) __overloadable
|
|
||||||
__enable_if_no_overflow_ssizet(count)
|
|
||||||
__error_if_overflows_objectsize(count, __bos0(buf));
|
|
||||||
|
|
||||||
__BIONIC_FORTIFY_INLINE
|
__BIONIC_FORTIFY_INLINE
|
||||||
ssize_t pread64(int fd, void* const __pass_object_size0 buf, size_t count,
|
ssize_t pread64(int fd, void* const __pass_object_size0 buf, size_t count, off64_t offset)
|
||||||
off64_t offset) __overloadable {
|
__overloadable
|
||||||
|
__error_if_overflows_ssizet(count, pread64)
|
||||||
|
__error_if_overflows_objectsize(count, __bos0(buf), pread64) {
|
||||||
size_t bos = __bos0(buf);
|
size_t bos = __bos0(buf);
|
||||||
|
|
||||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||||
|
@ -140,20 +113,11 @@ ssize_t pread64(int fd, void* const __pass_object_size0 buf, size_t count,
|
||||||
#endif /* __ANDROID_API__ >= __ANDROID_API_M__ */
|
#endif /* __ANDROID_API__ >= __ANDROID_API_M__ */
|
||||||
|
|
||||||
#if __ANDROID_API__ >= __ANDROID_API_N__
|
#if __ANDROID_API__ >= __ANDROID_API_N__
|
||||||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
|
||||||
ssize_t pwrite(int fd, const void* buf, size_t count, off_t offset)
|
|
||||||
__overloadable
|
|
||||||
__error_if_overflows_ssizet(count);
|
|
||||||
|
|
||||||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
|
||||||
ssize_t pwrite(int fd, const void* buf, size_t count, off_t offset)
|
|
||||||
__overloadable
|
|
||||||
__enable_if_no_overflow_ssizet(count)
|
|
||||||
__error_if_overflows_objectsize(count, __bos0(buf));
|
|
||||||
|
|
||||||
__BIONIC_FORTIFY_INLINE
|
__BIONIC_FORTIFY_INLINE
|
||||||
ssize_t pwrite(int fd, const void* const __pass_object_size0 buf, size_t count,
|
ssize_t pwrite(int fd, const void* const __pass_object_size0 buf, size_t count, off_t offset)
|
||||||
off_t offset) __overloadable {
|
__overloadable
|
||||||
|
__error_if_overflows_ssizet(count, pwrite)
|
||||||
|
__error_if_overflows_objectsize(count, __bos0(buf), pwrite) {
|
||||||
size_t bos = __bos0(buf);
|
size_t bos = __bos0(buf);
|
||||||
|
|
||||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||||
|
@ -163,20 +127,11 @@ ssize_t pwrite(int fd, const void* const __pass_object_size0 buf, size_t count,
|
||||||
return __PWRITE_PREFIX(chk)(fd, buf, count, offset, bos);
|
return __PWRITE_PREFIX(chk)(fd, buf, count, offset, bos);
|
||||||
}
|
}
|
||||||
|
|
||||||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
|
||||||
ssize_t pwrite64(int fd, const void* buf, size_t count, off64_t offset)
|
|
||||||
__overloadable
|
|
||||||
__error_if_overflows_ssizet(count);
|
|
||||||
|
|
||||||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
|
||||||
ssize_t pwrite64(int fd, const void* buf, size_t count, off64_t offset)
|
|
||||||
__overloadable
|
|
||||||
__enable_if_no_overflow_ssizet(count)
|
|
||||||
__error_if_overflows_objectsize(count, __bos0(buf));
|
|
||||||
|
|
||||||
__BIONIC_FORTIFY_INLINE
|
__BIONIC_FORTIFY_INLINE
|
||||||
ssize_t pwrite64(int fd, const void* const __pass_object_size0 buf,
|
ssize_t pwrite64(int fd, const void* const __pass_object_size0 buf, size_t count, off64_t offset)
|
||||||
size_t count, off64_t offset) __overloadable {
|
__overloadable
|
||||||
|
__error_if_overflows_ssizet(count, pwrite64)
|
||||||
|
__error_if_overflows_objectsize(count, __bos0(buf), pwrite64) {
|
||||||
size_t bos = __bos0(buf);
|
size_t bos = __bos0(buf);
|
||||||
|
|
||||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||||
|
@ -188,18 +143,11 @@ ssize_t pwrite64(int fd, const void* const __pass_object_size0 buf,
|
||||||
#endif /* __ANDROID_API__ >= __ANDROID_API_N__ */
|
#endif /* __ANDROID_API__ >= __ANDROID_API_N__ */
|
||||||
|
|
||||||
#if __ANDROID_API__ >= __ANDROID_API_L__
|
#if __ANDROID_API__ >= __ANDROID_API_L__
|
||||||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
|
||||||
ssize_t read(int fd, void* buf, size_t count) __overloadable
|
|
||||||
__error_if_overflows_ssizet(count);
|
|
||||||
|
|
||||||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
|
||||||
ssize_t read(int fd, void* buf, size_t count) __overloadable
|
|
||||||
__enable_if_no_overflow_ssizet(count)
|
|
||||||
__error_if_overflows_objectsize(count, __bos0(buf));
|
|
||||||
|
|
||||||
__BIONIC_FORTIFY_INLINE
|
__BIONIC_FORTIFY_INLINE
|
||||||
ssize_t read(int fd, void* const __pass_object_size0 buf, size_t count)
|
ssize_t read(int fd, void* const __pass_object_size0 buf, size_t count)
|
||||||
__overloadable {
|
__overloadable
|
||||||
|
__error_if_overflows_ssizet(count, read)
|
||||||
|
__error_if_overflows_objectsize(count, __bos0(buf), read) {
|
||||||
size_t bos = __bos0(buf);
|
size_t bos = __bos0(buf);
|
||||||
|
|
||||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||||
|
@ -211,18 +159,11 @@ ssize_t read(int fd, void* const __pass_object_size0 buf, size_t count)
|
||||||
#endif /* __ANDROID_API__ >= __ANDROID_API_L__ */
|
#endif /* __ANDROID_API__ >= __ANDROID_API_L__ */
|
||||||
|
|
||||||
#if __ANDROID_API__ >= __ANDROID_API_N__
|
#if __ANDROID_API__ >= __ANDROID_API_N__
|
||||||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
|
||||||
ssize_t write(int fd, const void* buf, size_t count) __overloadable
|
|
||||||
__error_if_overflows_ssizet(count);
|
|
||||||
|
|
||||||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
|
||||||
ssize_t write(int fd, const void* buf, size_t count) __overloadable
|
|
||||||
__enable_if_no_overflow_ssizet(count)
|
|
||||||
__error_if_overflows_objectsize(count, __bos0(buf));
|
|
||||||
|
|
||||||
__BIONIC_FORTIFY_INLINE
|
__BIONIC_FORTIFY_INLINE
|
||||||
ssize_t write(int fd, const void* const __pass_object_size0 buf, size_t count)
|
ssize_t write(int fd, const void* const __pass_object_size0 buf, size_t count)
|
||||||
__overloadable {
|
__overloadable
|
||||||
|
__error_if_overflows_ssizet(count, write)
|
||||||
|
__error_if_overflows_objectsize(count, __bos0(buf), write) {
|
||||||
size_t bos = __bos0(buf);
|
size_t bos = __bos0(buf);
|
||||||
|
|
||||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||||
|
@ -234,18 +175,11 @@ ssize_t write(int fd, const void* const __pass_object_size0 buf, size_t count)
|
||||||
#endif /* __ANDROID_API__ >= __ANDROID_API_N__ */
|
#endif /* __ANDROID_API__ >= __ANDROID_API_N__ */
|
||||||
|
|
||||||
#if __ANDROID_API__ >= __ANDROID_API_M__
|
#if __ANDROID_API__ >= __ANDROID_API_M__
|
||||||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
|
||||||
ssize_t readlink(const char* path, char* buf, size_t size) __overloadable
|
|
||||||
__error_if_overflows_ssizet(size);
|
|
||||||
|
|
||||||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
|
||||||
ssize_t readlink(const char* path, char* buf, size_t size) __overloadable
|
|
||||||
__enable_if_no_overflow_ssizet(size)
|
|
||||||
__error_if_overflows_objectsize(size, __bos(buf));
|
|
||||||
|
|
||||||
__BIONIC_FORTIFY_INLINE
|
__BIONIC_FORTIFY_INLINE
|
||||||
ssize_t readlink(const char* path, char* const __pass_object_size buf,
|
ssize_t readlink(const char* path, char* const __pass_object_size buf, size_t size)
|
||||||
size_t size) __overloadable {
|
__overloadable
|
||||||
|
__error_if_overflows_ssizet(size, readlink)
|
||||||
|
__error_if_overflows_objectsize(size, __bos(buf), readlink) {
|
||||||
size_t bos = __bos(buf);
|
size_t bos = __bos(buf);
|
||||||
|
|
||||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||||
|
@ -255,21 +189,11 @@ ssize_t readlink(const char* path, char* const __pass_object_size buf,
|
||||||
return __readlink_chk(path, buf, size, bos);
|
return __readlink_chk(path, buf, size, bos);
|
||||||
}
|
}
|
||||||
|
|
||||||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
|
||||||
ssize_t readlinkat(int dirfd, const char* path, char* buf, size_t size)
|
|
||||||
__overloadable
|
|
||||||
__error_if_overflows_ssizet(size);
|
|
||||||
|
|
||||||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
|
||||||
ssize_t readlinkat(int dirfd, const char* path, char* buf, size_t size)
|
|
||||||
__overloadable
|
|
||||||
__enable_if_no_overflow_ssizet(size)
|
|
||||||
__error_if_overflows_objectsize(size, __bos(buf));
|
|
||||||
|
|
||||||
__BIONIC_FORTIFY_INLINE
|
__BIONIC_FORTIFY_INLINE
|
||||||
ssize_t readlinkat(int dirfd, const char* path,
|
ssize_t readlinkat(int dirfd, const char* path, char* const __pass_object_size buf, size_t size)
|
||||||
char* const __pass_object_size buf, size_t size)
|
__overloadable
|
||||||
__overloadable {
|
__error_if_overflows_ssizet(size, readlinkat)
|
||||||
|
__error_if_overflows_objectsize(size, __bos(buf), readlinkat) {
|
||||||
size_t bos = __bos(buf);
|
size_t bos = __bos(buf);
|
||||||
|
|
||||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||||
|
|
|
@ -199,7 +199,7 @@ void test_read() {
|
||||||
char buf[4];
|
char buf[4];
|
||||||
// NOLINTNEXTLINE(whitespace/line_length)
|
// NOLINTNEXTLINE(whitespace/line_length)
|
||||||
// GCC: error: call to '__read_dest_size_error' declared with attribute error: read called with size bigger than destination
|
// GCC: error: call to '__read_dest_size_error' declared with attribute error: read called with size bigger than destination
|
||||||
// CLANG: error: call to unavailable function 'read': 'count' bytes overflows the given object
|
// CLANG: error: in call to 'read', 'count' bytes overflows the given object
|
||||||
read(0, buf, 6);
|
read(0, buf, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ void test_getcwd() {
|
||||||
char buf[4];
|
char buf[4];
|
||||||
// NOLINTNEXTLINE(whitespace/line_length)
|
// NOLINTNEXTLINE(whitespace/line_length)
|
||||||
// GCC: error: call to '__getcwd_dest_size_error' declared with attribute error: getcwd called with size bigger than destination
|
// GCC: error: call to '__getcwd_dest_size_error' declared with attribute error: getcwd called with size bigger than destination
|
||||||
// CLANG: error: call to unavailable function 'getcwd': 'size' bytes overflows the given object
|
// CLANG: error: in call to 'getcwd', 'size' bytes overflows the given object
|
||||||
getcwd(buf, 5);
|
getcwd(buf, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ void test_pwrite64_size() {
|
||||||
char buf[4] = {0};
|
char buf[4] = {0};
|
||||||
// NOLINTNEXTLINE(whitespace/line_length)
|
// NOLINTNEXTLINE(whitespace/line_length)
|
||||||
// GCC: error: call to '__pwrite64_dest_size_error' declared with attribute error: pwrite64 called with size bigger than destination
|
// GCC: error: call to '__pwrite64_dest_size_error' declared with attribute error: pwrite64 called with size bigger than destination
|
||||||
// CLANG: error: call to unavailable function 'pwrite64': 'count' bytes overflows the given object
|
// CLANG: error: in call to 'pwrite64', 'count' bytes overflows the given object
|
||||||
pwrite64(STDOUT_FILENO, buf, 5, 0);
|
pwrite64(STDOUT_FILENO, buf, 5, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,7 +292,7 @@ void test_pwrite64_too_big() {
|
||||||
char buf[4] = {0};
|
char buf[4] = {0};
|
||||||
// NOLINTNEXTLINE(whitespace/line_length)
|
// NOLINTNEXTLINE(whitespace/line_length)
|
||||||
// GCC: error: call to '__pwrite64_count_toobig_error' declared with attribute error: pwrite64 called with count > SSIZE_MAX
|
// GCC: error: call to '__pwrite64_count_toobig_error' declared with attribute error: pwrite64 called with count > SSIZE_MAX
|
||||||
// CLANG: error: call to unavailable function 'pwrite64': count must be <= SSIZE_MAX
|
// CLANG: error: in call to 'pwrite64', 'count' must be <= SSIZE_MAX
|
||||||
pwrite64(STDOUT_FILENO, buf, SIZE_MAX, 0);
|
pwrite64(STDOUT_FILENO, buf, SIZE_MAX, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +300,7 @@ void test_write_size() {
|
||||||
char buf[4] = {0};
|
char buf[4] = {0};
|
||||||
// NOLINTNEXTLINE(whitespace/line_length)
|
// NOLINTNEXTLINE(whitespace/line_length)
|
||||||
// GCC: error: call to '__write_dest_size_error' declared with attribute error: write called with size bigger than destination
|
// GCC: error: call to '__write_dest_size_error' declared with attribute error: write called with size bigger than destination
|
||||||
// CLANG: error: call to unavailable function 'write': 'count' bytes overflows the given object
|
// CLANG: error: in call to 'write', 'count' bytes overflows the given object
|
||||||
write(STDOUT_FILENO, buf, 5);
|
write(STDOUT_FILENO, buf, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue