fortify: use a macro in diagnose_if
Our diagnose_if conditions are repetitive. It's potentially convenient to hide that behind a macro. There's an upcoming refactor to our run-time checks; having static checks look super similar is convenient, and makes correctness (hopefully) slightly more obvious. Bug: 131861088 Test: checkbuild on internal master. Change-Id: Ic39a3b6bf020734c1bef6be144f61ef81466aafe
This commit is contained in:
parent
f8813d14aa
commit
5273dc588a
7 changed files with 28 additions and 29 deletions
|
@ -40,8 +40,7 @@ int __ppoll64_chk(struct pollfd*, nfds_t, const struct timespec*, const sigset64
|
|||
__BIONIC_FORTIFY_INLINE
|
||||
int poll(struct pollfd* const fds __pass_object_size, nfds_t fd_count, int timeout)
|
||||
__overloadable
|
||||
__clang_error_if(__bos(fds) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
|
||||
__bos(fds) < sizeof(*fds) * fd_count,
|
||||
__clang_error_if(__bos_unevaluated_lt(__bos(fds), sizeof(*fds) * fd_count),
|
||||
"in call to 'poll', fd_count is larger than the given buffer") {
|
||||
size_t bos_fds = __bos(fds);
|
||||
|
||||
|
@ -54,8 +53,7 @@ int poll(struct pollfd* const fds __pass_object_size, nfds_t fd_count, int timeo
|
|||
__BIONIC_FORTIFY_INLINE
|
||||
int ppoll(struct pollfd* const fds __pass_object_size, nfds_t fd_count, const struct timespec* timeout, const sigset_t* mask)
|
||||
__overloadable
|
||||
__clang_error_if(__bos(fds) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
|
||||
__bos(fds) < sizeof(*fds) * fd_count,
|
||||
__clang_error_if(__bos_unevaluated_lt(__bos(fds), sizeof(*fds) * fd_count),
|
||||
"in call to 'ppoll', fd_count is larger than the given buffer") {
|
||||
size_t bos_fds = __bos(fds);
|
||||
|
||||
|
@ -69,8 +67,7 @@ int ppoll(struct pollfd* const fds __pass_object_size, nfds_t fd_count, const st
|
|||
__BIONIC_FORTIFY_INLINE
|
||||
int ppoll64(struct pollfd* const fds __pass_object_size, nfds_t fd_count, const struct timespec* timeout, const sigset64_t* mask)
|
||||
__overloadable
|
||||
__clang_error_if(__bos(fds) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
|
||||
__bos(fds) < sizeof(*fds) * fd_count,
|
||||
__clang_error_if(__bos_unevaluated_lt(__bos(fds), sizeof(*fds) * fd_count),
|
||||
"in call to 'ppoll64', fd_count is larger than the given buffer") {
|
||||
size_t bos_fds = __bos(fds);
|
||||
|
||||
|
|
|
@ -44,8 +44,7 @@ ssize_t __recvfrom_chk(int, void*, size_t, size_t, int, struct sockaddr*,
|
|||
__BIONIC_FORTIFY_INLINE
|
||||
ssize_t recvfrom(int fd, void* const buf __pass_object_size0, size_t len, int flags, struct sockaddr* src_addr, socklen_t* addr_len)
|
||||
__overloadable
|
||||
__clang_error_if(__bos(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE && __bos(buf) < len,
|
||||
__recvfrom_bad_size) {
|
||||
__clang_error_if(__bos_unevaluated_lt(__bos0(buf), len), __recvfrom_bad_size) {
|
||||
size_t bos = __bos0(buf);
|
||||
|
||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||
|
@ -59,8 +58,7 @@ ssize_t recvfrom(int fd, void* const buf __pass_object_size0, size_t len, int fl
|
|||
__BIONIC_FORTIFY_INLINE
|
||||
ssize_t sendto(int fd, const void* const buf __pass_object_size0, size_t len, int flags, const struct sockaddr* dest_addr, socklen_t addr_len)
|
||||
__overloadable
|
||||
__clang_error_if(__bos0(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE && __bos0(buf) < len,
|
||||
__sendto_bad_size) {
|
||||
__clang_error_if(__bos_unevaluated_lt(__bos0(buf), len), __sendto_bad_size) {
|
||||
size_t bos = __bos0(buf);
|
||||
|
||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||
|
@ -73,7 +71,7 @@ ssize_t sendto(int fd, const void* const buf __pass_object_size0, size_t len, in
|
|||
__BIONIC_FORTIFY_INLINE
|
||||
ssize_t recv(int socket, void* const buf __pass_object_size0, size_t len, int flags)
|
||||
__overloadable
|
||||
__clang_error_if(__bos0(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE && __bos0(buf) < len,
|
||||
__clang_error_if(__bos_unevaluated_lt(__bos0(buf), len),
|
||||
"'recv' called with size bigger than buffer") {
|
||||
return recvfrom(socket, buf, len, flags, NULL, 0);
|
||||
}
|
||||
|
@ -81,7 +79,7 @@ ssize_t recv(int socket, void* const buf __pass_object_size0, size_t len, int fl
|
|||
__BIONIC_FORTIFY_INLINE
|
||||
ssize_t send(int socket, const void* const buf __pass_object_size0, size_t len, int flags)
|
||||
__overloadable
|
||||
__clang_error_if(__bos0(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE && __bos0(buf) < len,
|
||||
__clang_error_if(__bos_unevaluated_lt(__bos0(buf), len),
|
||||
"'send' called with size bigger than buffer") {
|
||||
return sendto(socket, buf, len, flags, NULL, 0);
|
||||
}
|
||||
|
|
|
@ -57,8 +57,7 @@ int vsprintf(char* const __pass_object_size dest, const char* format, va_list ap
|
|||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
||||
int snprintf(char* dest, size_t size, const char* format)
|
||||
__overloadable
|
||||
__enable_if(__bos(dest) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
|
||||
__bos(dest) < __builtin_strlen(format),
|
||||
__enable_if(__bos_unevaluated_lt(__bos(dest), __builtin_strlen(format)),
|
||||
"format string will always overflow destination buffer")
|
||||
__errorattr("format string will always overflow destination buffer");
|
||||
|
||||
|
@ -75,8 +74,7 @@ int snprintf(char* const __pass_object_size dest, size_t size, const char* forma
|
|||
__BIONIC_ERROR_FUNCTION_VISIBILITY
|
||||
int sprintf(char* dest, const char* format)
|
||||
__overloadable
|
||||
__enable_if(__bos(dest) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
|
||||
__bos(dest) < __builtin_strlen(format),
|
||||
__enable_if(__bos_unevaluated_lt(__bos(dest), __builtin_strlen(format)),
|
||||
"format string will always overflow destination buffer")
|
||||
__errorattr("format string will always overflow destination buffer");
|
||||
|
||||
|
@ -96,7 +94,7 @@ size_t fread(void* const __pass_object_size0 buf, size_t size, size_t count, FIL
|
|||
__overloadable
|
||||
__clang_error_if(__unsafe_check_mul_overflow(size, count),
|
||||
"in call to 'fread', size * count overflows")
|
||||
__clang_error_if(__bos(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE && size * count > __bos(buf),
|
||||
__clang_error_if(__bos_unevaluated_lt(__bos0(buf), size * count),
|
||||
"in call to 'fread', size * count is too large for the given buffer") {
|
||||
size_t bos = __bos0(buf);
|
||||
|
||||
|
@ -111,7 +109,7 @@ size_t fwrite(const void* const __pass_object_size0 buf, size_t size, size_t cou
|
|||
__overloadable
|
||||
__clang_error_if(__unsafe_check_mul_overflow(size, count),
|
||||
"in call to 'fwrite', size * count overflows")
|
||||
__clang_error_if(__bos(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE && size * count > __bos(buf),
|
||||
__clang_error_if(__bos_unevaluated_lt(__bos0(buf), size * count),
|
||||
"in call to 'fwrite', size * count is too large for the given buffer") {
|
||||
size_t bos = __bos0(buf);
|
||||
|
||||
|
@ -128,7 +126,7 @@ __BIONIC_FORTIFY_INLINE
|
|||
char* fgets(char* const __pass_object_size dest, int size, FILE* stream)
|
||||
__overloadable
|
||||
__clang_error_if(size < 0, "in call to 'fgets', size should not be negative")
|
||||
__clang_error_if(size > __bos(dest),
|
||||
__clang_error_if(__bos_unevaluated_lt(__bos(dest), size),
|
||||
"in call to 'fgets', size is larger than the destination buffer") {
|
||||
size_t bos = __bos(dest);
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@
|
|||
#define __PATH_MAX 4096
|
||||
|
||||
char* realpath(const char* path, char* resolved)
|
||||
__clang_error_if(__bos(resolved) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
|
||||
__bos(resolved) < __PATH_MAX, __realpath_buf_too_small_str)
|
||||
__clang_error_if(__bos_unevaluated_lt(__bos(resolved), __PATH_MAX),
|
||||
__realpath_buf_too_small_str)
|
||||
__clang_error_if(!path, "'realpath': NULL path is never correct; flipped arguments?");
|
||||
/* No need for a definition; the only issues we can catch are at compile-time. */
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ extern void* __memrchr_real(const void*, int, size_t) __RENAME(memrchr);
|
|||
__BIONIC_FORTIFY_INLINE
|
||||
void* memcpy(void* const dst __pass_object_size0, const void* src, size_t copy_amount)
|
||||
__overloadable
|
||||
__clang_error_if(__bos0(dst) != __BIONIC_FORTIFY_UNKNOWN_SIZE && __bos0(dst) < copy_amount,
|
||||
__clang_error_if(__bos_unevaluated_lt(__bos0(dst), copy_amount),
|
||||
"'memcpy' called with size bigger than buffer") {
|
||||
return __builtin___memcpy_chk(dst, src, copy_amount, __bos0(dst));
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ void* memcpy(void* const dst __pass_object_size0, const void* src, size_t copy_a
|
|||
__BIONIC_FORTIFY_INLINE
|
||||
void* memmove(void* const dst __pass_object_size0, const void* src, size_t len)
|
||||
__overloadable
|
||||
__clang_error_if(__bos0(dst) != __BIONIC_FORTIFY_UNKNOWN_SIZE && __bos0(dst) < len,
|
||||
__clang_error_if(__bos_unevaluated_lt(__bos0(dst), len),
|
||||
"'memmove' called with size bigger than buffer") {
|
||||
return __builtin___memmove_chk(dst, src, len, __bos0(dst));
|
||||
}
|
||||
|
@ -62,8 +62,7 @@ void* memmove(void* const dst __pass_object_size0, const void* src, size_t len)
|
|||
__BIONIC_FORTIFY_INLINE
|
||||
char* stpcpy(char* const dst __pass_object_size, const char* src)
|
||||
__overloadable
|
||||
__clang_error_if(__bos(dst) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
|
||||
__bos(dst) <= __builtin_strlen(src),
|
||||
__clang_error_if(__bos_unevaluated_leq(__bos(dst), __builtin_strlen(src)),
|
||||
"'stpcpy' called with string bigger than buffer") {
|
||||
return __builtin___stpcpy_chk(dst, src, __bos(dst));
|
||||
}
|
||||
|
@ -73,8 +72,7 @@ char* stpcpy(char* const dst __pass_object_size, const char* src)
|
|||
__BIONIC_FORTIFY_INLINE
|
||||
char* strcpy(char* const dst __pass_object_size, const char* src)
|
||||
__overloadable
|
||||
__clang_error_if(__bos(dst) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
|
||||
__bos(dst) <= __builtin_strlen(src),
|
||||
__clang_error_if(__bos_unevaluated_leq(__bos(dst), __builtin_strlen(src)),
|
||||
"'strcpy' called with string bigger than buffer") {
|
||||
return __builtin___strcpy_chk(dst, src, __bos(dst));
|
||||
}
|
||||
|
@ -92,7 +90,7 @@ char* strncat(char* const dst __pass_object_size, const char* src, size_t n) __o
|
|||
__BIONIC_FORTIFY_INLINE
|
||||
void* memset(void* const s __pass_object_size0, int c, size_t n)
|
||||
__overloadable
|
||||
__clang_error_if(__bos0(s) != __BIONIC_FORTIFY_UNKNOWN_SIZE && __bos0(s) < n,
|
||||
__clang_error_if(__bos_unevaluated_lt(__bos0(s), n),
|
||||
"'memset' called with size bigger than buffer")
|
||||
/* If you're a user who wants this warning to go away: use `(&memset)(foo, bar, baz)`. */
|
||||
__clang_warning_if(c && !n, "'memset' will set 0 bytes; maybe the arguments got flipped?") {
|
||||
|
|
|
@ -63,7 +63,7 @@ ssize_t __readlinkat_chk(int dirfd, const char*, char*, size_t, size_t) __INTROD
|
|||
__clang_error_if((what) > SSIZE_MAX, "in call to '" #fn "', '" #what "' must be <= SSIZE_MAX")
|
||||
|
||||
#define __error_if_overflows_objectsize(what, objsize, fn) \
|
||||
__clang_error_if((objsize) != __BIONIC_FORTIFY_UNKNOWN_SIZE && (what) > (objsize), \
|
||||
__clang_error_if(__bos_unevaluated_lt((objsize), (what)), \
|
||||
"in call to '" #fn "', '" #what "' bytes overflows the given object")
|
||||
|
||||
#if __ANDROID_API__ >= __ANDROID_API_N__
|
||||
|
|
|
@ -289,6 +289,14 @@
|
|||
#define __pass_object_size __pass_object_size_n(__bos_level)
|
||||
#define __pass_object_size0 __pass_object_size_n(0)
|
||||
|
||||
/* Intended for use in unevaluated contexts, e.g. diagnose_if conditions. */
|
||||
#define __bos_unevaluated_lt(bos_val, val) \
|
||||
((bos_val) != __BIONIC_FORTIFY_UNKNOWN_SIZE && (bos_val) < (val))
|
||||
|
||||
#define __bos_unevaluated_leq(bos_val, val) \
|
||||
((bos_val) != __BIONIC_FORTIFY_UNKNOWN_SIZE && (bos_val) <= (val))
|
||||
|
||||
|
||||
#if defined(__BIONIC_FORTIFY) || defined(__BIONIC_DECLARE_FORTIFY_HELPERS)
|
||||
# define __BIONIC_INCLUDE_FORTIFY_HEADERS 1
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue