blob: 259ea7addd6700de45f7fd9152d31bb1f3da5974 [file] [log] [blame]
From: George Burgess <gbiv@chromium.org>
This patch adds a clang-specific FORTIFY to our glibc implementation. No
attempt has been made to upstream it yet, because we need two more
attributes implemented in clang in order to have a "complete" FORTIFY
implementation. However, this patch gets us ~99% of the way there. Once
we update clang + this patch, we'll try to upstream this.
For documentation on FORTIFY and some background on how a
clang-specific FORTIFY works, please see this doc:
https://docs.google.com/document/d/1DFfZDICTbL7RqS74wJVIJ-YnjQOj1SaoqfhbgddFYSM/edit?usp=sharing
https://crbug.com/638456
--- include/stdio.h
+++ include/stdio.h
@@ -164,12 +164,36 @@ libc_hidden_proto (__obstack_vprintf_chk)
/* The <stdio.h> header does not include the declaration for gets
anymore when compiling with _GNU_SOURCE. Provide a copy here. */
-extern char *gets (char *__s);
+__fortify_overloadable
+extern char *gets (char *__s) __CLANG_NO_MANGLE (gets);
+
# if __USE_FORTIFY_LEVEL > 0
extern char *__gets_chk (char *__str, size_t) __wur;
+
+# define __warn_gets_use_something_else \
+ "please use fgets or getline instead, gets can't specify buffer size"
+# ifdef __use_clang_fortify
+__fortify_potential_overload __wur char *
+gets (char *const __clang_pass_object_size __str)
+ __clang_enable_if (__bos (__str) != (size_t) -1,
+ "selected if this call looks safe")
+{
+ return __gets_chk (__str, __bos (__str));
+}
+
+extern char *__REDIRECT (__gets_alias, (char *__str), gets) __wur;
+
+__fortify_potential_overload __wur
+__clang_warning (__warn_gets_use_something_else) char *
+gets (char *const __clang_pass_object_size __str)
+{
+ if (__bos (__str) != (size_t) -1)
+ return __gets_chk (__str, __bos (__str));
+ return __gets_alias (__str);
+}
+# else
extern char *__REDIRECT (__gets_warn, (char *__str), gets)
- __wur __warnattr ("please use fgets or getline instead, gets can't "
- "specify buffer size");
+ __wur __warnattr (__warn_gets_use_something_else);
__fortify_function __wur char *
gets (char *__str)
@@ -178,6 +202,8 @@ gets (char *__str)
return __gets_chk (__str, __bos (__str));
return __gets_warn (__str);
}
+# endif
+# undef __warn_gets_use_something_else
# endif
__END_DECLS
--- io/bits/fcntl2.h
+++ io/bits/fcntl2.h
@@ -32,10 +32,32 @@ extern int __REDIRECT (__open_2, (const char *__path, int __oflag),
extern int __REDIRECT (__open_alias, (const char *__path, int __oflag, ...),
open64) __nonnull ((1));
#endif
-__errordecl (__open_too_many_args,
- "open can be called either with 2 or 3 arguments, not more");
-__errordecl (__open_missing_mode,
- "open with O_CREAT in second argument needs 3 arguments");
+
+#define __warn_open_too_many_args \
+ "open can be called either with 2 or 3 arguments, not more"
+#define __warn_open_missing_mode \
+ "open with O_CREAT in second argument needs 3 arguments"
+#ifdef __use_clang_fortify
+__fortify_error_function __clang_error (__warn_open_missing_mode) int
+open (const char *__path, int __oflag)
+ __clang_prefer_this_overload
+ __clang_enable_if (__oflag & O_CREAT,
+ "selected if open is given O_CREAT, but no mode");
+
+__fortify_overload __clang_prefer_this_overload int
+open (const char *__path, int __oflag)
+{
+ return __open_2 (__path, __oflag);
+}
+
+__fortify_overload int
+open (const char *__path, int __oflag, mode_t __mode)
+{
+ return __open_alias (__path, __oflag, __mode);
+}
+#else
+__errordecl (__open_too_many_args, __warn_open_too_many_args);
+__errordecl (__open_missing_mode, __warn_open_missing_mode);
__fortify_function int
open (const char *__path, int __oflag, ...)
@@ -58,16 +80,44 @@ open (const char *__path, int __oflag, ...)
return __open_alias (__path, __oflag, __va_arg_pack ());
}
+#endif
+#undef __warn_open_too_many_args
+#undef __warn_open_missing_mode
#ifdef __USE_LARGEFILE64
extern int __open64_2 (const char *__path, int __oflag) __nonnull ((1));
extern int __REDIRECT (__open64_alias, (const char *__path, int __oflag,
...), open64) __nonnull ((1));
-__errordecl (__open64_too_many_args,
- "open64 can be called either with 2 or 3 arguments, not more");
-__errordecl (__open64_missing_mode,
- "open64 with O_CREAT in second argument needs 3 arguments");
+
+# define __warn_open64_too_many_args "open64 can be called either with 2 or " \
+ "3 arguments, not more"
+# define __warn_open64_missing_mode "open64 with O_CREAT in second argument " \
+ "needs 3 arguments"
+# ifdef __use_clang_fortify
+__fortify_error_function __clang_error (__warn_open64_too_many_args) int
+open64 (const char *__path, int __oflag, int __mode, ...);
+
+__fortify_error_function __clang_error (__warn_open64_missing_mode) int
+open64 (const char *__path, int __oflag)
+ __clang_prefer_this_overload
+ __clang_enable_if (__oflag & O_CREAT,
+ "selected if open64 is given O_CREAT, but no mode");
+
+__fortify_overload __clang_prefer_this_overload int
+open64 (const char *__path, int __oflag)
+{
+ return __open64_2 (__path, __oflag);
+}
+
+__fortify_overload __clang_prefer_this_overload int
+open64 (const char *__path, int __oflag, int __mode)
+{
+ return __open64_alias (__path, __oflag, __mode);
+}
+# else
+__errordecl (__open64_too_many_args, __warn_open64_too_many_args);
+__errordecl (__open64_missing_mode, __warn_open64_missing_mode);
__fortify_function int
open64 (const char *__path, int __oflag, ...)
@@ -90,6 +140,9 @@ open64 (const char *__path, int __oflag, ...)
return __open64_alias (__path, __oflag, __va_arg_pack ());
}
+# endif
+# undef __warn_open64_too_many_args
+# undef __warn_open64_missing_mode
#endif
@@ -108,10 +161,35 @@ extern int __REDIRECT (__openat_alias, (int __fd, const char *__path,
int __oflag, ...), openat64)
__nonnull ((2));
# endif
-__errordecl (__openat_too_many_args,
- "openat can be called either with 3 or 4 arguments, not more");
-__errordecl (__openat_missing_mode,
- "openat with O_CREAT in third argument needs 4 arguments");
+
+# define __warn_openat_too_many_args "openat can be called either with 3 or " \
+ "4 arguments, not more"
+# define __warn_openat_missing_mode "openat with O_CREAT in third argument " \
+ "needs 4 arguments"
+# ifdef __use_clang_fortify
+__fortify_error_function __clang_error (__warn_openat_too_many_args) int
+openat (int __fd, const char *__path, int __oflag, int __mode, ...);
+
+__fortify_error_function __clang_error (__warn_openat_missing_mode) int
+openat (int __fd, const char *__path, int __oflag)
+ __clang_prefer_this_overload
+ __clang_enable_if (__oflag & O_CREAT,
+ "selected if openat is given O_CREAT but no mode");
+
+__fortify_overload __clang_prefer_this_overload int
+openat (int __fd, const char *__path, int __oflag)
+{
+ return __openat_2 (__fd, __path, __oflag);
+}
+
+__fortify_overload __clang_prefer_this_overload int
+openat (int __fd, const char *__path, int __oflag, int __mode)
+{
+ return __openat_alias (__fd, __path, __oflag, __mode);
+}
+# else
+__errordecl (__openat_too_many_args, __warn_openat_too_many_args);
+__errordecl (__openat_missing_mode, __warn_openat_missing_mode);
__fortify_function int
openat (int __fd, const char *__path, int __oflag, ...)
@@ -134,6 +212,9 @@ openat (int __fd, const char *__path, int __oflag, ...)
return __openat_alias (__fd, __path, __oflag, __va_arg_pack ());
}
+# endif
+# undef __warn_openat_too_many_args
+# undef __warn_openat_missing_mode
# ifdef __USE_LARGEFILE64
@@ -142,11 +223,36 @@ extern int __openat64_2 (int __fd, const char *__path, int __oflag)
extern int __REDIRECT (__openat64_alias, (int __fd, const char *__path,
int __oflag, ...), openat64)
__nonnull ((2));
-__errordecl (__openat64_too_many_args,
- "openat64 can be called either with 3 or 4 arguments, not more");
-__errordecl (__openat64_missing_mode,
- "openat64 with O_CREAT in third argument needs 4 arguments");
+# define __warn_openat64_too_many_args "openat64 can be called either with " \
+ "3 or 4 arguments, not more"
+# define __warn_openat64_missing_mode "openat64 with O_CREAT in third " \
+ "argument needs 4 arguments"
+
+# ifdef __use_clang_fortify
+__fortify_error_function __clang_error (__warn_openat64_too_many_args) int
+openat64 (int __fd, const char *__path, int __oflag, int __mode, ...);
+
+__fortify_error_function __clang_error (__warn_openat64_missing_mode) int
+openat64 (int __fd, const char *__path, int __oflag)
+ __clang_prefer_this_overload
+ __clang_enable_if (__oflag & O_CREAT,
+ "selected if openat64 is given O_CREAT, but no mode");
+
+__fortify_overload __clang_prefer_this_overload int
+openat64 (int __fd, const char *__path, int __oflag)
+{
+ return __openat64_2 (__fd, __path, __oflag);
+}
+
+__fortify_overload __clang_prefer_this_overload int
+openat64 (int __fd, const char *__path, int __oflag, int __mode)
+{
+ return __openat64_alias (__fd, __path, __oflag, __mode);
+}
+# else
+__errordecl (__openat64_too_many_args, __warn_openat64_too_many_args);
+__errordecl (__openat64_missing_mode, __warn_openat64_missing_mode);
__fortify_function int
openat64 (int __fd, const char *__path, int __oflag, ...)
{
@@ -168,5 +274,8 @@ openat64 (int __fd, const char *__path, int __oflag, ...)
return __openat64_alias (__fd, __path, __oflag, __va_arg_pack ());
}
+# endif
+# undef __warn_openat64_too_many_args
+# undef __warn_openat64_missing_mode
# endif
#endif
--- io/bits/poll2.h
+++ io/bits/poll2.h
@@ -27,10 +27,32 @@ extern int __REDIRECT (__poll_alias, (struct pollfd *__fds, nfds_t __nfds,
int __timeout), poll);
extern int __poll_chk (struct pollfd *__fds, nfds_t __nfds, int __timeout,
__SIZE_TYPE__ __fdslen);
+
+#define __warn_poll_nfds "poll called with fds buffer too small file nfds entries"
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_poll_nfds) int
+poll (struct pollfd *const __clang_pass_object_size __fds, nfds_t __nfds,
+ int __timeout)
+ __clang_enable_if (__bos (__fds) != (__SIZE_TYPE__) -1
+ && __bos (__fds) / sizeof (*__fds) < __nfds,
+ "selected if this call looks dangerous")
+{
+ return __poll_chk (__fds, __nfds, __timeout, __bos (__fds));
+}
+
+__fortify_overload int
+poll (struct pollfd *const __clang_pass_object_size __fds, nfds_t __nfds,
+ int __timeout)
+{
+ if (__bos (__fds) != (__SIZE_TYPE__) -1)
+ return __poll_chk (__fds, __nfds, __timeout, __bos (__fds));
+ return __poll_alias (__fds, __nfds, __timeout);
+}
+#else
extern int __REDIRECT (__poll_chk_warn, (struct pollfd *__fds, nfds_t __nfds,
int __timeout, __SIZE_TYPE__ __fdslen),
__poll_chk)
- __warnattr ("poll called with fds buffer too small file nfds entries");
+ __warnattr (__warn_poll_nfds);
__fortify_function int
poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
@@ -45,6 +67,8 @@ poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
return __poll_alias (__fds, __nfds, __timeout);
}
+#endif
+#undef __warn_poll_nfds
#ifdef __USE_GNU
@@ -54,12 +78,35 @@ extern int __REDIRECT (__ppoll_alias, (struct pollfd *__fds, nfds_t __nfds,
extern int __ppoll_chk (struct pollfd *__fds, nfds_t __nfds,
const struct timespec *__timeout,
const __sigset_t *__ss, __SIZE_TYPE__ __fdslen);
+
+# define __warn_ppoll_nfds \
+ "ppoll called with fds buffer too small file nfds entries"
+# ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_ppoll_nfds) int
+ppoll (struct pollfd *const __clang_pass_object_size __fds, nfds_t __nfds,
+ const struct timespec *__timeout, const __sigset_t *__ss)
+ __clang_enable_if (__bos (__fds) != (__SIZE_TYPE__) -1
+ && __bos (__fds) / sizeof (*__fds) < __nfds,
+ "selected if this call looks dangerous")
+{
+ return __ppoll_chk (__fds, __nfds, __timeout, __ss, __bos (__fds));
+}
+
+__fortify_overload int
+ppoll (struct pollfd *const __clang_pass_object_size __fds, nfds_t __nfds,
+ const struct timespec *__timeout, const __sigset_t *__ss)
+{
+ if (__bos (__fds) != (__SIZE_TYPE__) -1)
+ return __ppoll_chk (__fds, __nfds, __timeout, __ss, __bos (__fds));
+ return __ppoll_alias (__fds, __nfds, __timeout, __ss);
+}
+# else
extern int __REDIRECT (__ppoll_chk_warn, (struct pollfd *__fds, nfds_t __nfds,
const struct timespec *__timeout,
const __sigset_t *__ss,
__SIZE_TYPE__ __fdslen),
__ppoll_chk)
- __warnattr ("ppoll called with fds buffer too small file nfds entries");
+ __warnattr (__warn_ppoll_nfds);
__fortify_function int
ppoll (struct pollfd *__fds, nfds_t __nfds, const struct timespec *__timeout,
@@ -76,6 +123,9 @@ ppoll (struct pollfd *__fds, nfds_t __nfds, const struct timespec *__timeout,
return __ppoll_alias (__fds, __nfds, __timeout, __ss);
}
+# endif
+# undef __warn_ppoll_nfds
+
#endif
__END_DECLS
--- io/fcntl.h
+++ io/fcntl.h
@@ -166,9 +166,12 @@ extern int fcntl (int __fd, int __cmd, ...);
This function is a cancellation point and therefore not marked with
__THROW. */
#ifndef __USE_FILE_OFFSET64
-extern int open (const char *__file, int __oflag, ...) __nonnull ((1));
+__fortify_overloadable
+extern int open (const char *__file, int __oflag, ...)
+ __nonnull ((1)) __CLANG_NO_MANGLE (open);
#else
# ifdef __REDIRECT
+__fortify_overloadable
extern int __REDIRECT (open, (const char *__file, int __oflag, ...), open64)
__nonnull ((1));
# else
@@ -176,7 +179,9 @@ extern int __REDIRECT (open, (const char *__file, int __oflag, ...), open64)
# endif
#endif
#ifdef __USE_LARGEFILE64
-extern int open64 (const char *__file, int __oflag, ...) __nonnull ((1));
+__fortify_overloadable
+extern int open64 (const char *__file, int __oflag, ...)
+ __nonnull ((1)) __CLANG_NO_MANGLE (open64);
#endif
#ifdef __USE_ATFILE
@@ -190,10 +195,12 @@ extern int open64 (const char *__file, int __oflag, ...) __nonnull ((1));
This function is a cancellation point and therefore not marked with
__THROW. */
# ifndef __USE_FILE_OFFSET64
+__fortify_overloadable
extern int openat (int __fd, const char *__file, int __oflag, ...)
- __nonnull ((2));
+ __nonnull ((2)) __CLANG_NO_MANGLE (openat);
# else
# ifdef __REDIRECT
+__fortify_overloadable
extern int __REDIRECT (openat, (int __fd, const char *__file, int __oflag,
...), openat64) __nonnull ((2));
# else
@@ -201,8 +208,9 @@ extern int __REDIRECT (openat, (int __fd, const char *__file, int __oflag,
# endif
# endif
# ifdef __USE_LARGEFILE64
+__fortify_overloadable
extern int openat64 (int __fd, const char *__file, int __oflag, ...)
- __nonnull ((2));
+ __nonnull ((2)) __CLANG_NO_MANGLE (openat64);
# endif
#endif
@@ -298,7 +306,7 @@ extern int posix_fallocate64 (int __fd, off64_t __offset, off64_t __len);
/* Define some inlines helping to catch common problems. */
#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function \
- && defined __va_arg_pack_len
+ && (defined __va_arg_pack_len || defined __use_clang_fortify)
# include <bits/fcntl2.h>
#endif
--- io/sys/poll.h
+++ io/sys/poll.h
@@ -54,7 +54,9 @@ __BEGIN_DECLS
This function is a cancellation point and therefore not marked with
__THROW. */
-extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout);
+__fortify_overloadable
+extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
+ __CLANG_NO_MANGLE (poll);
#ifdef __USE_GNU
/* Like poll, but before waiting the threads signal mask is replaced
@@ -63,9 +65,11 @@ extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout);
This function is a cancellation point and therefore not marked with
__THROW. */
+__fortify_overloadable
extern int ppoll (struct pollfd *__fds, nfds_t __nfds,
const struct timespec *__timeout,
- const __sigset_t *__ss);
+ const __sigset_t *__ss)
+ __CLANG_NO_MANGLE (ppoll);
#endif
__END_DECLS
--- libio/bits/stdio2.h
+++ libio/bits/stdio2.h
@@ -26,7 +26,21 @@ extern int __vsprintf_chk (char *__restrict __s, int __flag, size_t __slen,
const char *__restrict __format,
_G_va_list __ap) __THROW;
-#ifdef __va_arg_pack
+#ifdef __use_clang_fortify
+/* clang doesn't have __va_arg_pack, so we need to defer to the va_arg versions
+ of these functions. */
+__fortify_overload int
+__NTH (sprintf (char *__restrict const __clang_pass_object_size __s,
+ const char *__restrict __fmt, ...))
+{
+ _G_va_list __ap;
+ va_start (__ap, __fmt);
+ int __result = __builtin___vsprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
+ __bos (__s), __fmt, __ap);
+ va_end (__ap);
+ return __result;
+}
+#elif defined(__va_arg_pack)
__fortify_function int
__NTH (sprintf (char *__restrict __s, const char *__restrict __fmt, ...))
{
@@ -39,9 +53,9 @@ __NTH (sprintf (char *__restrict __s, const char *__restrict __fmt, ...))
__VA_ARGS__)
#endif
-__fortify_function int
-__NTH (vsprintf (char *__restrict __s, const char *__restrict __fmt,
- _G_va_list __ap))
+__fortify_potential_overload int
+__NTH (vsprintf (char *__restrict const __clang_pass_object_size __s,
+ const char *__restrict __fmt, _G_va_list __ap))
{
return __builtin___vsprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
__bos (__s), __fmt, __ap);
@@ -56,7 +70,37 @@ extern int __vsnprintf_chk (char *__restrict __s, size_t __n, int __flag,
size_t __slen, const char *__restrict __format,
_G_va_list __ap) __THROW;
-# ifdef __va_arg_pack
+# ifdef __use_clang_fortify
+# define __warn_snprintf_buf_size \
+ "call to snprintf may overflow the destination buffer"
+__fortify_overload __clang_warning (__warn_snprintf_buf_size) int
+__NTH (snprintf (char *__restrict const __clang_pass_object_size __s,
+ size_t __n, const char *__restrict __fmt, ...))
+ __clang_enable_if (__bos (__s) != (size_t) -1 && __bos (__s) < __n,
+ "selected if this call looks dangerous")
+{
+ _G_va_list __ap;
+ va_start (__ap, __fmt);
+ int __result = __builtin___vsnprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1,
+ __bos (__s), __fmt, __ap);
+ va_end (__ap);
+ return __result;
+}
+
+# undef __warn_snprintf_buf_size
+
+__fortify_overload int
+__NTH (snprintf (char *__restrict const __clang_pass_object_size __s,
+ size_t __n, const char *__restrict __fmt, ...))
+{
+ _G_va_list __ap;
+ va_start (__ap, __fmt);
+ int __result = __builtin___vsnprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1,
+ __bos (__s), __fmt, __ap);
+ va_end (__ap);
+ return __result;
+}
+# elif defined(__va_arg_pack)
__fortify_function int
__NTH (snprintf (char *__restrict __s, size_t __n,
const char *__restrict __fmt, ...))
@@ -70,6 +114,29 @@ __NTH (snprintf (char *__restrict __s, size_t __n,
__VA_ARGS__)
# endif
+# ifdef __use_clang_fortify
+
+# define __warn_vsnprintf_buf_size \
+ "call to vsnprintf may overflow the destination buffer"
+__fortify_overload __clang_warning (__warn_vsnprintf_buf_size) int
+__NTH (vsnprintf (char *__restrict const __clang_pass_object_size __s,
+ size_t __n, const char *__restrict __fmt, _G_va_list __ap))
+ __clang_enable_if (__bos (__s) != (size_t) -1 && __bos (__s) < __n,
+ "selected if this call looks dangerous")
+{
+ return __builtin___vsnprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1,
+ __bos (__s), __fmt, __ap);
+}
+# undef __warn_vsnprintf_buf_size
+
+__fortify_overload int
+__NTH (vsnprintf (char *__restrict const __clang_pass_object_size __s,
+ size_t __n, const char *__restrict __fmt, _G_va_list __ap))
+{
+ return __builtin___vsnprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1,
+ __bos (__s), __fmt, __ap);
+}
+# else
__fortify_function int
__NTH (vsnprintf (char *__restrict __s, size_t __n,
const char *__restrict __fmt, _G_va_list __ap))
@@ -77,6 +144,7 @@ __NTH (vsnprintf (char *__restrict __s, size_t __n,
return __builtin___vsnprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1,
__bos (__s), __fmt, __ap);
}
+# endif
#endif
@@ -90,7 +158,28 @@ extern int __vfprintf_chk (FILE *__restrict __stream, int __flag,
extern int __vprintf_chk (int __flag, const char *__restrict __format,
_G_va_list __ap);
-# ifdef __va_arg_pack
+# ifdef __use_clang_fortify
+__fortify_function int
+fprintf (FILE *__restrict __stream, const char *__restrict __fmt, ...)
+{
+ _G_va_list __ap;
+ va_start (__ap, __fmt);
+ int __result = __vfprintf_chk (__stream, __USE_FORTIFY_LEVEL - 1, __fmt,
+ __ap);
+ va_end (__ap);
+ return __result;
+}
+
+__fortify_function int
+printf (const char *__restrict __fmt, ...)
+{
+ _G_va_list __ap;
+ va_start (__ap, __fmt);
+ int __result = __vprintf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __ap);
+ va_end (__ap);
+ return __result;
+}
+# elif defined(__va_arg_pack)
__fortify_function int
fprintf (FILE *__restrict __stream, const char *__restrict __fmt, ...)
{
@@ -113,11 +202,11 @@ printf (const char *__restrict __fmt, ...)
__fortify_function int
vprintf (const char *__restrict __fmt, _G_va_list __ap)
{
-#ifdef __USE_EXTERN_INLINES
+# ifdef __USE_EXTERN_INLINES
return __vfprintf_chk (stdout, __USE_FORTIFY_LEVEL - 1, __fmt, __ap);
-#else
+# else
return __vprintf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __ap);
-#endif
+# endif
}
__fortify_function int
@@ -134,7 +223,17 @@ extern int __vdprintf_chk (int __fd, int __flag,
const char *__restrict __fmt, _G_va_list __arg)
__attribute__ ((__format__ (__printf__, 3, 0)));
-# ifdef __va_arg_pack
+# ifdef __use_clang_fortify
+__fortify_function int
+dprintf (int __fd, const char *__restrict __fmt, ...)
+{
+ _G_va_list __ap;
+ va_start (__ap, __fmt);
+ int __result = __dprintf_chk (__fd, __USE_FORTIFY_LEVEL - 1, __fmt, __ap);
+ va_end (__ap);
+ return __result;
+}
+# elif defined(__va_arg_pack)
__fortify_function int
dprintf (int __fd, const char *__restrict __fmt, ...)
{
@@ -171,7 +270,40 @@ extern int __obstack_vprintf_chk (struct obstack *__restrict __obstack,
_G_va_list __args)
__THROW __attribute__ ((__format__ (__printf__, 3, 0)));
-# ifdef __va_arg_pack
+# ifdef __use_clang_fortify
+__fortify_function int
+__NTH (asprintf (char **__restrict __ptr, const char *__restrict __fmt, ...))
+{
+ _G_va_list __ap;
+ va_start (__ap, __fmt);
+ int __result = __asprintf_chk (__ptr, __USE_FORTIFY_LEVEL - 1, __fmt, __ap);
+ va_end (__ap);
+ return __result;
+}
+
+__fortify_function int
+__NTH (__asprintf (char **__restrict __ptr, const char *__restrict __fmt,
+ ...))
+{
+ _G_va_list __ap;
+ va_start (__ap, __fmt);
+ int __result = __asprintf_chk (__ptr, __USE_FORTIFY_LEVEL - 1, __fmt, __ap);
+ va_end (__ap);
+ return __result;
+}
+
+__fortify_function int
+__NTH (obstack_printf (struct obstack *__restrict __obstack,
+ const char *__restrict __fmt, ...))
+{
+ _G_va_list __ap;
+ va_start (__ap, __fmt);
+ int __result = __obstack_printf_chk (__obstack, __USE_FORTIFY_LEVEL - 1,
+ __fmt, __ap);
+ va_end (__ap);
+ return __result;
+}
+# elif defined(__va_arg_pack)
__fortify_function int
__NTH (asprintf (char **__restrict __ptr, const char *__restrict __fmt, ...))
{
@@ -225,9 +357,31 @@ __NTH (obstack_vprintf (struct obstack *__restrict __obstack,
#if !defined __USE_ISOC11 \
|| (defined __cplusplus && __cplusplus <= 201103L && !defined __USE_GNU)
extern char *__gets_chk (char *__str, size_t) __wur;
+
+# define __warn_gets_use_something_else \
+ "please use fgets or getline instead, gets can't specify buffer size"
+# ifdef __use_clang_fortify
+__fortify_potential_overload __wur char *
+gets (char *const __clang_pass_object_size __str)
+ __clang_enable_if (__bos (__str) != (size_t) -1,
+ "selected if this call looks safe")
+{
+ return __gets_chk (__str, __bos (__str));
+}
+
+extern char *__REDIRECT (__gets_alias, (char *__str), gets) __wur;
+
+__fortify_potential_overload __wur
+__clang_warning (__warn_gets_use_something_else) char *
+gets (char *const __clang_pass_object_size __str)
+{
+ if (__bos (__str) != (size_t) -1)
+ return __gets_chk (__str, __bos (__str));
+ return __gets_alias (__str);
+}
+# else
extern char *__REDIRECT (__gets_warn, (char *__str), gets)
- __wur __warnattr ("please use fgets or getline instead, gets can't "
- "specify buffer size");
+ __wur __warnattr (__warn_gets_use_something_else);
__fortify_function __wur char *
gets (char *__str)
@@ -236,6 +390,8 @@ gets (char *__str)
return __gets_chk (__str, __bos (__str));
return __gets_warn (__str);
}
+# endif
+# undef __warn_gets_use_something_else
#endif
extern char *__fgets_chk (char *__restrict __s, size_t __size, int __n,
@@ -243,11 +399,32 @@ extern char *__fgets_chk (char *__restrict __s, size_t __size, int __n,
extern char *__REDIRECT (__fgets_alias,
(char *__restrict __s, int __n,
FILE *__restrict __stream), fgets) __wur;
+
+#define __warn_fgets_bufsize \
+ "fgets called with bigger size than length of destination buffer"
+#ifdef __use_clang_fortify
+__fortify_overload __wur __clang_warning (__warn_fgets_bufsize) char *
+fgets (char *__restrict const __clang_pass_object_size __s, int __n,
+ FILE *__restrict __stream)
+ __clang_enable_if (__bos (__s) != (size_t) -1 && __bos (__s) < __n,
+ "selected if this call looks dangerous")
+{
+ return __fgets_chk (__s, __bos (__s), __n, __stream);
+}
+
+__fortify_overload __wur char *
+fgets (char *__restrict const __clang_pass_object_size __s, int __n,
+ FILE *__restrict __stream)
+{
+ if (__bos (__s) != (size_t) -1)
+ return __fgets_chk (__s, __bos (__s), __n, __stream);
+ return __fgets_alias (__s, __n, __stream);
+}
+#else
extern char *__REDIRECT (__fgets_chk_warn,
(char *__restrict __s, size_t __size, int __n,
FILE *__restrict __stream), __fgets_chk)
- __wur __warnattr ("fgets called with bigger size than length "
- "of destination buffer");
+ __wur __warnattr (__warn_fgets_bufsize);
__fortify_function __wur char *
fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
@@ -262,6 +439,8 @@ fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
}
return __fgets_alias (__s, __n, __stream);
}
+#endif
+#undef __warn_fgets_bufsize
extern size_t __fread_chk (void *__restrict __ptr, size_t __ptrlen,
size_t __size, size_t __n,
@@ -270,13 +449,38 @@ extern size_t __REDIRECT (__fread_alias,
(void *__restrict __ptr, size_t __size,
size_t __n, FILE *__restrict __stream),
fread) __wur;
+
+#define __warn_fread_bufsize \
+ "fread called with bigger size * nmemb than length of destination buffer"
+#define __mul_may_overflow(size, n) \
+ ((size | n) >= (((size_t)1) << (8 * sizeof (size_t) / 2)))
+#ifdef __use_clang_fortify
+__fortify_overload __wur __clang_warning (__warn_fread_bufsize) size_t
+fread (void *__restrict const __clang_pass_object_size0 __ptr, size_t __size,
+ size_t __n, FILE *__restrict __stream)
+ __clang_enable_if (!__mul_may_overflow(__size, __n)
+ && __bos0 (__ptr) != (size_t) -1
+ && __bos0 (__ptr) < __size * __n,
+ "selected if this call looks dangerous")
+{
+ return __fread_chk (__ptr, __bos0 (__ptr), __size, __n, __stream);
+}
+
+__fortify_overload __wur size_t
+fread (void *__restrict const __clang_pass_object_size0 __ptr, size_t __size,
+ size_t __n, FILE *__restrict __stream)
+{
+ if (__bos0 (__ptr) != (size_t) -1)
+ return __fread_chk (__ptr, __bos0 (__ptr), __size, __n, __stream);
+ return __fread_alias (__ptr, __size, __n, __stream);
+}
+#else
extern size_t __REDIRECT (__fread_chk_warn,
(void *__restrict __ptr, size_t __ptrlen,
size_t __size, size_t __n,
FILE *__restrict __stream),
__fread_chk)
- __wur __warnattr ("fread called with bigger size * nmemb than length "
- "of destination buffer");
+ __wur __warnattr (__warn_fread_bufsize);
__fortify_function __wur size_t
fread (void *__restrict __ptr, size_t __size, size_t __n,
@@ -286,7 +490,7 @@ fread (void *__restrict __ptr, size_t __size, size_t __n,
{
if (!__builtin_constant_p (__size)
|| !__builtin_constant_p (__n)
- || (__size | __n) >= (((size_t) 1) << (8 * sizeof (size_t) / 2)))
+ || __mul_may_overflow(__size, __n))
return __fread_chk (__ptr, __bos0 (__ptr), __size, __n, __stream);
if (__size * __n > __bos0 (__ptr))
@@ -294,6 +498,9 @@ fread (void *__restrict __ptr, size_t __size, size_t __n,
}
return __fread_alias (__ptr, __size, __n, __stream);
}
+#endif
+#undef __mul_may_overflow
+#undef __warn_fread_bufsize
#ifdef __USE_GNU
extern char *__fgets_unlocked_chk (char *__restrict __s, size_t __size,
@@ -301,11 +508,33 @@ extern char *__fgets_unlocked_chk (char *__restrict __s, size_t __size,
extern char *__REDIRECT (__fgets_unlocked_alias,
(char *__restrict __s, int __n,
FILE *__restrict __stream), fgets_unlocked) __wur;
+
+# define __warn_fgets_unlocked_bufsize \
+ "fgets_unlocked called with bigger size than length of destination buffer"
+# ifdef __use_clang_fortify
+__fortify_overload __wur __clang_warning (__warn_fgets_unlocked_bufsize) char *
+fgets_unlocked (char *__restrict const __clang_pass_object_size __s, int __n,
+ FILE *__restrict __stream)
+ __clang_enable_if (__bos (__s) != (size_t) -1
+ && (size_t) __n > __bos (__s),
+ "selected if this call looks dangerous")
+{
+ return __fgets_unlocked_chk (__s, __bos (__s), __n, __stream);
+}
+
+__fortify_overload __wur char *
+fgets_unlocked (char *__restrict const __clang_pass_object_size __s, int __n,
+ FILE *__restrict __stream)
+{
+ if (__bos (__s) != (size_t) -1)
+ return __fgets_unlocked_chk (__s, __bos (__s), __n, __stream);
+ return __fgets_unlocked_alias (__s, __n, __stream);
+}
+# else
extern char *__REDIRECT (__fgets_unlocked_chk_warn,
(char *__restrict __s, size_t __size, int __n,
FILE *__restrict __stream), __fgets_unlocked_chk)
- __wur __warnattr ("fgets_unlocked called with bigger size than length "
- "of destination buffer");
+ __wur __warnattr (__warn_fgets_unlocked_bufsize);
__fortify_function __wur char *
fgets_unlocked (char *__restrict __s, int __n, FILE *__restrict __stream)
@@ -320,6 +549,8 @@ fgets_unlocked (char *__restrict __s, int __n, FILE *__restrict __stream)
}
return __fgets_unlocked_alias (__s, __n, __stream);
}
+# endif
+# undef __warn_fgets_unlocked_bufsize
#endif
#ifdef __USE_MISC
@@ -331,13 +562,40 @@ extern size_t __REDIRECT (__fread_unlocked_alias,
(void *__restrict __ptr, size_t __size,
size_t __n, FILE *__restrict __stream),
fread_unlocked) __wur;
+
+# define __warn_fread_unlocked_buflen \
+ "fread_unlocked called with bigger size * nmemb than length of " \
+ "destination buffer"
+
+# ifdef __use_clang_fortify
+__fortify_overload __wur __clang_warning (__warn_fread_unlocked_buflen) size_t
+fread_unlocked (void *__restrict const __clang_pass_object_size0 __ptr,
+ size_t __size, size_t __n, FILE *__restrict __stream)
+ __clang_enable_if ((__size | __n)
+ >= (((size_t) 1) << (8 * sizeof (size_t) / 2)),
+ "selected if we can guarantee no overflow")
+ __clang_enable_if (__bos0 (__ptr) != (size_t) -1
+ && __size * __n > __bos0 (__ptr),
+ "selected if this call looks dangerous")
+{
+ return __fread_unlocked_chk (__ptr, __bos0 (__ptr), __size, __n, __stream);
+}
+
+__fortify_overload __wur size_t
+fread_unlocked (void *__restrict const __clang_pass_object_size0 __ptr,
+ size_t __size, size_t __n, FILE *__restrict __stream)
+{
+ if (__bos0 (__ptr) != (size_t) -1)
+ return __fread_unlocked_chk (__ptr, __bos0 (__ptr), __size, __n, __stream);
+ return __fread_unlocked_alias (__ptr, __size, __n, __stream);
+}
+# else
extern size_t __REDIRECT (__fread_unlocked_chk_warn,
(void *__restrict __ptr, size_t __ptrlen,
size_t __size, size_t __n,
FILE *__restrict __stream),
__fread_unlocked_chk)
- __wur __warnattr ("fread_unlocked called with bigger size * nmemb than "
- "length of destination buffer");
+ __wur __warnattr (__warn_fread_unlocked_buflen);
__fortify_function __wur size_t
fread_unlocked (void *__restrict __ptr, size_t __size, size_t __n,
@@ -356,7 +614,7 @@ fread_unlocked (void *__restrict __ptr, size_t __size, size_t __n,
__stream);
}
-# ifdef __USE_EXTERN_INLINES
+# ifdef __USE_EXTERN_INLINES
if (__builtin_constant_p (__size)
&& __builtin_constant_p (__n)
&& (__size | __n) < (((size_t) 1) << (8 * sizeof (size_t) / 2))
@@ -376,7 +634,9 @@ fread_unlocked (void *__restrict __ptr, size_t __size, size_t __n,
}
return (__cptr - (char *) __ptr) / __size;
}
-# endif
+# endif
return __fread_unlocked_alias (__ptr, __size, __n, __stream);
}
+# endif
+# undef __warn_fread_unlocked_buflen
#endif
--- libio/stdio.h
+++ libio/stdio.h
@@ -361,8 +361,10 @@ extern int fprintf (FILE *__restrict __stream,
marked with __THROW. */
extern int printf (const char *__restrict __format, ...);
/* Write formatted output to S. */
+__fortify_overloadable
extern int sprintf (char *__restrict __s,
- const char *__restrict __format, ...) __THROWNL;
+ const char *__restrict __format, ...)
+ __THROWNL __CLANG_NO_MANGLE (sprintf);
/* Write formatted output to S from argument list ARG.
@@ -376,20 +378,25 @@ extern int vfprintf (FILE *__restrict __s, const char *__restrict __format,
marked with __THROW. */
extern int vprintf (const char *__restrict __format, _G_va_list __arg);
/* Write formatted output to S from argument list ARG. */
+__fortify_overloadable
extern int vsprintf (char *__restrict __s, const char *__restrict __format,
- _G_va_list __arg) __THROWNL;
+ _G_va_list __arg) __THROWNL __CLANG_NO_MANGLE (vsprintf);
__END_NAMESPACE_STD
#if defined __USE_BSD || defined __USE_ISOC99 || defined __USE_UNIX98
__BEGIN_NAMESPACE_C99
/* Maximum chars of output to write in MAXLEN. */
+__fortify_overloadable
extern int snprintf (char *__restrict __s, size_t __maxlen,
const char *__restrict __format, ...)
- __THROWNL __attribute__ ((__format__ (__printf__, 3, 4)));
+ __THROWNL __attribute__ ((__format__ (__printf__, 3, 4)))
+ __CLANG_NO_MANGLE (snprintf);
+__fortify_overloadable
extern int vsnprintf (char *__restrict __s, size_t __maxlen,
const char *__restrict __format, _G_va_list __arg)
- __THROWNL __attribute__ ((__format__ (__printf__, 3, 0)));
+ __THROWNL __attribute__ ((__format__ (__printf__, 3, 0)))
+ __CLANG_NO_MANGLE (vsnprintf);
__END_NAMESPACE_C99
#endif
@@ -619,8 +626,9 @@ __BEGIN_NAMESPACE_STD
This function is a possible cancellation point and therefore not
marked with __THROW. */
+__fortify_overloadable
extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
- __wur;
+ __wur __CLANG_NO_MANGLE (fgets);
#if !defined __USE_ISOC11 \
|| (defined __cplusplus && __cplusplus <= 201103L)
@@ -635,7 +643,9 @@ extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
This function is a possible cancellation point and therefore not
marked with __THROW. */
-extern char *gets (char *__s) __wur __attribute_deprecated__;
+__fortify_overloadable
+extern char *gets (char *__s) __wur __attribute_deprecated__
+ __CLANG_NO_MANGLE (gets);
#endif
__END_NAMESPACE_STD
@@ -646,8 +656,10 @@ __END_NAMESPACE_STD
cancellation point. But due to similarity with an POSIX interface
or due to the implementation it is a cancellation point and
therefore not marked with __THROW. */
+__fortify_overloadable
extern char *fgets_unlocked (char *__restrict __s, int __n,
- FILE *__restrict __stream) __wur;
+ FILE *__restrict __stream)
+ __wur __CLANG_NO_MANGLE (fgets_unlocked);
#endif
@@ -706,14 +718,18 @@ extern int ungetc (int __c, FILE *__stream);
This function is a possible cancellation point and therefore not
marked with __THROW. */
+__fortify_overloadable
extern size_t fread (void *__restrict __ptr, size_t __size,
- size_t __n, FILE *__restrict __stream) __wur;
+ size_t __n, FILE *__restrict __stream)
+ __wur __CLANG_NO_MANGLE (fread);
/* Write chunks of generic data to STREAM.
This function is a possible cancellation point and therefore not
marked with __THROW. */
+__fortify_overloadable
extern size_t fwrite (const void *__restrict __ptr, size_t __size,
- size_t __n, FILE *__restrict __s);
+ size_t __n, FILE *__restrict __s)
+ __CLANG_NO_MANGLE (fwrite);
__END_NAMESPACE_STD
#ifdef __USE_GNU
@@ -734,8 +750,10 @@ extern int fputs_unlocked (const char *__restrict __s,
cancellation point. But due to similarity with an POSIX interface
or due to the implementation they are cancellation points and
therefore not marked with __THROW. */
+__fortify_overloadable
extern size_t fread_unlocked (void *__restrict __ptr, size_t __size,
- size_t __n, FILE *__restrict __stream) __wur;
+ size_t __n, FILE *__restrict __stream)
+__wur __CLANG_NO_MANGLE (fread_unlocked);
extern size_t fwrite_unlocked (const void *__restrict __ptr, size_t __size,
size_t __n, FILE *__restrict __stream);
#endif
--- misc/bits/syslog.h
+++ misc/bits/syslog.h
@@ -20,11 +20,33 @@
# error "Never include <bits/syslog.h> directly; use <sys/syslog.h> instead."
#endif
+#ifdef __USE_BSD
+extern void __vsyslog_chk (int __pri, int __flag, const char *__fmt,
+ __gnuc_va_list __ap)
+ __attribute__ ((__format__ (__printf__, 3, 0)));
+
+__fortify_function void
+vsyslog (int __pri, const char *__fmt, __gnuc_va_list __ap)
+{
+ __vsyslog_chk (__pri, __USE_FORTIFY_LEVEL - 1, __fmt, __ap);
+}
+#endif
extern void __syslog_chk (int __pri, int __flag, const char *__fmt, ...)
__attribute__ ((__format__ (__printf__, 3, 4)));
-#ifdef __va_arg_pack
+#if defined __use_clang_fortify && __USE_BSD
+/* clang doesn't support __va_arg_pack, so this is only possible if we have
+ vsyslog. */
+__fortify_function void
+syslog (int __pri, const char *__fmt, ...)
+{
+ __gnuc_va_list __ap;
+ va_start (__ap, __fmt);
+ __vsyslog_chk (__pri, __USE_FORTIFY_LEVEL - 1, __fmt, __ap);
+ va_end (__ap);
+}
+#elif defined __va_arg_pack
__fortify_function void
syslog (int __pri, const char *__fmt, ...)
{
@@ -35,15 +57,3 @@ syslog (int __pri, const char *__fmt, ...)
__syslog_chk (pri, __USE_FORTIFY_LEVEL - 1, __VA_ARGS__)
#endif
-
-#ifdef __USE_BSD
-extern void __vsyslog_chk (int __pri, int __flag, const char *__fmt,
- __gnuc_va_list __ap)
- __attribute__ ((__format__ (__printf__, 3, 0)));
-
-__fortify_function void
-vsyslog (int __pri, const char *__fmt, __gnuc_va_list __ap)
-{
- __vsyslog_chk (__pri, __USE_FORTIFY_LEVEL - 1, __fmt, __ap);
-}
-#endif
--- misc/sys/cdefs.h
+++ misc/sys/cdefs.h
@@ -129,9 +129,51 @@
/* Fortify support. */
-#define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1)
+#define __bos_level (__USE_FORTIFY_LEVEL > 1)
+#define __bos(ptr) __builtin_object_size (ptr, __bos_level)
#define __bos0(ptr) __builtin_object_size (ptr, 0)
#define __fortify_function __extern_always_inline __attribute_artificial__
+#if defined __clang__ && __USE_FORTIFY_LEVEL > 0 \
+ && !defined _CLANG_FORTIFY_DISABLE
+# define __use_clang_fortify 1
+/* Clang-style FORTIFY creates a different symbol for each FORTIFY'ed function,
+ whereas GCC-style doesn't. Thus, GCC can assume that the FORTIFY'ed function
+ is always available externally, but clang can't. */
+# define __attribute_overloadable__ __attribute__ ((__overloadable__))
+# define __fortify_overload static __always_inline __attribute_overloadable__
+/* FORTIFY functions that exist only as decls. Some of them share the same
+ signature as the FORTIFY'ed function, so we sometimes can't put `static` on
+ them. */
+# define __fortify_error_function static __attribute_overloadable__
+# define __clang_pass_object_size_n(n) __attribute__ ((pass_object_size (n)))
+# define __clang_enable_if(c, m) __attribute__ ((enable_if ((c), (m))))
+# define __clang_prefer_this_overload __clang_enable_if (1, "")
+# define __clang_warning(what) __attribute__ ((deprecated(what)))
+# define __clang_error(what) __attribute__ ((unavailable(what)))
+# define __fortify_potential_overload __fortify_overload
+# define __fortify_overloadable __attribute_overloadable__
+#else
+# define __fortify_potential_overload __fortify_function
+/* Some functions/decls can be shared between clang-style and non-clang-style
+ FORTIFY. Turning these into nops makes that possible. */
+# define __clang_pass_object_size_n(n)
+# define __attribute_overloadable__
+# define __fortify_overloadable
+#endif
+
+#define __clang_pass_object_size0 __clang_pass_object_size_n (0)
+#define __clang_pass_object_size __clang_pass_object_size_n (__bos_level)
+
+#ifdef __use_clang_fortify
+/* It's intentional that this allows macros to be expanded. Some libraries
+ #define stdlib functions to custom function names; if we don't allow this
+ expansion to happen, the name of the function in user code will be the
+ custom one, but the symbol we emit for the function definition (and calls to
+ the function) will be the stdlib one. This is *very* bad, and subtle. */
+# define __CLANG_NO_MANGLE(name) __asm__ (__STRING (name))
+#else
+# define __CLANG_NO_MANGLE(name)
+#endif
#if __GNUC_PREREQ (4,3)
# define __warndecl(name, msg) \
--- posix/bits/unistd.h
+++ posix/bits/unistd.h
@@ -24,11 +24,31 @@ extern ssize_t __read_chk (int __fd, void *__buf, size_t __nbytes,
size_t __buflen) __wur;
extern ssize_t __REDIRECT (__read_alias, (int __fd, void *__buf,
size_t __nbytes), read) __wur;
+
+#define __warn_read_buf_size "read called with bigger length than size of " \
+ "the destination buffer"
+#ifdef __use_clang_fortify
+__fortify_overload __wur __clang_warning (__warn_read_buf_size) ssize_t
+read (int __fd, void *const __clang_pass_object_size0 __buf, size_t __nbytes)
+ __clang_enable_if (__bos0 (__buf) != (size_t) -1
+ && __nbytes > __bos0 (__buf),
+ "selected if this read call seems unsafe")
+{
+ return __read_chk (__fd, __buf, __nbytes, __bos0 (__buf));
+}
+
+__fortify_overload __wur ssize_t
+read (int __fd, void *const __clang_pass_object_size0 __buf, size_t __nbytes)
+{
+ if (__bos0 (__buf) != (size_t) -1)
+ return __read_chk (__fd, __buf, __nbytes, __bos0 (__buf));
+ return __read_alias (__fd, __buf, __nbytes);
+}
+#else
extern ssize_t __REDIRECT (__read_chk_warn,
(int __fd, void *__buf, size_t __nbytes,
size_t __buflen), __read_chk)
- __wur __warnattr ("read called with bigger length than size of "
- "the destination buffer");
+ __wur __warnattr (__warn_read_buf_size);
__fortify_function __wur ssize_t
read (int __fd, void *__buf, size_t __nbytes)
@@ -43,6 +63,8 @@ read (int __fd, void *__buf, size_t __nbytes)
}
return __read_alias (__fd, __buf, __nbytes);
}
+#endif
+#undef __warn_read_buf_size
#ifdef __USE_UNIX98
extern ssize_t __pread_chk (int __fd, void *__buf, size_t __nbytes,
@@ -55,19 +77,42 @@ extern ssize_t __REDIRECT (__pread_alias,
extern ssize_t __REDIRECT (__pread64_alias,
(int __fd, void *__buf, size_t __nbytes,
__off64_t __offset), pread64) __wur;
+
+# define __warn_pread_bufsize \
+ "pread called with bigger length than size of the destination buffer"
+# define __warn_pread64_bufsize \
+ "pread64 called with bigger length than size of the destination buffer"
extern ssize_t __REDIRECT (__pread_chk_warn,
(int __fd, void *__buf, size_t __nbytes,
__off_t __offset, size_t __bufsize), __pread_chk)
- __wur __warnattr ("pread called with bigger length than size of "
- "the destination buffer");
+ __wur __warnattr (__warn_pread_bufsize);
extern ssize_t __REDIRECT (__pread64_chk_warn,
(int __fd, void *__buf, size_t __nbytes,
__off64_t __offset, size_t __bufsize),
__pread64_chk)
- __wur __warnattr ("pread64 called with bigger length than size of "
- "the destination buffer");
+ __wur __warnattr (__warn_pread64_bufsize);
# ifndef __USE_FILE_OFFSET64
+# ifdef __use_clang_fortify
+__fortify_overload __wur __clang_warning (__warn_pread_bufsize) ssize_t
+pread (int __fd, void *const __clang_pass_object_size0 __buf, size_t __nbytes,
+ __off_t __offset)
+ __clang_enable_if (__bos0 (__buf) != (size_t) -1
+ && __nbytes > __bos0 (__buf),
+ "selected if this call looks dangerous")
+{
+ return __pread_chk (__fd, __buf, __nbytes, __offset, __bos0 (__buf));
+}
+
+__fortify_overload __wur ssize_t
+pread (int __fd, void *const __clang_pass_object_size0 __buf, size_t __nbytes,
+ __off_t __offset)
+{
+ if (__bos0 (__buf) != (size_t) -1)
+ return __pread_chk (__fd, __buf, __nbytes, __offset, __bos0 (__buf));
+ return __pread_alias (__fd, __buf, __nbytes, __offset);
+}
+# else
__fortify_function __wur ssize_t
pread (int __fd, void *__buf, size_t __nbytes, __off_t __offset)
{
@@ -82,7 +127,28 @@ pread (int __fd, void *__buf, size_t __nbytes, __off_t __offset)
}
return __pread_alias (__fd, __buf, __nbytes, __offset);
}
+# endif
# else
+# ifdef __use_clang_fortify
+__fortify_overload __wur __clang_warning (__warn_pread64_bufsize) ssize_t
+pread (int __fd, void *const __clang_pass_object_size0 __buf, size_t __nbytes,
+ __off64_t __offset)
+ __clang_enable_if (__bos0 (__buf) != (size_t) -1
+ && __nbytes > __bos0 (__buf),
+ "selected if this call looks dangerous")
+{
+ return __pread64_chk (__fd, __buf, __nbytes, __offset, __bos0 (__buf));
+}
+
+__fortify_overload __wur ssize_t
+pread (int __fd, void *const __clang_pass_object_size0 __buf, size_t __nbytes,
+ __off64_t __offset)
+{
+ if (__bos0 (__buf) != (size_t) -1)
+ return __pread64_chk (__fd, __buf, __nbytes, __offset, __bos0 (__buf));
+ return __pread64_alias (__fd, __buf, __nbytes, __offset);
+}
+# else
__fortify_function __wur ssize_t
pread (int __fd, void *__buf, size_t __nbytes, __off64_t __offset)
{
@@ -98,9 +164,30 @@ pread (int __fd, void *__buf, size_t __nbytes, __off64_t __offset)
return __pread64_alias (__fd, __buf, __nbytes, __offset);
}
+# endif
# endif
# ifdef __USE_LARGEFILE64
+# ifdef __use_clang_fortify
+__fortify_overload __wur __clang_warning (__warn_pread64_bufsize) ssize_t
+pread64 (int __fd, void *const __clang_pass_object_size0 __buf, size_t __nbytes,
+ __off64_t __offset)
+ __clang_enable_if (__bos0 (__buf) != (size_t) -1
+ && __nbytes > __bos0 (__buf),
+ "selected if this call looks dangerous")
+{
+ return __pread64_chk (__fd, __buf, __nbytes, __offset, __bos0 (__buf));
+}
+
+__fortify_overload __wur ssize_t
+pread64 (int __fd, void *const __clang_pass_object_size0 __buf, size_t __nbytes,
+ __off64_t __offset)
+{
+ if (__bos0 (__buf) != (size_t) -1)
+ return __pread64_chk (__fd, __buf, __nbytes, __offset, __bos0 (__buf));
+ return __pread64_alias (__fd, __buf, __nbytes, __offset);
+}
+# else
__fortify_function __wur ssize_t
pread64 (int __fd, void *__buf, size_t __nbytes, __off64_t __offset)
{
@@ -116,7 +203,10 @@ pread64 (int __fd, void *__buf, size_t __nbytes, __off64_t __offset)
return __pread64_alias (__fd, __buf, __nbytes, __offset);
}
+# endif
# endif
+# undef __warn_pread_bufsize
+# undef __warn_pread64_bufsize
#endif
#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K
@@ -128,12 +218,36 @@ extern ssize_t __REDIRECT_NTH (__readlink_alias,
(const char *__restrict __path,
char *__restrict __buf, size_t __len), readlink)
__nonnull ((1, 2)) __wur;
+
+# define __warn_readlink_buf_size "readlink called with bigger length than " \
+ "size of destination buffer"
+# ifdef __use_clang_fortify
+__fortify_overload __nonnull ((1, 2)) __wur
+__clang_warning (__warn_readlink_buf_size) ssize_t
+__NTH (readlink (const char *__restrict __path,
+ char *__restrict const __clang_pass_object_size __buf,
+ size_t __len))
+ __clang_enable_if (__bos (__buf) != (size_t) -1 && __len > __bos (__buf),
+ "selected if this call looks dangerous")
+{
+ return __readlink_chk (__path, __buf, __len, __bos (__buf));
+}
+
+__fortify_overload __nonnull ((1, 2)) __wur ssize_t
+__NTH (readlink (const char *__restrict __path,
+ char *__restrict const __clang_pass_object_size __buf,
+ size_t __len))
+{
+ if (__bos (__buf) != (size_t) -1)
+ return __readlink_chk (__path, __buf, __len, __bos (__buf));
+ return __readlink_alias (__path, __buf, __len);
+}
+# else
extern ssize_t __REDIRECT_NTH (__readlink_chk_warn,
(const char *__restrict __path,
char *__restrict __buf, size_t __len,
size_t __buflen), __readlink_chk)
- __nonnull ((1, 2)) __wur __warnattr ("readlink called with bigger length "
- "than size of destination buffer");
+ __nonnull ((1, 2)) __wur __warnattr (__warn_readlink_buf_size);
__fortify_function __nonnull ((1, 2)) __wur ssize_t
__NTH (readlink (const char *__restrict __path, char *__restrict __buf,
@@ -149,6 +263,8 @@ __NTH (readlink (const char *__restrict __path, char *__restrict __buf,
}
return __readlink_alias (__path, __buf, __len);
}
+# endif
+# undef __warn_readlink_buf_size
#endif
#ifdef __USE_ATFILE
@@ -161,13 +277,38 @@ extern ssize_t __REDIRECT_NTH (__readlinkat_alias,
char *__restrict __buf, size_t __len),
readlinkat)
__nonnull ((2, 3)) __wur;
+
+# define __warn_readlinkat_buf_size "readlinkat called with bigger length " \
+ "than size of destination buffer"
+# ifdef __use_clang_fortify
+__fortify_overload __nonnull ((2, 3)) __wur
+__clang_warning (__warn_readlinkat_buf_size) ssize_t
+__NTH (readlinkat (int __fd,
+ const char *__restrict __path,
+ char *__restrict const __clang_pass_object_size __buf,
+ size_t __len))
+ __clang_enable_if (__bos (__buf) != (size_t) -1 && __bos (__buf) <= __len,
+ "selected if this call looks dangerous")
+{
+ return __readlinkat_chk (__fd, __path, __buf, __len, __bos (__buf));
+}
+
+__fortify_overload __nonnull ((2, 3)) __wur ssize_t
+__NTH (readlinkat (int __fd,
+ const char *__restrict __path,
+ char *__restrict const __clang_pass_object_size __buf,
+ size_t __len))
+{
+ if (__bos (__buf) != (size_t) -1)
+ return __readlinkat_chk (__fd, __path, __buf, __len, __bos (__buf));
+ return __readlinkat_alias (__fd, __path, __buf, __len);
+}
+# else
extern ssize_t __REDIRECT_NTH (__readlinkat_chk_warn,
(int __fd, const char *__restrict __path,
char *__restrict __buf, size_t __len,
size_t __buflen), __readlinkat_chk)
- __nonnull ((2, 3)) __wur __warnattr ("readlinkat called with bigger "
- "length than size of destination "
- "buffer");
+ __nonnull ((2, 3)) __wur __warnattr (__warn_readlinkat_buf_size);
__fortify_function __nonnull ((2, 3)) __wur ssize_t
__NTH (readlinkat (int __fd, const char *__restrict __path,
@@ -184,17 +325,38 @@ __NTH (readlinkat (int __fd, const char *__restrict __path,
}
return __readlinkat_alias (__fd, __path, __buf, __len);
}
+# endif
+# undef __warn_readlinkat_buf_size
#endif
extern char *__getcwd_chk (char *__buf, size_t __size, size_t __buflen)
__THROW __wur;
extern char *__REDIRECT_NTH (__getcwd_alias,
(char *__buf, size_t __size), getcwd) __wur;
+
+#define __warn_getcwd_buf_size \
+ "getcwd caller with bigger length than size of destination buffer"
+#ifdef __use_clang_fortify
+__fortify_overload __wur __clang_warning (__warn_getcwd_buf_size) char *
+__NTH (getcwd (char *const __clang_pass_object_size __buf, size_t __size))
+ __clang_enable_if (__bos (__buf) != (size_t) -1 && __size > __bos (__buf),
+ "selected if this call looks dangerous")
+{
+ return __getcwd_chk (__buf, __size, __bos (__buf));
+}
+
+__fortify_overload __wur char *
+__NTH (getcwd (char *const __clang_pass_object_size __buf, size_t __size))
+{
+ if (__bos (__buf) != (size_t) -1)
+ return __getcwd_chk (__buf, __size, __bos (__buf));
+ return __getcwd_alias (__buf, __size);
+}
+#else
extern char *__REDIRECT_NTH (__getcwd_chk_warn,
(char *__buf, size_t __size, size_t __buflen),
__getcwd_chk)
- __wur __warnattr ("getcwd caller with bigger length than size of "
- "destination buffer");
+ __wur __warnattr (__warn_getcwd_buf_size);
__fortify_function __wur char *
__NTH (getcwd (char *__buf, size_t __size))
@@ -209,32 +371,82 @@ __NTH (getcwd (char *__buf, size_t __size))
}
return __getcwd_alias (__buf, __size);
}
+#endif
+#undef __warn_getcwd_buf_size
#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED
+# define __warn_getwd_use_something_else \
+ "please use getcwd instead, as getwd doesn't specify buffer size"
+
extern char *__getwd_chk (char *__buf, size_t buflen)
__THROW __nonnull ((1)) __wur;
+# ifdef __use_clang_fortify
+__fortify_potential_overload __nonnull ((1)) __attribute_deprecated__ __wur
+char *
+__NTH (getwd (char *const __clang_pass_object_size __buf))
+ __clang_enable_if (__bos (__buf) != (size_t) -1,
+ "selected if this call looks safe")
+{
+ return __getwd_chk (__buf, __bos (__buf));
+}
+
+extern char *__REDIRECT (__getwd_alias, (char *__str), getwd) __wur;
+
+__fortify_potential_overload __nonnull ((1)) __attribute_deprecated__
+__clang_warning (__warn_getwd_use_something_else) __wur
+char *
+__NTH (getwd (char *const __clang_pass_object_size __buf))
+{
+ if (__bos (__buf) != (size_t) -1)
+ return __getwd_chk (__buf, __bos (__buf));
+ return __getwd_alias (__buf);
+}
+# else
extern char *__REDIRECT_NTH (__getwd_warn, (char *__buf), getwd)
- __nonnull ((1)) __wur __warnattr ("please use getcwd instead, as getwd "
- "doesn't specify buffer size");
+ __nonnull ((1)) __wur __warnattr (__warn_getwd_use_something_else);
-__fortify_function __nonnull ((1)) __attribute_deprecated__ __wur char *
-__NTH (getwd (char *__buf))
+__fortify_potential_overload __nonnull ((1)) __attribute_deprecated__ __wur
+char *
+__NTH (getwd (char *const __clang_pass_object_size __buf))
{
if (__bos (__buf) != (size_t) -1)
return __getwd_chk (__buf, __bos (__buf));
return __getwd_warn (__buf);
}
+# endif
+# undef __warn_getwd_use_something_else
#endif
extern size_t __confstr_chk (int __name, char *__buf, size_t __len,
size_t __buflen) __THROW;
extern size_t __REDIRECT_NTH (__confstr_alias, (int __name, char *__buf,
size_t __len), confstr);
+
+#define __warn_confstr_dest_size \
+ "confstr called with bigger length than size of destination buffer"
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_confstr_dest_size) size_t
+__NTH (confstr (int __name, char *const __clang_pass_object_size __buf,
+ size_t __len))
+ __clang_enable_if (__bos (__buf) != (size_t) -1 && __bos (__buf) < __len,
+ "selected if this call looks dangerous")
+{
+ return __confstr_chk (__name, __buf, __len, __bos (__buf));
+}
+
+__fortify_overload size_t
+__NTH (confstr (int __name, char *const __clang_pass_object_size __buf,
+ size_t __len))
+{
+ if (__bos (__buf) != (size_t) -1)
+ return __confstr_chk (__name, __buf, __len, __bos (__buf));
+ return __confstr_alias (__name, __buf, __len);
+}
+#else
extern size_t __REDIRECT_NTH (__confstr_chk_warn,
(int __name, char *__buf, size_t __len,
size_t __buflen), __confstr_chk)
- __warnattr ("confstr called with bigger length than size of destination "
- "buffer");
+ __warnattr (__warn_confstr_dest_size);
__fortify_function size_t
__NTH (confstr (int __name, char *__buf, size_t __len))
@@ -249,17 +461,40 @@ __NTH (confstr (int __name, char *__buf, size_t __len))
}
return __confstr_alias (__name, __buf, __len);
}
+#endif
+#undef __warn_confstr_dest_size
extern int __getgroups_chk (int __size, __gid_t __list[], size_t __listlen)
__THROW __wur;
extern int __REDIRECT_NTH (__getgroups_alias, (int __size, __gid_t __list[]),
getgroups) __wur;
+
+#define __warn_getgroups_count \
+ "getgroups called with bigger group count than what can fit into " \
+ "destination buffer"
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_getgroups_count) int
+__NTH (getgroups (int __size, __gid_t *const __clang_pass_object_size __list))
+ __clang_enable_if (__bos (__list) != (size_t) -1
+ && __size * sizeof (__gid_t) > __bos (__list),
+ "selected if this call looks dangerous")
+{
+ return __getgroups_chk (__size, __list, __bos (__list));
+}
+
+__fortify_overload int
+__NTH (getgroups (int __size, __gid_t *const __clang_pass_object_size __list))
+{
+ if (__bos (__list) != (size_t) -1)
+ return __getgroups_chk (__size, __list, __bos (__list));
+ return __getgroups_alias (__size, __list);
+}
+#else
extern int __REDIRECT_NTH (__getgroups_chk_warn,
(int __size, __gid_t __list[], size_t __listlen),
__getgroups_chk)
- __wur __warnattr ("getgroups called with bigger group count than what "
- "can fit into destination buffer");
+ __wur __warnattr (__warn_getgroups_count);
__fortify_function int
__NTH (getgroups (int __size, __gid_t __list[]))
@@ -274,6 +509,8 @@ __NTH (getgroups (int __size, __gid_t __list[]))
}
return __getgroups_alias (__size, __list);
}
+#endif
+#undef __warn_getgroups_count
extern int __ttyname_r_chk (int __fd, char *__buf, size_t __buflen,
@@ -281,11 +518,33 @@ extern int __ttyname_r_chk (int __fd, char *__buf, size_t __buflen,
extern int __REDIRECT_NTH (__ttyname_r_alias, (int __fd, char *__buf,
size_t __buflen), ttyname_r)
__nonnull ((2));
+
+#define __warn_ttyname_buflen "ttyname_r called with bigger buflen than " \
+ "size of destination buffer"
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_ttyname_buflen) int
+__NTH (ttyname_r (int __fd, char *const __clang_pass_object_size __buf,
+ size_t __buflen))
+ __clang_enable_if (__bos (__buf) != (size_t) -1
+ && __buflen > __bos (__buf),
+ "selected if this call looks dangerous")
+{
+ return __ttyname_r_chk (__fd, __buf, __buflen, __bos (__buf));
+}
+
+__fortify_overload int
+__NTH (ttyname_r (int __fd, char *const __clang_pass_object_size __buf,
+ size_t __buflen))
+{
+ if (__bos (__buf) != (size_t) -1)
+ return __ttyname_r_chk (__fd, __buf, __buflen, __bos (__buf));
+ return __ttyname_r_alias (__fd, __buf, __buflen);
+}
+#else
extern int __REDIRECT_NTH (__ttyname_r_chk_warn,
(int __fd, char *__buf, size_t __buflen,
size_t __nreal), __ttyname_r_chk)
- __nonnull ((2)) __warnattr ("ttyname_r called with bigger buflen than "
- "size of destination buffer");
+ __nonnull ((2)) __warnattr (__warn_ttyname_buflen);
__fortify_function int
__NTH (ttyname_r (int __fd, char *__buf, size_t __buflen))
@@ -300,6 +559,8 @@ __NTH (ttyname_r (int __fd, char *__buf, size_t __buflen))
}
return __ttyname_r_alias (__fd, __buf, __buflen);
}
+#endif
+#undef __warn_ttyname_buflen
#if defined __USE_REENTRANT || defined __USE_POSIX199506
@@ -307,11 +568,31 @@ extern int __getlogin_r_chk (char *__buf, size_t __buflen, size_t __nreal)
__nonnull ((1));
extern int __REDIRECT (__getlogin_r_alias, (char *__buf, size_t __buflen),
getlogin_r) __nonnull ((1));
+
+# define __warn_getlogin_r_buflen "getlogin_r called with bigger buflen than " \
+ "size of destination buffer"
+# ifdef __use_clang_fortify
+__fortify_overload int
+getlogin_r (char *const __clang_pass_object_size __buf, size_t __buflen)
+ __clang_enable_if (__bos (__buf) != (size_t) -1
+ && __buflen > __bos (__buf),
+ "selected if this call looks dangerous")
+{
+ return __getlogin_r_chk (__buf, __buflen, __bos (__buf));
+}
+
+__fortify_overload int
+getlogin_r (char *const __clang_pass_object_size __buf, size_t __buflen)
+{
+ if (__bos (__buf) != (size_t) -1)
+ return __getlogin_r_chk (__buf, __buflen, __bos (__buf));
+ return __getlogin_r_alias (__buf, __buflen);
+}
+# else
extern int __REDIRECT (__getlogin_r_chk_warn,
(char *__buf, size_t __buflen, size_t __nreal),
__getlogin_r_chk)
- __nonnull ((1)) __warnattr ("getlogin_r called with bigger buflen than "
- "size of destination buffer");
+ __nonnull ((1)) __warnattr (__warn_getlogin_r_buflen);
__fortify_function int
getlogin_r (char *__buf, size_t __buflen)
@@ -326,6 +607,8 @@ getlogin_r (char *__buf, size_t __buflen)
}
return __getlogin_r_alias (__buf, __buflen);
}
+# endif
+# undef __warn_getlogin_r_buflen
#endif
@@ -334,11 +617,32 @@ extern int __gethostname_chk (char *__buf, size_t __buflen, size_t __nreal)
__THROW __nonnull ((1));
extern int __REDIRECT_NTH (__gethostname_alias, (char *__buf, size_t __buflen),
gethostname) __nonnull ((1));
+
+# define __warn_gethostname_buflen "gethostname called with bigger buflen " \
+ "than size of destination buffer"
+# ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_gethostname_buflen) int
+__NTH (gethostname (char *const __clang_pass_object_size __buf, size_t __buflen))
+ __clang_enable_if (__bos (__buf) != (size_t) -1
+ && __buflen > __bos (__buf),
+ "selected if this call looks dangerous")
+{
+ return __gethostname_chk (__buf, __buflen, __bos (__buf));
+}
+
+__fortify_overload int
+__NTH (gethostname (char *const __clang_pass_object_size __buf,
+ size_t __buflen))
+{
+ if (__bos (__buf) != (size_t) -1)
+ return __gethostname_chk (__buf, __buflen, __bos (__buf));
+ return __gethostname_alias (__buf, __buflen);
+}
+# else
extern int __REDIRECT_NTH (__gethostname_chk_warn,
(char *__buf, size_t __buflen, size_t __nreal),
__gethostname_chk)
- __nonnull ((1)) __warnattr ("gethostname called with bigger buflen than "
- "size of destination buffer");
+ __nonnull ((1)) __warnattr (__warn_gethostname_buflen);
__fortify_function int
__NTH (gethostname (char *__buf, size_t __buflen))
@@ -353,6 +657,8 @@ __NTH (gethostname (char *__buf, size_t __buflen))
}
return __gethostname_alias (__buf, __buflen);
}
+# endif
+# undef __warn_gethostname_buflen
#endif
@@ -362,12 +668,34 @@ extern int __getdomainname_chk (char *__buf, size_t __buflen, size_t __nreal)
extern int __REDIRECT_NTH (__getdomainname_alias, (char *__buf,
size_t __buflen),
getdomainname) __nonnull ((1)) __wur;
+
+# define __warn_getdomainname_buflen \
+ "getdomainname called with bigger buflen than size of destination buffer"
+
+# ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_getdomainname_buflen) int
+__NTH (getdomainname (char *const __clang_pass_object_size __buf,
+ size_t __buflen))
+ __clang_enable_if (__bos (__buf) != (size_t) -1
+ && __buflen > __bos (__buf),
+ "selected if this call looks dangerous")
+{
+ return __getdomainname_chk (__buf, __buflen, __bos (__buf));
+}
+
+__fortify_overload int
+__NTH (getdomainname (char *const __clang_pass_object_size __buf,
+ size_t __buflen))
+{
+ if (__bos (__buf) != (size_t) -1)
+ return __getdomainname_chk (__buf, __buflen, __bos (__buf));
+ return __getdomainname_alias (__buf, __buflen);
+}
+# else
extern int __REDIRECT_NTH (__getdomainname_chk_warn,
(char *__buf, size_t __buflen, size_t __nreal),
__getdomainname_chk)
- __nonnull ((1)) __wur __warnattr ("getdomainname called with bigger "
- "buflen than size of destination "
- "buffer");
+ __nonnull ((1)) __wur __warnattr (__warn_getdomainname_buflen);
__fortify_function int
__NTH (getdomainname (char *__buf, size_t __buflen))
@@ -382,4 +710,6 @@ __NTH (getdomainname (char *__buf, size_t __buflen))
}
return __getdomainname_alias (__buf, __buflen);
}
+# endif
+# undef __warn_getdomainname_buflen
#endif
--- posix/unistd.h
+++ posix/unistd.h
@@ -357,7 +357,9 @@ extern int close (int __fd);
This function is a cancellation point and therefore not marked with
__THROW. */
-extern ssize_t read (int __fd, void *__buf, size_t __nbytes) __wur;
+__fortify_overloadable
+extern ssize_t read (int __fd, void *__buf, size_t __nbytes) __wur
+ __CLANG_NO_MANGLE (read);
/* Write N bytes of BUF to FD. Return the number written, or -1.
@@ -373,8 +375,9 @@ extern ssize_t write (int __fd, const void *__buf, size_t __n) __wur;
This function is a cancellation point and therefore not marked with
__THROW. */
+__fortify_overloadable
extern ssize_t pread (int __fd, void *__buf, size_t __nbytes,
- __off_t __offset) __wur;
+ __off_t __offset) __wur __CLANG_NO_MANGLE (pread);
/* Write N bytes of BUF to FD at the given position OFFSET without
changing the file pointer. Return the number written, or -1.
@@ -385,6 +388,7 @@ extern ssize_t pwrite (int __fd, const void *__buf, size_t __n,
__off_t __offset) __wur;
# else
# ifdef __REDIRECT
+__fortify_overloadable
extern ssize_t __REDIRECT (pread, (int __fd, void *__buf, size_t __nbytes,
__off64_t __offset),
pread64) __wur;
@@ -401,8 +405,9 @@ extern ssize_t __REDIRECT (pwrite, (int __fd, const void *__buf,
/* Read NBYTES into BUF from FD at the given position OFFSET without
changing the file pointer. Return the number read, -1 for errors
or 0 for EOF. */
+__fortify_overloadable
extern ssize_t pread64 (int __fd, void *__buf, size_t __nbytes,
- __off64_t __offset) __wur;
+ __off64_t __offset) __wur __CLANG_NO_MANGLE (pread64);
/* Write N bytes of BUF to FD at the given position OFFSET without
changing the file pointer. Return the number written, or -1. */
extern ssize_t pwrite64 (int __fd, const void *__buf, size_t __n,
@@ -508,7 +513,9 @@ extern int fchdir (int __fd) __THROW __wur;
an array is allocated with `malloc'; the array is SIZE
bytes long, unless SIZE == 0, in which case it is as
big as necessary. */
-extern char *getcwd (char *__buf, size_t __size) __THROW __wur;
+__fortify_overloadable
+extern char *getcwd (char *__buf, size_t __size) __THROW __wur
+ __CLANG_NO_MANGLE (getcwd);
#ifdef __USE_GNU
/* Return a malloc'd string containing the current directory name.
@@ -522,8 +529,10 @@ extern char *get_current_dir_name (void) __THROW;
/* Put the absolute pathname of the current working directory in BUF.
If successful, return BUF. If not, put an error message in
BUF and return NULL. BUF should be at least PATH_MAX bytes long. */
+__fortify_overloadable
extern char *getwd (char *__buf)
- __THROW __nonnull ((1)) __attribute_deprecated__ __wur;
+ __THROW __nonnull ((1)) __attribute_deprecated__ __wur
+ __CLANG_NO_MANGLE (getwd);
#endif
@@ -620,7 +629,9 @@ extern long int sysconf (int __name) __THROW;
#ifdef __USE_POSIX2
/* Get the value of the string-valued system variable NAME. */
-extern size_t confstr (int __name, char *__buf, size_t __len) __THROW;
+__fortify_overloadable
+extern size_t confstr (int __name, char *__buf, size_t __len) __THROW
+ __CLANG_NO_MANGLE (confstr);
#endif
@@ -686,7 +697,9 @@ extern __gid_t getegid (void) __THROW;
/* If SIZE is zero, return the number of supplementary groups
the calling process is in. Otherwise, fill in the group IDs
of its supplementary groups in LIST and return the number written. */
-extern int getgroups (int __size, __gid_t __list[]) __THROW __wur;
+__fortify_overloadable
+extern int getgroups (int __size, __gid_t __list[]) __THROW __wur
+ __CLANG_NO_MANGLE (getgroups);
#ifdef __USE_GNU
/* Return nonzero iff the calling process is in group GID. */
@@ -767,12 +780,14 @@ extern __pid_t vfork (void) __THROW;
/* Return the pathname of the terminal FD is open on, or NULL on errors.
The returned storage is good only until the next call to this function. */
-extern char *ttyname (int __fd) __THROW;
+__fortify_overloadable
+extern char *ttyname (int __fd) __THROW __CLANG_NO_MANGLE (ttyname);
/* Store at most BUFLEN characters of the pathname of the terminal FD is
open on in BUF. Return 0 on success, otherwise an error number. */
+__fortify_overloadable
extern int ttyname_r (int __fd, char *__buf, size_t __buflen)
- __THROW __nonnull ((2)) __wur;
+ __THROW __nonnull ((2)) __wur __CLANG_NO_MANGLE (ttyname_r);
/* Return 1 if FD is a valid descriptor associated
with a terminal, zero if not. */
@@ -806,9 +821,10 @@ extern int symlink (const char *__from, const char *__to)
/* Read the contents of the symbolic link PATH into no more than
LEN bytes of BUF. The contents are not null-terminated.
Returns the number of characters read, or -1 for errors. */
+__fortify_overloadable
extern ssize_t readlink (const char *__restrict __path,
char *__restrict __buf, size_t __len)
- __THROW __nonnull ((1, 2)) __wur;
+ __THROW __nonnull ((1, 2)) __wur __CLANG_NO_MANGLE (readlink);
#endif /* Use BSD. */
#ifdef __USE_ATFILE
@@ -817,9 +833,10 @@ extern int symlinkat (const char *__from, int __tofd,
const char *__to) __THROW __nonnull ((1, 3)) __wur;
/* Like readlink but a relative PATH is interpreted relative to FD. */
+__fortify_overloadable
extern ssize_t readlinkat (int __fd, const char *__restrict __path,
char *__restrict __buf, size_t __len)
- __THROW __nonnull ((2, 3)) __wur;
+ __THROW __nonnull ((2, 3)) __wur __CLANG_NO_MANGLE (readlinkat);
#endif
/* Remove the link NAME. */
@@ -854,7 +871,9 @@ extern char *getlogin (void);
This function is a possible cancellation point and therefore not
marked with __THROW. */
-extern int getlogin_r (char *__name, size_t __name_len) __nonnull ((1));
+__fortify_overloadable
+extern int getlogin_r (char *__name, size_t __name_len) __nonnull ((1))
+ __CLANG_NO_MANGLE (getlogin_r);
#endif
#ifdef __USE_BSD
@@ -876,7 +895,9 @@ extern int setlogin (const char *__name) __THROW __nonnull ((1));
/* Put the name of the current host in no more than LEN bytes of NAME.
The result is null-terminated if LEN is large enough for the full
name and the terminator. */
-extern int gethostname (char *__name, size_t __len) __THROW __nonnull ((1));
+__fortify_overloadable
+extern int gethostname (char *__name, size_t __len) __THROW __nonnull ((1))
+ __CLANG_NO_MANGLE (gethostname);
#endif
@@ -894,8 +915,9 @@ extern int sethostid (long int __id) __THROW __wur;
/* Get and set the NIS (aka YP) domain name, if any.
Called just like `gethostname' and `sethostname'.
The NIS domain name is usually the empty string when not using NIS. */
+__fortify_overloadable
extern int getdomainname (char *__name, size_t __len)
- __THROW __nonnull ((1)) __wur;
+ __THROW __nonnull ((1)) __wur __CLANG_NO_MANGLE (getdomainname);
extern int setdomainname (const char *__name, size_t __len)
__THROW __nonnull ((1)) __wur;
--- rt/bits/mqueue2.h
+++ rt/bits/mqueue2.h
@@ -22,17 +22,60 @@
/* Check that calls to mq_open with O_CREAT set have an appropriate third and fourth
parameter. */
+__fortify_overloadable
extern mqd_t mq_open (const char *__name, int __oflag, ...)
- __THROW __nonnull ((1));
+ __THROW __nonnull ((1)) __CLANG_NO_MANGLE (mq_open);
extern mqd_t __mq_open_2 (const char *__name, int __oflag)
__THROW __nonnull ((1));
extern mqd_t __REDIRECT_NTH (__mq_open_alias, (const char *__name,
int __oflag, ...), mq_open)
__nonnull ((1));
+
+#define __warn_mq_open_wrong_number_of_args "mq_open can be called either " \
+ "with 2 or 4 arguments"
+#define __warn_mq_open_missing_mode_and_attr "mq_open with O_CREAT in second " \
+ "argument needs 4 arguments"
+#ifdef __use_clang_fortify
+__fortify_overload __clang_prefer_this_overload
+__clang_error (__warn_mq_open_missing_mode_and_attr) mqd_t
+__NTH (mq_open (const char *__name, int __oflag))
+ __clang_enable_if ((__oflag & O_CREAT),
+ "selected if mq_open is given O_CREAT, but no mode or attr")
+{
+ return __mq_open_alias (__name, __oflag);
+}
+
+__fortify_overload __clang_error (__warn_mq_open_wrong_number_of_args) mqd_t
+__NTH (mq_open (const char *__name, int __oflag, int __mode))
+{
+ return __mq_open_alias (__name, __oflag, __mode);
+}
+
+__fortify_overload __clang_error (__warn_mq_open_wrong_number_of_args)
+mqd_t
+__NTH (mq_open (const char *__name, int __oflag, int __mode,
+ struct mq_attr *__attr, ...))
+{
+ return __mq_open_alias (__name, __oflag, __mode, __attr);
+}
+
+__fortify_overload __clang_prefer_this_overload mqd_t
+__NTH (mq_open (const char *__name, int __oflag))
+{
+ return __mq_open_alias (__name, __oflag);
+}
+
+__fortify_overload __clang_prefer_this_overload mqd_t
+__NTH (mq_open (const char *__name, int __oflag, int __mode,
+ struct mq_attr *__attr))
+{
+ return __mq_open_alias (__name, __oflag, __mode, __attr);
+}
+#else
__errordecl (__mq_open_wrong_number_of_args,
- "mq_open can be called either with 2 or 4 arguments");
+ __warn_mq_open_wrong_number_of_args);
__errordecl (__mq_open_missing_mode_and_attr,
- "mq_open with O_CREAT in second argument needs 4 arguments");
+ __warn_mq_open_missing_mode_and_attr);
__fortify_function mqd_t
__NTH (mq_open (const char *__name, int __oflag, ...))
@@ -55,3 +98,6 @@ __NTH (mq_open (const char *__name, int __oflag, ...))
return __mq_open_alias (__name, __oflag, __va_arg_pack ());
}
+#endif
+#undef __warn_mq_open_wrong_number_of_args
+#undef __warn_mq_open_missing_mode_and_attr
--- rt/mqueue.h
+++ rt/mqueue.h
@@ -37,8 +37,9 @@ __BEGIN_DECLS
argument is taken as `struct mq_attr *', pointer to message queue
attributes. If the fourth argument is NULL, default attributes are
used. */
+__fortify_overloadable
extern mqd_t mq_open (const char *__name, int __oflag, ...)
- __THROW __nonnull ((1));
+ __THROW __nonnull ((1)) __CLANG_NO_MANGLE (mq_open);
/* Removes the association between message queue descriptor MQDES and its
message queue. */
@@ -91,7 +92,7 @@ extern int mq_timedsend (mqd_t __mqdes, const char *__msg_ptr,
/* Define some inlines helping to catch common problems. */
#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function \
- && defined __va_arg_pack_len
+ && (defined __va_arg_pack_len || defined __use_clang_fortify)
# include <bits/mqueue2.h>
#endif
--- socket/bits/socket2.h
+++ socket/bits/socket2.h
@@ -24,11 +24,32 @@ extern ssize_t __recv_chk (int __fd, void *__buf, size_t __n, size_t __buflen,
int __flags);
extern ssize_t __REDIRECT (__recv_alias, (int __fd, void *__buf, size_t __n,
int __flags), recv);
+
+#define __warn_recv_buflen "recv called with bigger length than size of " \
+ "destination buffer"
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_recv_buflen) ssize_t
+recv (int __fd, void *const __clang_pass_object_size0 __buf, size_t __n,
+ int __flags)
+ __clang_enable_if (__bos0 (__buf) != (size_t) -1 && __bos0 (__buf) < __n,
+ "selected if this call looks dangerous")
+{
+ return __recv_chk (__fd, __buf, __n, __bos0 (__buf), __flags);
+}
+
+__fortify_overload ssize_t
+recv (int __fd, void *const __clang_pass_object_size0 __buf, size_t __n,
+ int __flags)
+{
+ if (__bos0 (__buf) != (size_t) -1)
+ return __recv_chk (__fd, __buf, __n, __bos0 (__buf), __flags);
+ return __recv_alias (__fd, __buf, __n, __flags);
+}
+#else
extern ssize_t __REDIRECT (__recv_chk_warn,
(int __fd, void *__buf, size_t __n, size_t __buflen,
int __flags), __recv_chk)
- __warnattr ("recv called with bigger length than size of destination "
- "buffer");
+ __warnattr (__warn_recv_buflen);
__fortify_function ssize_t
recv (int __fd, void *__buf, size_t __n, int __flags)
@@ -43,6 +64,8 @@ recv (int __fd, void *__buf, size_t __n, int __flags)
}
return __recv_alias (__fd, __buf, __n, __flags);
}
+#endif
+#undef __warn_recv_buflen
extern ssize_t __recvfrom_chk (int __fd, void *__restrict __buf, size_t __n,
size_t __buflen, int __flags,
@@ -52,13 +75,38 @@ extern ssize_t __REDIRECT (__recvfrom_alias,
(int __fd, void *__restrict __buf, size_t __n,
int __flags, __SOCKADDR_ARG __addr,
socklen_t *__restrict __addr_len), recvfrom);
+
+#define __warn_recvfrom_buflen "recvfrom called with bigger length than size " \
+ "of destination buffer"
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_recvfrom_buflen) ssize_t
+recvfrom (int __fd, void *__restrict const __clang_pass_object_size0 __buf,
+ size_t __n, int __flags, __SOCKADDR_ARG __addr,
+ socklen_t *__restrict __addr_len)
+ __clang_enable_if (__bos0 (__buf) != (size_t) -1 && __bos0 (__buf) < __n,
+ "selected if this call looks dangerous")
+{
+ return __recvfrom_chk (__fd, __buf, __n, __bos0 (__buf), __flags,
+ __addr, __addr_len);
+}
+
+__fortify_overload ssize_t
+recvfrom (int __fd, void *__restrict const __clang_pass_object_size0 __buf,
+ size_t __n, int __flags, __SOCKADDR_ARG __addr,
+ socklen_t *__restrict __addr_len)
+{
+ if (__bos0 (__buf) != (size_t) -1)
+ return __recvfrom_chk (__fd, __buf, __n, __bos0 (__buf), __flags,
+ __addr, __addr_len);
+ return __recvfrom_alias (__fd, __buf, __n, __flags, __addr, __addr_len);
+}
+#else
extern ssize_t __REDIRECT (__recvfrom_chk_warn,
(int __fd, void *__restrict __buf, size_t __n,
size_t __buflen, int __flags,
__SOCKADDR_ARG __addr,
socklen_t *__restrict __addr_len), __recvfrom_chk)
- __warnattr ("recvfrom called with bigger length than size of "
- "destination buffer");
+ __warnattr (__warn_recvfrom_buflen);
__fortify_function ssize_t
recvfrom (int __fd, void *__restrict __buf, size_t __n, int __flags,
@@ -75,3 +123,6 @@ recvfrom (int __fd, void *__restrict __buf, size_t __n, int __flags,
}
return __recvfrom_alias (__fd, __buf, __n, __flags, __addr, __addr_len);
}
+#endif
+#undef __warn_recvfrom_buflen
+
--- socket/sys/socket.h
+++ socket/sys/socket.h
@@ -153,7 +153,9 @@ extern ssize_t send (int __fd, const void *__buf, size_t __n, int __flags);
This function is a cancellation point and therefore not marked with
__THROW. */
-extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags);
+__fortify_overloadable
+extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags)
+ __CLANG_NO_MANGLE (recv);
/* Send N bytes of BUF on socket FD to peer at address ADDR (which is
ADDR_LEN bytes long). Returns the number sent, or -1 for errors.
@@ -171,9 +173,11 @@ extern ssize_t sendto (int __fd, const void *__buf, size_t __n,
This function is a cancellation point and therefore not marked with
__THROW. */
+__fortify_overloadable
extern ssize_t recvfrom (int __fd, void *__restrict __buf, size_t __n,
int __flags, __SOCKADDR_ARG __addr,
- socklen_t *__restrict __addr_len);
+ socklen_t *__restrict __addr_len)
+ __CLANG_NO_MANGLE (recvfrom);
/* Send a message described MESSAGE on socket FD.
--- stdlib/bits/stdlib.h
+++ stdlib/bits/stdlib.h
@@ -26,27 +26,55 @@ extern char *__realpath_chk (const char *__restrict __name,
extern char *__REDIRECT_NTH (__realpath_alias,
(const char *__restrict __name,
char *__restrict __resolved), realpath) __wur;
+
+#define __warn_realpath_arg_too_small \
+ "second argument of realpath must be either NULL or at least PATH_MAX " \
+ "bytes long buffer"
+#ifdef __use_clang_fortify
+# if defined _LIBC_LIMITS_H_ && defined PATH_MAX
+__fortify_overload __wur __clang_warning (__warn_realpath_arg_too_small) char *
+__NTH (realpath (const char *__restrict __name,
+ char *__restrict const __clang_pass_object_size __resolved))
+ __clang_enable_if (__bos (__resolved) != (size_t) -1, "")
+ __clang_enable_if (__bos (__resolved) < PATH_MAX,
+ "selected if this call looks dangerous")
+{
+ return __realpath_chk (__name, __resolved, __bos (__resolved));
+}
+# endif
+__fortify_overload __wur char *
+__NTH (realpath (const char *__restrict __name,
+ char *__restrict const __clang_pass_object_size __resolved))
+ __clang_enable_if (__bos (__resolved) != (size_t) -1,
+ "selected if this call looks dangerous")
+{
+ if (__bos (__resolved) != (size_t) -1)
+ return __realpath_chk (__name, __resolved, __bos (__resolved));
+ return __realpath_alias (__name, __resolved);
+}
+#else
extern char *__REDIRECT_NTH (__realpath_chk_warn,
(const char *__restrict __name,
char *__restrict __resolved,
size_t __resolvedlen), __realpath_chk) __wur
- __warnattr ("second argument of realpath must be either NULL or at "
- "least PATH_MAX bytes long buffer");
+ __warnattr (__warn_realpath_arg_too_small);
__fortify_function __wur char *
__NTH (realpath (const char *__restrict __name, char *__restrict __resolved))
{
if (__bos (__resolved) != (size_t) -1)
{
-#if defined _LIBC_LIMITS_H_ && defined PATH_MAX
+# if defined _LIBC_LIMITS_H_ && defined PATH_MAX
if (__bos (__resolved) < PATH_MAX)
return __realpath_chk_warn (__name, __resolved, __bos (__resolved));
-#endif
+# endif
return __realpath_chk (__name, __resolved, __bos (__resolved));
}
return __realpath_alias (__name, __resolved);
}
+#endif
+#undef __warn_realpath_arg_too_small
extern int __ptsname_r_chk (int __fd, char *__buf, size_t __buflen,
@@ -54,11 +82,34 @@ extern int __ptsname_r_chk (int __fd, char *__buf, size_t __buflen,
extern int __REDIRECT_NTH (__ptsname_r_alias, (int __fd, char *__buf,
size_t __buflen), ptsname_r)
__nonnull ((2));
+
+#define __warn_ptsname_r_arg_too_small "ptsname_r called with buflen bigger " \
+ "than size of buf"
+
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_ptsname_r_arg_too_small) int
+__NTH (ptsname_r (int __fd, char *const __clang_pass_object_size __buf,
+ size_t __buflen))
+ __clang_enable_if (__bos (__buf) != (size_t) -1
+ && __buflen > __bos (__buf),
+ "selected if this call looks dangerous")
+{
+ return __ptsname_r_chk (__fd, __buf, __buflen, __bos (__buf));
+}
+
+__fortify_overload int
+__NTH (ptsname_r (int __fd, char *const __clang_pass_object_size __buf,
+ size_t __buflen))
+{
+ if (__bos (__buf) != (size_t) -1)
+ return __ptsname_r_chk (__fd, __buf, __buflen, __bos (__buf));
+ return __ptsname_r_alias (__fd, __buf, __buflen);
+}
+#else
extern int __REDIRECT_NTH (__ptsname_r_chk_warn,
(int __fd, char *__buf, size_t __buflen,
size_t __nreal), __ptsname_r_chk)
- __nonnull ((2)) __warnattr ("ptsname_r called with buflen bigger than "
- "size of buf");
+ __nonnull ((2)) __warnattr (__warn_ptsname_r_arg_too_small);
__fortify_function int
__NTH (ptsname_r (int __fd, char *__buf, size_t __buflen))
@@ -72,6 +123,8 @@ __NTH (ptsname_r (int __fd, char *__buf, size_t __buflen))
}
return __ptsname_r_alias (__fd, __buf, __buflen);
}
+#endif
+#undef __warn_ptsname_r_arg_too_small
extern int __wctomb_chk (char *__s, wchar_t __wchar, size_t __buflen)
@@ -79,8 +132,8 @@ extern int __wctomb_chk (char *__s, wchar_t __wchar, size_t __buflen)
extern int __REDIRECT_NTH (__wctomb_alias, (char *__s, wchar_t __wchar),
wctomb) __wur;
-__fortify_function __wur int
-__NTH (wctomb (char *__s, wchar_t __wchar))
+__fortify_potential_overload __wur int
+__NTH (wctomb (char *const __clang_pass_object_size __s, wchar_t __wchar))
{
/* We would have to include <limits.h> to get a definition of MB_LEN_MAX.
But this would only disturb the namespace. So we define our own
@@ -102,12 +155,35 @@ extern size_t __REDIRECT_NTH (__mbstowcs_alias,
(wchar_t *__restrict __dst,
const char *__restrict __src,
size_t __len), mbstowcs);
+
+#define __warn_mbstowcs_too_small_dst \
+ "mbstowcs called with dst buffer smaller than len * sizeof (wchar_t)"
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_mbstowcs_too_small_dst) size_t
+__NTH (mbstowcs (wchar_t *__restrict const __clang_pass_object_size __dst,
+ const char *__restrict __src, size_t __len))
+ __clang_enable_if (__bos (__dst) != (size_t) -1
+ && __len > __bos (__dst) / sizeof (wchar_t),
+ "selected if this call looks dangerous")
+{
+ return __mbstowcs_chk (__dst, __src, __len, __bos (__dst) / sizeof (wchar_t));
+}
+
+__fortify_overload size_t
+__NTH (mbstowcs (wchar_t *__restrict const __clang_pass_object_size __dst,
+ const char *__restrict __src, size_t __len))
+{
+ if (__bos (__dst) != (size_t) -1)
+ return __mbstowcs_chk (__dst, __src, __len,
+ __bos (__dst) / sizeof (wchar_t));
+ return __mbstowcs_alias (__dst, __src, __len);
+}
+#else
extern size_t __REDIRECT_NTH (__mbstowcs_chk_warn,
(wchar_t *__restrict __dst,
const char *__restrict __src,
size_t __len, size_t __dstlen), __mbstowcs_chk)
- __warnattr ("mbstowcs called with dst buffer smaller than len "
- "* sizeof (wchar_t)");
+ __warnattr (__warn_mbstowcs_too_small_dst);
__fortify_function size_t
__NTH (mbstowcs (wchar_t *__restrict __dst, const char *__restrict __src,
@@ -125,6 +201,8 @@ __NTH (mbstowcs (wchar_t *__restrict __dst, const char *__restrict __src,
}
return __mbstowcs_alias (__dst, __src, __len);
}
+#endif
+#undef __warn_mbstowcs_too_small_dst
extern size_t __wcstombs_chk (char *__restrict __dst,
@@ -134,11 +212,33 @@ extern size_t __REDIRECT_NTH (__wcstombs_alias,
(char *__restrict __dst,
const wchar_t *__restrict __src,
size_t __len), wcstombs);
+
+#define __warn_wcstombs_dst_too_small \
+ "wcstombs called with dst buffer smaller than len"
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_wcstombs_dst_too_small) size_t
+__NTH (wcstombs (char *__restrict const __clang_pass_object_size __dst,
+ const wchar_t *__restrict __src, size_t __len))
+ __clang_enable_if (__bos (__dst) != (size_t) -1 && __len > __bos (__dst),
+ "selected if this call looks dangerous")
+{
+ return __wcstombs_chk (__dst, __src, __len, __bos (__dst));
+}
+
+__fortify_overload size_t
+__NTH (wcstombs (char *__restrict const __clang_pass_object_size __dst,
+ const wchar_t *__restrict __src, size_t __len))
+{
+ if (__bos (__dst) != (size_t) -1)
+ return __wcstombs_chk (__dst, __src, __len, __bos (__dst));
+ return __wcstombs_alias (__dst, __src, __len);
+}
+#else
extern size_t __REDIRECT_NTH (__wcstombs_chk_warn,
(char *__restrict __dst,
const wchar_t *__restrict __src,
size_t __len, size_t __dstlen), __wcstombs_chk)
- __warnattr ("wcstombs called with dst buffer smaller than len");
+ __warnattr (__warn_wcstombs_dst_too_small);
__fortify_function size_t
__NTH (wcstombs (char *__restrict __dst, const wchar_t *__restrict __src,
@@ -153,3 +253,5 @@ __NTH (wcstombs (char *__restrict __dst, const wchar_t *__restrict __src,
}
return __wcstombs_alias (__dst, __src, __len);
}
+#endif
+#undef __warn_wcstombs_dst_too_small
--- stdlib/stdlib.h
+++ stdlib/stdlib.h
@@ -731,8 +731,10 @@ extern char *canonicalize_file_name (const char *__name)
PATH_MAX chars or more, returns null with `errno' set to
ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
returns the name in RESOLVED. */
+__fortify_overloadable
extern char *realpath (const char *__restrict __name,
- char *__restrict __resolved) __THROW __wur;
+ char *__restrict __resolved) __THROW __wur
+ __CLANG_NO_MANGLE (realpath);
#endif
@@ -867,16 +869,21 @@ extern int mbtowc (wchar_t *__restrict __pwc,
const char *__restrict __s, size_t __n) __THROW;
/* Put the multibyte character represented
by WCHAR in S, returning its length. */
-extern int wctomb (char *__s, wchar_t __wchar) __THROW;
+__fortify_overloadable
+extern int wctomb (char *__s, wchar_t __wchar) __THROW
+ __CLANG_NO_MANGLE (wctomb);
/* Convert a multibyte string to a wide char string. */
+__fortify_overloadable
extern size_t mbstowcs (wchar_t *__restrict __pwcs,
- const char *__restrict __s, size_t __n) __THROW;
+ const char *__restrict __s, size_t __n)
+ __THROW __CLANG_NO_MANGLE (mbstowcs);
/* Convert a wide char string to multibyte string. */
+__fortify_overloadable
extern size_t wcstombs (char *__restrict __s,
const wchar_t *__restrict __pwcs, size_t __n)
- __THROW;
+ __THROW __CLANG_NO_MANGLE (wcstombs);
__END_NAMESPACE_STD
@@ -937,8 +944,9 @@ extern char *ptsname (int __fd) __THROW __wur;
/* Store at most BUFLEN characters of the pathname of the slave pseudo
terminal associated with the master FD is open on in BUF.
Return 0 on success, otherwise an error number. */
+__fortify_overloadable
extern int ptsname_r (int __fd, char *__buf, size_t __buflen)
- __THROW __nonnull ((2));
+ __THROW __nonnull ((2)) __CLANG_NO_MANGLE (ptsname_r);
/* Open a master pseudo terminal and return its file descriptor. */
extern int getpt (void);
--- string/bits/string3.h
+++ string/bits/string3.h
@@ -19,9 +19,6 @@
# error "Never use <bits/string3.h> directly; include <string.h> instead."
#endif
-__warndecl (__warn_memset_zero_len,
- "memset used with constant zero length parameter; this could be due to transposed parameters");
-
#ifndef __cplusplus
/* XXX This is temporarily. We should not redefine any of the symbols
and instead integrate the error checking into the original
@@ -43,30 +40,130 @@ __warndecl (__warn_memset_zero_len,
# endif
#endif
+#ifdef __use_clang_fortify
+# define __warn_len_too_large \
+ "called with bigger length than the destination buffer"
+# define __enable_if_dest_too_small_impl(dest, len, bos) \
+ __clang_enable_if (bos (dest) != (size_t) -1 && bos (dest) < len, \
+ "selected if this call looks dangerous")
+# define __enable_if_dest_too_small0(dest, len) \
+ __enable_if_dest_too_small_impl(dest, len, __bos0)
+# define __enable_if_dest_too_small(dest, len) \
+ __enable_if_dest_too_small_impl(dest, len, __bos)
+
+# define __warn_input_str_too_large \
+ "destination buffer will always be overflown by source"
+# define __enable_if_src_too_large(dest, src) \
+ __clang_enable_if (__bos (dest) != (size_t) -1 \
+ && __bos (dest) <= __builtin_strlen(src), \
+ "enabled if this call looks dangerous")
+#endif
+
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_len_too_large) void *
+__NTH (memcpy (void *__restrict const __clang_pass_object_size0 __dest,
+ const void *__restrict __src, size_t __len))
+ __enable_if_dest_too_small0 (__dest, __len)
+{
+ return __builtin___memcpy_chk (__dest, __src, __len, __bos0 (__dest));
+}
+__fortify_overload void *
+__NTH (memcpy (void *__restrict const __clang_pass_object_size0 __dest,
+ const void *__restrict __src, size_t __len))
+{
+ return __builtin___memcpy_chk (__dest, __src, __len, __bos0 (__dest));
+}
+#else
__fortify_function void *
__NTH (memcpy (void *__restrict __dest, const void *__restrict __src,
size_t __len))
{
return __builtin___memcpy_chk (__dest, __src, __len, __bos0 (__dest));
}
+#endif
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_len_too_large) void *
+__NTH (memmove (void *const __clang_pass_object_size0 __dest,
+ const void *__src, size_t __len))
+ __enable_if_dest_too_small0 (__dest, __len)
+{
+ return __builtin___memmove_chk (__dest, __src, __len, __bos0 (__dest));
+}
+
+__fortify_overload void *
+__NTH (memmove (void *const __clang_pass_object_size0 __dest,
+ const void *__src, size_t __len))
+{
+ return __builtin___memmove_chk (__dest, __src, __len, __bos0 (__dest));
+}
+#else
__fortify_function void *
__NTH (memmove (void *__dest, const void *__src, size_t __len))
{
return __builtin___memmove_chk (__dest, __src, __len, __bos0 (__dest));
}
+#endif
#ifdef __USE_GNU
+# ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_len_too_large) void *
+__NTH (mempcpy (void *__restrict const __clang_pass_object_size0 __dest,
+ const void *__restrict __src, size_t __len))
+ __enable_if_dest_too_small0 (__dest, __len)
+{
+ return __builtin___mempcpy_chk (__dest, __src, __len, __bos0 (__dest));
+}
+
+__fortify_overload void *
+__NTH (mempcpy (void *__restrict const __clang_pass_object_size0 __dest,
+ const void *__restrict __src, size_t __len))
+{
+ return __builtin___mempcpy_chk (__dest, __src, __len, __bos0 (__dest));
+}
+# else
__fortify_function void *
__NTH (mempcpy (void *__restrict __dest, const void *__restrict __src,
size_t __len))
{
return __builtin___mempcpy_chk (__dest, __src, __len, __bos0 (__dest));
}
+# endif
#endif
+#define __warn_memset_zero_len_msg \
+ "memset used with constant zero length parameter; this could be due to " \
+ "transposed parameters"
+
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_len_too_large) void *
+__NTH (memset (void *__dest, int __ch, size_t __len))
+ __enable_if_dest_too_small0 (__dest, __len)
+{
+ return __dest;
+}
+
+/* If the second and third parameter look like they're transposed, be sure to
+ emit a warning. */
+__fortify_overload __clang_warning (__warn_memset_zero_len_msg) void *
+__NTH (memset (void *__dest, int __ch, size_t __len))
+ __clang_enable_if (__len == 0 && __ch != 0,
+ "called if __len/__ch seem to be flipped")
+{
+ return __dest;
+}
+
+__fortify_overload void *
+__NTH (memset (void *const __clang_pass_object_size0 __dest, int __ch,
+ size_t __len))
+{
+ return __builtin___memset_chk (__dest, __ch, __len, __bos0 (__dest));
+}
+#else
+__warndecl (__warn_memset_zero_len, __warn_memset_zero_len_msg);
+
/* The first two tests here help to catch a somewhat common problem
where the second and third parameter are transposed. This is
especially problematic if the intended fill value is zero. In this
@@ -83,42 +180,129 @@ __NTH (memset (void *__dest, int __ch, size_t __len))
}
return __builtin___memset_chk (__dest, __ch, __len, __bos0 (__dest));
}
+#endif
+#undef __warn_memset_zero_len_msg
#ifdef __USE_BSD
+# ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_len_too_large) void
+__NTH (bcopy (const void *__src, void *const __clang_pass_object_size0 __dest,
+ size_t __len))
+ __enable_if_dest_too_small0 (__dest, __len)
+{
+ (void) __builtin___memmove_chk (__dest, __src, __len, __bos0 (__dest));
+}
+
+__fortify_overload void
+__NTH (bcopy (const void *__src, void *const __clang_pass_object_size0 __dest,
+ size_t __len))
+{
+ (void) __builtin___memmove_chk (__dest, __src, __len, __bos0 (__dest));
+}
+# else
__fortify_function void
__NTH (bcopy (const void *__src, void *__dest, size_t __len))
{
(void) __builtin___memmove_chk (__dest, __src, __len, __bos0 (__dest));
}
+# endif
+
+# ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_len_too_large) void
+__NTH (bzero (void *const __clang_pass_object_size0 __dest, size_t __len))
+ __enable_if_dest_too_small0 (__dest, __len)
+{
+ (void) __builtin___memset_chk (__dest, '\0', __len, __bos0 (__dest));
+}
+__fortify_overload void
+__NTH (bzero (void *const __clang_pass_object_size0 __dest, size_t __len))
+{
+ (void) __builtin___memset_chk (__dest, '\0', __len, __bos0 (__dest));
+}
+# else
__fortify_function void
__NTH (bzero (void *__dest, size_t __len))
{
(void) __builtin___memset_chk (__dest, '\0', __len, __bos0 (__dest));
}
+# endif
#endif
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_input_str_too_large) char *
+__NTH (strcpy (char *__restrict const __clang_pass_object_size __dest,
+ const char *__restrict __src))
+ __enable_if_src_too_large (__dest, __src)
+{
+ return __builtin___strcpy_chk (__dest, __src, __bos (__dest));
+}
+
+__fortify_overload char *
+__NTH (strcpy (char *__restrict const __clang_pass_object_size __dest,
+ const char *__restrict __src))
+{
+ return __builtin___strcpy_chk (__dest, __src, __bos (__dest));
+}
+#else
__fortify_function char *
__NTH (strcpy (char *__restrict __dest, const char *__restrict __src))
{
return __builtin___strcpy_chk (__dest, __src, __bos (__dest));
}
+#endif
#ifdef __USE_GNU
+# ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_input_str_too_large) char *
+__NTH (stpcpy (char *__restrict const __clang_pass_object_size __dest,
+ const char *__restrict __src))
+ __enable_if_src_too_large (__dest, __src)
+{
+ return __builtin___stpcpy_chk (__dest, __src, __bos (__dest));
+}
+
+__fortify_overload char *
+__NTH (stpcpy (char *__restrict const __clang_pass_object_size __dest,
+ const char *__restrict __src))
+{
+ return __builtin___stpcpy_chk (__dest, __src, __bos (__dest));
+}
+# else
__fortify_function char *
__NTH (stpcpy (char *__restrict __dest, const char *__restrict __src))
{
return __builtin___stpcpy_chk (__dest, __src, __bos (__dest));
}
+# endif
#endif
+#ifdef __use_clang_fortify
+/* We explicitly don't include checks for when __builtin_strlen (__src) is
+ provably less than __bos (__dest), but __len > __bos (__dest). In those
+ cases, the user should just fix their code. */
+__fortify_overload __clang_warning (__warn_len_too_large) char *
+__NTH (strncpy (char *__restrict const __clang_pass_object_size __dest,
+ const char *__restrict __src, size_t __len))
+ __enable_if_dest_too_small (__dest, __len)
+{
+ return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
+}
+__fortify_overload char *
+__NTH (strncpy (char *__restrict const __clang_pass_object_size __dest,
+ const char *__restrict __src, size_t __len))
+{
+ return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
+}
+#else
__fortify_function char *
__NTH (strncpy (char *__restrict __dest, const char *__restrict __src,
size_t __len))
{
return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
}
+#endif
// XXX We have no corresponding builtin yet.
extern char *__stpncpy_chk (char *__dest, const char *__src, size_t __n,
@@ -126,6 +310,24 @@ extern char *__stpncpy_chk (char *__dest, const char *__src, size_t __n,
extern char *__REDIRECT_NTH (__stpncpy_alias, (char *__dest, const char *__src,
size_t __n), stpncpy);
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_len_too_large) char *
+__NTH (stpncpy (char *const __clang_pass_object_size __dest, const char *__src,
+ size_t __n))
+ __enable_if_dest_too_small (__dest, __n)
+{
+ return __stpncpy_chk (__dest, __src, __n, __bos (__dest));
+}
+
+__fortify_overload char *
+__NTH (stpncpy (char *const __clang_pass_object_size __dest, const char *__src,
+ size_t __n))
+{
+ if (__bos (__dest) != (size_t) -1)
+ return __stpncpy_chk (__dest, __src, __n, __bos (__dest));
+ return __stpncpy_alias (__dest, __src, __n);
+}
+#else
__fortify_function char *
__NTH (stpncpy (char *__dest, const char *__src, size_t __n))
{
@@ -134,18 +336,61 @@ __NTH (stpncpy (char *__dest, const char *__src, size_t __n))
return __stpncpy_chk (__dest, __src, __n, __bos (__dest));
return __stpncpy_alias (__dest, __src, __n);
}
+#endif
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_input_str_too_large) char *
+__NTH (strcat (char *__restrict const __clang_pass_object_size __dest,
+ const char *__restrict __src))
+ __enable_if_src_too_large (__dest, __src)
+{
+ return __builtin___strcat_chk (__dest, __src, __bos (__dest));
+}
+__fortify_overload char *
+__NTH (strcat (char *__restrict const __clang_pass_object_size __dest,
+ const char *__restrict __src))
+{
+ return __builtin___strcat_chk (__dest, __src, __bos (__dest));
+}
+#else
__fortify_function char *
__NTH (strcat (char *__restrict __dest, const char *__restrict __src))
{
return __builtin___strcat_chk (__dest, __src, __bos (__dest));
}
+#endif
+
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_len_too_large) char *
+__NTH (strncat (char *__restrict const __clang_pass_object_size __dest,
+ const char *__restrict __src, size_t __len))
+ __enable_if_dest_too_small (__dest, __len)
+{
+ return __builtin___strncat_chk (__dest, __src, __len, __bos (__dest));
+}
+__fortify_overload char *
+__NTH (strncat (char *__restrict const __clang_pass_object_size __dest,
+ const char *__restrict __src, size_t __len))
+{
+ return __builtin___strncat_chk (__dest, __src, __len, __bos (__dest));
+}
+#else
__fortify_function char *
__NTH (strncat (char *__restrict __dest, const char *__restrict __src,
size_t __len))
{
return __builtin___strncat_chk (__dest, __src, __len, __bos (__dest));
}
+#endif
+
+#ifdef __use_clang_fortify
+# undef __warn_len_too_large
+# undef __enable_if_dest_too_small_impl
+# undef __enable_if_dest_too_small0
+# undef __enable_if_dest_too_small
+# undef __warn_input_str_too_large
+# undef __enable_if_src_too_large
+#endif
--- string/string.h
+++ string/string.h
@@ -43,12 +43,15 @@ __BEGIN_DECLS
__BEGIN_NAMESPACE_STD
/* Copy N bytes of SRC to DEST. */
+__fortify_overloadable
extern void *memcpy (void *__restrict __dest, const void *__restrict __src,
- size_t __n) __THROW __nonnull ((1, 2));
+ size_t __n)
+ __THROW __nonnull ((1, 2)) __CLANG_NO_MANGLE (memcpy);
/* Copy N bytes of SRC to DEST, guaranteeing
correct behavior for overlapping strings. */
+__fortify_overloadable
extern void *memmove (void *__dest, const void *__src, size_t __n)
- __THROW __nonnull ((1, 2));
+ __THROW __nonnull ((1, 2)) __CLANG_NO_MANGLE (memmove);
__END_NAMESPACE_STD
/* Copy no more than N bytes of SRC to DEST, stopping when C is found.
@@ -63,11 +66,14 @@ extern void *memccpy (void *__restrict __dest, const void *__restrict __src,
__BEGIN_NAMESPACE_STD
/* Set N bytes of S to C. */
-extern void *memset (void *__s, int __c, size_t __n) __THROW __nonnull ((1));
+__fortify_overloadable
+extern void *memset (void *__s, int __c, size_t __n)
+ __THROW __nonnull ((1)) __CLANG_NO_MANGLE (memset);
/* Compare N bytes of S1 and S2. */
+__fortify_overloadable
extern int memcmp (const void *__s1, const void *__s2, size_t __n)
- __THROW __attribute_pure__ __nonnull ((1, 2));
+ __THROW __attribute_pure__ __nonnull ((1, 2)) __CLANG_NO_MANGLE (memcmp);
/* Search N bytes of S for C. */
#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
@@ -126,19 +132,24 @@ extern void *memrchr (const void *__s, int __c, size_t __n)
__BEGIN_NAMESPACE_STD
/* Copy SRC to DEST. */
+__fortify_overloadable
extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
- __THROW __nonnull ((1, 2));
+ __THROW __nonnull ((1, 2)) __CLANG_NO_MANGLE (strcpy);
/* Copy no more than N characters of SRC to DEST. */
+__fortify_overloadable
extern char *strncpy (char *__restrict __dest,
const char *__restrict __src, size_t __n)
- __THROW __nonnull ((1, 2));
+ __THROW __nonnull ((1, 2)) __CLANG_NO_MANGLE (strncpy);
/* Append SRC onto DEST. */
+__fortify_overloadable
extern char *strcat (char *__restrict __dest, const char *__restrict __src)
- __THROW __nonnull ((1, 2));
+ __THROW __nonnull ((1, 2)) __CLANG_NO_MANGLE (strcat);
/* Append no more than N characters from SRC onto DEST. */
+__fortify_overloadable
extern char *strncat (char *__restrict __dest, const char *__restrict __src,
- size_t __n) __THROW __nonnull ((1, 2));
+ size_t __n)
+ __THROW __nonnull ((1, 2)) __CLANG_NO_MANGLE (strncat);
/* Compare S1 and S2. */
extern int strcmp (const char *__s1, const char *__s2)
@@ -388,9 +399,11 @@ extern void *memmem (const void *__haystack, size_t __haystacklen,
extern void *__mempcpy (void *__restrict __dest,
const void *__restrict __src, size_t __n)
__THROW __nonnull ((1, 2));
+
+__fortify_overloadable
extern void *mempcpy (void *__restrict __dest,
const void *__restrict __src, size_t __n)
- __THROW __nonnull ((1, 2));
+ __THROW __nonnull ((1, 2)) __CLANG_NO_MANGLE (mempcpy);
#endif
@@ -452,11 +465,14 @@ extern void __bzero (void *__s, size_t __n) __THROW __nonnull ((1));
#ifdef __USE_BSD
/* Copy N bytes of SRC to DEST (like memmove, but args reversed). */
+__fortify_overloadable
extern void bcopy (const void *__src, void *__dest, size_t __n)
- __THROW __nonnull ((1, 2));
+ __THROW __nonnull ((1, 2)) __CLANG_NO_MANGLE (bcopy);
/* Set N bytes of S to 0. */
-extern void bzero (void *__s, size_t __n) __THROW __nonnull ((1));
+__fortify_overloadable
+extern void bzero (void *__s, size_t __n)
+ __THROW __nonnull ((1)) __CLANG_NO_MANGLE (bzero);
/* Compare N bytes of S1 and S2 (same as memcmp). */
extern int bcmp (const void *__s1, const void *__s2, size_t __n)
@@ -566,17 +582,20 @@ extern char *strsignal (int __sig) __THROW;
/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */
extern char *__stpcpy (char *__restrict __dest, const char *__restrict __src)
__THROW __nonnull ((1, 2));
+__fortify_overloadable
extern char *stpcpy (char *__restrict __dest, const char *__restrict __src)
- __THROW __nonnull ((1, 2));
+ __THROW __nonnull ((1, 2)) __CLANG_NO_MANGLE (stpcpy);
/* Copy no more than N characters of SRC to DEST, returning the address of
the last character written into DEST. */
+__fortify_overloadable
extern char *__stpncpy (char *__restrict __dest,
const char *__restrict __src, size_t __n)
- __THROW __nonnull ((1, 2));
+ __THROW __nonnull ((1, 2)) __CLANG_NO_MANGLE (__stpncpy);
+__fortify_overloadable
extern char *stpncpy (char *__restrict __dest,
const char *__restrict __src, size_t __n)
- __THROW __nonnull ((1, 2));
+ __THROW __nonnull ((1, 2)) __CLANG_NO_MANGLE (stpncpy);
#endif
#ifdef __USE_GNU
--- wcsmbs/bits/wchar2.h
+++ wcsmbs/bits/wchar2.h
@@ -28,12 +28,34 @@ extern wchar_t *__REDIRECT_NTH (__wmemcpy_alias,
(wchar_t *__restrict __s1,
const wchar_t *__restrict __s2, size_t __n),
wmemcpy);
+
+#define __warn_wmemcpy_buflen "wmemcpy called with length bigger than size " \
+ "of destination buffer"
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_wmemcpy_buflen) wchar_t *
+__NTH (wmemcpy (wchar_t *__restrict const __clang_pass_object_size0 __s1,
+ const wchar_t *__restrict __s2, size_t __n))
+ __clang_enable_if (__bos0 (__s1) != (size_t) -1
+ && __n > __bos0 (__s1) / sizeof (wchar_t),
+ "selected if this call looks dangerous")
+{
+ return __wmemcpy_chk (__s1, __s2, __n, __bos0 (__s1) / sizeof (wchar_t));
+}
+
+__fortify_overload wchar_t *
+__NTH (wmemcpy (wchar_t *__restrict const __clang_pass_object_size0 __s1,
+ const wchar_t *__restrict __s2, size_t __n))
+{
+ if (__bos0 (__s1) != (size_t) -1)
+ return __wmemcpy_chk (__s1, __s2, __n, __bos0 (__s1) / sizeof (wchar_t));
+ return __wmemcpy_alias (__s1, __s2, __n);
+}
+#else
extern wchar_t *__REDIRECT_NTH (__wmemcpy_chk_warn,
(wchar_t *__restrict __s1,
const wchar_t *__restrict __s2, size_t __n,
size_t __ns1), __wmemcpy_chk)
- __warnattr ("wmemcpy called with length bigger than size of destination "
- "buffer");
+ __warnattr (__warn_wmemcpy_buflen);
__fortify_function wchar_t *
__NTH (wmemcpy (wchar_t *__restrict __s1, const wchar_t *__restrict __s2,
@@ -51,6 +73,8 @@ __NTH (wmemcpy (wchar_t *__restrict __s1, const wchar_t *__restrict __s2,
}
return __wmemcpy_alias (__s1, __s2, __n);
}
+#endif
+#undef __warn_wmemcpy_buflen
extern wchar_t *__wmemmove_chk (wchar_t *__s1, const wchar_t *__s2,
@@ -58,11 +82,33 @@ extern wchar_t *__wmemmove_chk (wchar_t *__s1, const wchar_t *__s2,
extern wchar_t *__REDIRECT_NTH (__wmemmove_alias, (wchar_t *__s1,
const wchar_t *__s2,
size_t __n), wmemmove);
+
+#define __warn_wmemmove_buflen "wmemmove called with length bigger than size " \
+ " of destination buffer"
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_wmemmove_buflen) wchar_t *
+__NTH (wmemmove (wchar_t *const __clang_pass_object_size0 __s1,
+ const wchar_t *__s2, size_t __n))
+ __clang_enable_if (__bos0 (__s1) != (size_t) -1
+ && __n > __bos0 (__s1) / sizeof (wchar_t),
+ "selected if this call looks dangerous")
+{
+ return __wmemmove_chk (__s1, __s2, __n, __bos0 (__s1) / sizeof (wchar_t));
+}
+
+__fortify_overload wchar_t *
+__NTH (wmemmove (wchar_t *const __clang_pass_object_size0 __s1,
+ const wchar_t *__s2, size_t __n))
+{
+ if (__bos0 (__s1) != (size_t) -1)
+ return __wmemmove_chk (__s1, __s2, __n, __bos0 (__s1) / sizeof (wchar_t));
+ return __wmemmove_alias (__s1, __s2, __n);
+}
+#else
extern wchar_t *__REDIRECT_NTH (__wmemmove_chk_warn,
(wchar_t *__s1, const wchar_t *__s2,
size_t __n, size_t __ns1), __wmemmove_chk)
- __warnattr ("wmemmove called with length bigger than size of destination "
- "buffer");
+ __warnattr (__warn_wmemmove_buflen);
__fortify_function wchar_t *
__NTH (wmemmove (wchar_t *__s1, const wchar_t *__s2, size_t __n))
@@ -79,6 +125,8 @@ __NTH (wmemmove (wchar_t *__s1, const wchar_t *__s2, size_t __n))
}
return __wmemmove_alias (__s1, __s2, __n);
}
+#endif
+#undef __warn_wmemmove_buflen
#ifdef __USE_GNU
@@ -89,12 +137,34 @@ extern wchar_t *__REDIRECT_NTH (__wmempcpy_alias,
(wchar_t *__restrict __s1,
const wchar_t *__restrict __s2,
size_t __n), wmempcpy);
+
+# define __warn_wmemcpy_buflen \
+ "wmempcpy called with length bigger than size of destination buffer"
+# ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_wmemcpy_buflen) wchar_t *
+__NTH (wmempcpy (wchar_t *__restrict const __clang_pass_object_size0 __s1,
+ const wchar_t *__restrict __s2, size_t __n))
+ __clang_enable_if (__bos0 (__s1) != (size_t) -1
+ && __n > __bos0 (__s1) / sizeof (wchar_t),
+ "selected if this call looks dangerous")
+{
+ return __wmempcpy_chk (__s1, __s2, __n, __bos0 (__s1) / sizeof (wchar_t));
+}
+
+__fortify_overload wchar_t *
+__NTH (wmempcpy (wchar_t *__restrict const __clang_pass_object_size0 __s1,
+ const wchar_t *__restrict __s2, size_t __n))
+{
+ if (__bos0 (__s1) != (size_t) -1)
+ return __wmempcpy_chk (__s1, __s2, __n, __bos0 (__s1) / sizeof (wchar_t));
+ return __wmempcpy_alias (__s1, __s2, __n);
+}
+# else
extern wchar_t *__REDIRECT_NTH (__wmempcpy_chk_warn,
(wchar_t *__restrict __s1,
const wchar_t *__restrict __s2, size_t __n,
size_t __ns1), __wmempcpy_chk)
- __warnattr ("wmempcpy called with length bigger than size of destination "
- "buffer");
+ __warnattr (__warn_wmemcpy_buflen);
__fortify_function wchar_t *
__NTH (wmempcpy (wchar_t *__restrict __s1, const wchar_t *__restrict __s2,
@@ -112,6 +182,8 @@ __NTH (wmempcpy (wchar_t *__restrict __s1, const wchar_t *__restrict __s2,
}
return __wmempcpy_alias (__s1, __s2, __n);
}
+# endif
+# undef __warn_wmemcpy_buflen
#endif
@@ -119,11 +191,33 @@ extern wchar_t *__wmemset_chk (wchar_t *__s, wchar_t __c, size_t __n,
size_t __ns) __THROW;
extern wchar_t *__REDIRECT_NTH (__wmemset_alias, (wchar_t *__s, wchar_t __c,
size_t __n), wmemset);
+
+#define __warn_wmemset_buflen "wmemset called with length bigger than size " \
+ "of destination buffer"
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_wmemset_buflen) wchar_t *
+__NTH (wmemset (wchar_t *const __clang_pass_object_size0 __s, wchar_t __c,
+ size_t __n))
+ __clang_enable_if (__bos0 (__s) != (size_t) -1
+ && __n > __bos0 (__s) / sizeof (wchar_t),
+ "selected if this call looks dangerous")
+{
+ return __wmemset_chk (__s, __c, __n, __bos0 (__s) / sizeof (wchar_t));
+}
+
+__fortify_overload wchar_t *
+__NTH (wmemset (wchar_t *const __clang_pass_object_size0 __s, wchar_t __c,
+ size_t __n))
+{
+ if (__bos0 (__s) != (size_t) -1)
+ return __wmemset_chk (__s, __c, __n, __bos0 (__s) / sizeof (wchar_t));
+ return __wmemset_alias (__s, __c, __n);
+}
+#else
extern wchar_t *__REDIRECT_NTH (__wmemset_chk_warn,
(wchar_t *__s, wchar_t __c, size_t __n,
size_t __ns), __wmemset_chk)
- __warnattr ("wmemset called with length bigger than size of destination "
- "buffer");
+ __warnattr (__warn_wmemset_buflen);
__fortify_function wchar_t *
__NTH (wmemset (wchar_t *__s, wchar_t __c, size_t __n))
@@ -139,6 +233,8 @@ __NTH (wmemset (wchar_t *__s, wchar_t __c, size_t __n))
}
return __wmemset_alias (__s, __c, __n);
}
+#endif
+#undef __warn_wmemset_buflen
extern wchar_t *__wcscpy_chk (wchar_t *__restrict __dest,
@@ -148,8 +244,9 @@ extern wchar_t *__REDIRECT_NTH (__wcscpy_alias,
(wchar_t *__restrict __dest,
const wchar_t *__restrict __src), wcscpy);
-__fortify_function wchar_t *
-__NTH (wcscpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src))
+__fortify_potential_overload wchar_t *
+__NTH (wcscpy (wchar_t *__restrict const __clang_pass_object_size __dest,
+ const wchar_t *__restrict __src))
{
if (__bos (__dest) != (size_t) -1)
return __wcscpy_chk (__dest, __src, __bos (__dest) / sizeof (wchar_t));
@@ -164,8 +261,9 @@ extern wchar_t *__REDIRECT_NTH (__wcpcpy_alias,
(wchar_t *__restrict __dest,
const wchar_t *__restrict __src), wcpcpy);
-__fortify_function wchar_t *
-__NTH (wcpcpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src))
+__fortify_potential_overload wchar_t *
+__NTH (wcpcpy (wchar_t *__restrict const __clang_pass_object_size __dest,
+ const wchar_t *__restrict __src))
{
if (__bos (__dest) != (size_t) -1)
return __wcpcpy_chk (__dest, __src, __bos (__dest) / sizeof (wchar_t));
@@ -180,12 +278,35 @@ extern wchar_t *__REDIRECT_NTH (__wcsncpy_alias,
(wchar_t *__restrict __dest,
const wchar_t *__restrict __src,
size_t __n), wcsncpy);
+
+#define __warn_wcsncpy_buflen "wcsncpy called with length bigger than size " \
+ "of destination buffer"
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_wcsncpy_buflen) wchar_t *
+__NTH (wcsncpy (wchar_t *__restrict const __clang_pass_object_size __dest,
+ const wchar_t *__restrict __src, size_t __n))
+ __clang_enable_if (__bos (__dest) != (size_t) -1
+ && __n > __bos (__dest) / sizeof (wchar_t),
+ "selected if this call looks dangerous")
+{
+ return __wcsncpy_chk (__dest, __src, __n, __bos (__dest) / sizeof (wchar_t));
+}
+
+__fortify_overload wchar_t *
+__NTH (wcsncpy (wchar_t *__restrict const __clang_pass_object_size __dest,
+ const wchar_t *__restrict __src, size_t __n))
+{
+ if (__bos (__dest) != (size_t) -1)
+ return __wcsncpy_chk (__dest, __src, __n,
+ __bos (__dest) / sizeof (wchar_t));
+ return __wcsncpy_alias (__dest, __src, __n);
+}
+#else
extern wchar_t *__REDIRECT_NTH (__wcsncpy_chk_warn,
(wchar_t *__restrict __dest,
const wchar_t *__restrict __src,
size_t __n, size_t __destlen), __wcsncpy_chk)
- __warnattr ("wcsncpy called with length bigger than size of destination "
- "buffer");
+ __warnattr (__warn_wcsncpy_buflen);
__fortify_function wchar_t *
__NTH (wcsncpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src,
@@ -202,6 +323,8 @@ __NTH (wcsncpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src,
}
return __wcsncpy_alias (__dest, __src, __n);
}
+#endif
+#undef __warn_wcsncpy_buflen
extern wchar_t *__wcpncpy_chk (wchar_t *__restrict __dest,
@@ -211,12 +334,35 @@ extern wchar_t *__REDIRECT_NTH (__wcpncpy_alias,
(wchar_t *__restrict __dest,
const wchar_t *__restrict __src,
size_t __n), wcpncpy);
+
+#define __warn_wcpncpy_buflen "wcpncpy called with length bigger than size " \
+ "of destination buffer"
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_wcpncpy_buflen) wchar_t *
+__NTH (wcpncpy (wchar_t *__restrict const __clang_pass_object_size __dest,
+ const wchar_t *__restrict __src, size_t __n))
+ __clang_enable_if (__bos (__dest) != (size_t) -1
+ && __n > __bos (__dest) / sizeof (wchar_t),
+ "selected if this call looks dangerous")
+{
+ return __wcpncpy_chk (__dest, __src, __n, __bos (__dest) / sizeof (wchar_t));
+}
+
+__fortify_overload wchar_t *
+__NTH (wcpncpy (wchar_t *__restrict const __clang_pass_object_size __dest,
+ const wchar_t *__restrict __src, size_t __n))
+{
+ if (__bos (__dest) != (size_t) -1)
+ return __wcpncpy_chk (__dest, __src, __n,
+ __bos (__dest) / sizeof (wchar_t));
+ return __wcpncpy_alias (__dest, __src, __n);
+}
+#else
extern wchar_t *__REDIRECT_NTH (__wcpncpy_chk_warn,
(wchar_t *__restrict __dest,
const wchar_t *__restrict __src,
size_t __n, size_t __destlen), __wcpncpy_chk)
- __warnattr ("wcpncpy called with length bigger than size of destination "
- "buffer");
+ __warnattr (__warn_wcpncpy_buflen);
__fortify_function wchar_t *
__NTH (wcpncpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src,
@@ -233,6 +379,8 @@ __NTH (wcpncpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src,
}
return __wcpncpy_alias (__dest, __src, __n);
}
+#endif
+#undef __warn_wcpncpy_buflen
extern wchar_t *__wcscat_chk (wchar_t *__restrict __dest,
@@ -242,8 +390,9 @@ extern wchar_t *__REDIRECT_NTH (__wcscat_alias,
(wchar_t *__restrict __dest,
const wchar_t *__restrict __src), wcscat);
-__fortify_function wchar_t *
-__NTH (wcscat (wchar_t *__restrict __dest, const wchar_t *__restrict __src))
+__fortify_potential_overload wchar_t *
+__NTH (wcscat (wchar_t *__restrict const __clang_pass_object_size __dest,
+ const wchar_t *__restrict __src))
{
if (__bos (__dest) != (size_t) -1)
return __wcscat_chk (__dest, __src, __bos (__dest) / sizeof (wchar_t));
@@ -259,9 +408,9 @@ extern wchar_t *__REDIRECT_NTH (__wcsncat_alias,
const wchar_t *__restrict __src,
size_t __n), wcsncat);
-__fortify_function wchar_t *
-__NTH (wcsncat (wchar_t *__restrict __dest, const wchar_t *__restrict __src,
- size_t __n))
+__fortify_potential_overload wchar_t *
+__NTH (wcsncat (wchar_t *__restrict const __clang_pass_object_size __dest,
+ const wchar_t *__restrict __src, size_t __n))
{
if (__bos (__dest) != (size_t) -1)
return __wcsncat_chk (__dest, __src, __n,
@@ -280,7 +429,36 @@ extern int __REDIRECT_NTH_LDBL (__swprintf_alias,
const wchar_t *__restrict __fmt, ...),
swprintf);
-#ifdef __va_arg_pack
+extern int __vswprintf_chk (wchar_t *__restrict __s, size_t __n,
+ int __flag, size_t __s_len,
+ const wchar_t *__restrict __format,
+ __gnuc_va_list __arg)
+ __THROW /* __attribute__ ((__format__ (__wprintf__, 5, 0))) */;
+
+extern int __REDIRECT_NTH_LDBL (__vswprintf_alias,
+ (wchar_t *__restrict __s, size_t __n,
+ const wchar_t *__restrict __fmt,
+ __gnuc_va_list __ap), vswprintf);
+
+
+#ifdef __use_clang_fortify
+__fortify_overload int
+__NTH (swprintf (wchar_t *__restrict const __clang_pass_object_size __s,
+ size_t __n, const wchar_t *__restrict __fmt, ...))
+{
+ __gnuc_va_list __va;
+ va_start (__va, __fmt);
+ int __result;
+ if (__bos (__s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1)
+ __result = __vswprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1,
+ __bos (__s) / sizeof (wchar_t),
+ __fmt, __va);
+ else
+ __result = __vswprintf_alias (__s, __n, __fmt, __va);
+ va_end (__va);
+ return __result;
+}
+#elif defined (__va_arg_pack)
__fortify_function int
__NTH (swprintf (wchar_t *__restrict __s, size_t __n,
const wchar_t *__restrict __fmt, ...))
@@ -300,20 +478,10 @@ __NTH (swprintf (wchar_t *__restrict __s, size_t __n,
: swprintf (s, n, __VA_ARGS__))
#endif
-extern int __vswprintf_chk (wchar_t *__restrict __s, size_t __n,
- int __flag, size_t __s_len,
- const wchar_t *__restrict __format,
- __gnuc_va_list __arg)
- __THROW /* __attribute__ ((__format__ (__wprintf__, 5, 0))) */;
-
-extern int __REDIRECT_NTH_LDBL (__vswprintf_alias,
- (wchar_t *__restrict __s, size_t __n,
- const wchar_t *__restrict __fmt,
- __gnuc_va_list __ap), vswprintf);
-
-__fortify_function int
-__NTH (vswprintf (wchar_t *__restrict __s, size_t __n,
- const wchar_t *__restrict __fmt, __gnuc_va_list __ap))
+__fortify_potential_overload int
+__NTH (vswprintf (wchar_t *__restrict const __clang_pass_object_size __s,
+ size_t __n, const wchar_t *__restrict __fmt,
+ __gnuc_va_list __ap))
{
if (__bos (__s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1)
return __vswprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1,
@@ -334,7 +502,27 @@ extern int __vfwprintf_chk (__FILE *__restrict __stream, int __flag,
extern int __vwprintf_chk (int __flag, const wchar_t *__restrict __format,
__gnuc_va_list __ap);
-# ifdef __va_arg_pack
+# ifdef __use_clang_fortify
+__fortify_function int
+wprintf (const wchar_t *__restrict __fmt, ...)
+{
+ __gnuc_va_list __ap;
+ va_start (__ap, __fmt);
+ int __r = __vwprintf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __ap);
+ va_end (__ap);
+ return __r;
+}
+
+__fortify_function int
+fwprintf (__FILE *__restrict __stream, const wchar_t *__restrict __fmt, ...)
+{
+ __gnuc_va_list __ap;
+ va_start (__ap, __fmt);
+ int __r = __vfwprintf_chk (__stream, __USE_FORTIFY_LEVEL - 1, __fmt, __ap);
+ va_end (__ap);
+ return __r;
+}
+# elif defined __va_arg_pack
__fortify_function int
wprintf (const wchar_t *__restrict __fmt, ...)
{
@@ -374,11 +562,33 @@ extern wchar_t *__fgetws_chk (wchar_t *__restrict __s, size_t __size, int __n,
extern wchar_t *__REDIRECT (__fgetws_alias,
(wchar_t *__restrict __s, int __n,
__FILE *__restrict __stream), fgetws) __wur;
+
+#define __warn_fgetws_buflen "fgetws called with bigger size than length " \
+ "of destination buffer"
+#ifdef __use_clang_fortify
+__fortify_overload __wur __clang_warning (__warn_fgetws_buflen) wchar_t *
+fgetws (wchar_t *__restrict const __clang_pass_object_size __s, int __n,
+ __FILE *__restrict __stream)
+ __clang_enable_if (__bos (__s) != (size_t) -1
+ && __n > __bos (__s) / sizeof (wchar_t),
+ "selected if this call looks dangerous")
+{
+ return __fgetws_chk (__s, __bos (__s) / sizeof (wchar_t), __n, __stream);
+}
+
+__fortify_overload __wur wchar_t *
+fgetws (wchar_t *__restrict const __clang_pass_object_size __s, int __n,
+ __FILE *__restrict __stream)
+{
+ if (__bos (__s) != (size_t) -1)
+ return __fgetws_chk (__s, __bos (__s) / sizeof (wchar_t), __n, __stream);
+ return __fgetws_alias (__s, __n, __stream);
+}
+#else
extern wchar_t *__REDIRECT (__fgetws_chk_warn,
(wchar_t *__restrict __s, size_t __size, int __n,
__FILE *__restrict __stream), __fgetws_chk)
- __wur __warnattr ("fgetws called with bigger size than length "
- "of destination buffer");
+ __wur __warnattr (__warn_fgetws_buflen);
__fortify_function __wur wchar_t *
fgetws (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream)
@@ -395,6 +605,8 @@ fgetws (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream)
}
return __fgetws_alias (__s, __n, __stream);
}
+#endif
+#undef __warn_fgetws_buflen
#ifdef __USE_GNU
extern wchar_t *__fgetws_unlocked_chk (wchar_t *__restrict __s, size_t __size,
@@ -404,12 +616,36 @@ extern wchar_t *__REDIRECT (__fgetws_unlocked_alias,
(wchar_t *__restrict __s, int __n,
__FILE *__restrict __stream), fgetws_unlocked)
__wur;
+
+# define __warn_fgetws_buflen \
+ "fgetws_unlocked called with bigger size than length of destination buffer"
+# ifdef __use_clang_fortify
+__fortify_overload __wur __clang_warning (__warn_fgetws_buflen) wchar_t *
+fgetws_unlocked (wchar_t *__restrict const __clang_pass_object_size __s,
+ int __n, __FILE *__restrict __stream)
+ __clang_enable_if (__bos (__s) != (size_t) -1
+ && __n > __bos (__s) / sizeof (wchar_t),
+ "selected if this call looks dangerous")
+{
+ return __fgetws_unlocked_chk (__s, __bos (__s) / sizeof (wchar_t), __n,
+ __stream);
+}
+
+__fortify_overload __wur wchar_t *
+fgetws_unlocked (wchar_t *__restrict const __clang_pass_object_size __s,
+ int __n, __FILE *__restrict __stream)
+{
+ if (__bos (__s) != (size_t) -1)
+ return __fgetws_unlocked_chk (__s, __bos (__s) / sizeof (wchar_t),
+ __n, __stream);
+ return __fgetws_unlocked_alias (__s, __n, __stream);
+}
+# else
extern wchar_t *__REDIRECT (__fgetws_unlocked_chk_warn,
(wchar_t *__restrict __s, size_t __size, int __n,
__FILE *__restrict __stream),
__fgetws_unlocked_chk)
- __wur __warnattr ("fgetws_unlocked called with bigger size than length "
- "of destination buffer");
+ __wur __warnattr (__warn_fgetws_buflen);
__fortify_function __wur wchar_t *
fgetws_unlocked (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream)
@@ -426,6 +662,8 @@ fgetws_unlocked (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream)
}
return __fgetws_unlocked_alias (__s, __n, __stream);
}
+# endif
+# undef __warn_fgetws_buflen
#endif
@@ -436,9 +674,9 @@ extern size_t __REDIRECT_NTH (__wcrtomb_alias,
(char *__restrict __s, wchar_t __wchar,
mbstate_t *__restrict __ps), wcrtomb) __wur;
-__fortify_function __wur size_t
-__NTH (wcrtomb (char *__restrict __s, wchar_t __wchar,
- mbstate_t *__restrict __ps))
+__fortify_potential_overload __wur size_t
+__NTH (wcrtomb (char *__restrict const __clang_pass_object_size __s,
+ wchar_t __wchar, mbstate_t *__restrict __ps))
{
/* We would have to include <limits.h> to get a definition of MB_LEN_MAX.
But this would only disturb the namespace. So we define our own
@@ -462,13 +700,39 @@ extern size_t __REDIRECT_NTH (__mbsrtowcs_alias,
const char **__restrict __src,
size_t __len, mbstate_t *__restrict __ps),
mbsrtowcs);
+
+#define __warn_mbsrtowcs_buflen "mbsrtowcs called with dst buffer smaller " \
+ "than len * sizeof (wchar_t)"
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_mbsrtowcs_buflen) size_t
+__NTH (mbsrtowcs (wchar_t *__restrict const __clang_pass_object_size __dst,
+ const char **__restrict __src, size_t __len,
+ mbstate_t *__restrict __ps))
+ __clang_enable_if (__bos (__dst) != (size_t) -1
+ && __len > __bos (__dst) / sizeof (wchar_t),
+ "selected if this call looks dangerous")
+{
+ return __mbsrtowcs_chk (__dst, __src, __len, __ps,
+ __bos (__dst) / sizeof (wchar_t));
+}
+
+__fortify_overload size_t
+__NTH (mbsrtowcs (wchar_t *__restrict const __clang_pass_object_size __dst,
+ const char **__restrict __src, size_t __len,
+ mbstate_t *__restrict __ps))
+{
+ if (__bos (__dst) != (size_t) -1)
+ return __mbsrtowcs_chk (__dst, __src, __len, __ps,
+ __bos (__dst) / sizeof (wchar_t));
+ return __mbsrtowcs_alias (__dst, __src, __len, __ps);
+}
+#else
extern size_t __REDIRECT_NTH (__mbsrtowcs_chk_warn,
(wchar_t *__restrict __dst,
const char **__restrict __src,
size_t __len, mbstate_t *__restrict __ps,
size_t __dstlen), __mbsrtowcs_chk)
- __warnattr ("mbsrtowcs called with dst buffer smaller than len "
- "* sizeof (wchar_t)");
+ __warnattr (__warn_mbsrtowcs_buflen);
__fortify_function size_t
__NTH (mbsrtowcs (wchar_t *__restrict __dst, const char **__restrict __src,
@@ -486,6 +750,8 @@ __NTH (mbsrtowcs (wchar_t *__restrict __dst, const char **__restrict __src,
}
return __mbsrtowcs_alias (__dst, __src, __len, __ps);
}
+#endif
+#undef __warn_mbsrtowcs_buflen
extern size_t __wcsrtombs_chk (char *__restrict __dst,
@@ -497,12 +763,36 @@ extern size_t __REDIRECT_NTH (__wcsrtombs_alias,
const wchar_t **__restrict __src,
size_t __len, mbstate_t *__restrict __ps),
wcsrtombs);
+
+#define __warn_wcsrtombs_buflen "wcsrtombs called with dst buffer smaller " \
+ "than len"
+#ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_wcsrtombs_buflen) size_t
+__NTH (wcsrtombs (char *__restrict const __clang_pass_object_size __dst,
+ const wchar_t **__restrict __src, size_t __len,
+ mbstate_t *__restrict __ps))
+ __clang_enable_if (__bos (__dst) != (size_t) -1 && __len > __bos (__dst),
+ "selected if this call looks dangerous")
+{
+ return __wcsrtombs_chk (__dst, __src, __len, __ps, __bos (__dst));
+}
+
+__fortify_overload size_t
+__NTH (wcsrtombs (char *__restrict const __clang_pass_object_size __dst,
+ const wchar_t **__restrict __src, size_t __len,
+ mbstate_t *__restrict __ps))
+{
+ if (__bos (__dst) != (size_t) -1)
+ return __wcsrtombs_chk (__dst, __src, __len, __ps, __bos (__dst));
+ return __wcsrtombs_alias (__dst, __src, __len, __ps);
+}
+#else
extern size_t __REDIRECT_NTH (__wcsrtombs_chk_warn,
(char *__restrict __dst,
const wchar_t **__restrict __src,
size_t __len, mbstate_t *__restrict __ps,
size_t __dstlen), __wcsrtombs_chk)
- __warnattr ("wcsrtombs called with dst buffer smaller than len");
+ __warnattr (__warn_wcsrtombs_buflen);
__fortify_function size_t
__NTH (wcsrtombs (char *__restrict __dst, const wchar_t **__restrict __src,
@@ -518,6 +808,8 @@ __NTH (wcsrtombs (char *__restrict __dst, const wchar_t **__restrict __src,
}
return __wcsrtombs_alias (__dst, __src, __len, __ps);
}
+#endif
+#undef __warn_wcsrtombs_buflen
#ifdef __USE_GNU
@@ -530,13 +822,38 @@ extern size_t __REDIRECT_NTH (__mbsnrtowcs_alias,
const char **__restrict __src, size_t __nmc,
size_t __len, mbstate_t *__restrict __ps),
mbsnrtowcs);
+
+# define __warn_mbsnrtowcs_buflen "mbsnrtowcs called with dst buffer smaller " \
+ "than len * sizeof (wchar_t)"
+# ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_mbsnrtowcs_buflen) size_t
+__NTH (mbsnrtowcs (wchar_t *__restrict const __clang_pass_object_size __dst,
+ const char **__restrict __src, size_t __nmc, size_t __len,
+ mbstate_t *__restrict __ps))
+ __clang_enable_if (__bos (__dst) != (size_t) -1 && __bos (__dst) < __len,
+ "selected if this call looks dangerous")
+{
+ return __mbsnrtowcs_chk (__dst, __src, __nmc, __len, __ps,
+ __bos (__dst) / sizeof (wchar_t));
+}
+
+__fortify_overload size_t
+__NTH (mbsnrtowcs (wchar_t *__restrict const __clang_pass_object_size __dst,
+ const char **__restrict __src, size_t __nmc, size_t __len,
+ mbstate_t *__restrict __ps))
+{
+ if (__bos (__dst) != (size_t) -1)
+ return __mbsnrtowcs_chk (__dst, __src, __nmc, __len, __ps,
+ __bos (__dst) / sizeof (wchar_t));
+ return __mbsnrtowcs_alias (__dst, __src, __nmc, __len, __ps);
+}
+# else
extern size_t __REDIRECT_NTH (__mbsnrtowcs_chk_warn,
(wchar_t *__restrict __dst,
const char **__restrict __src, size_t __nmc,
size_t __len, mbstate_t *__restrict __ps,
size_t __dstlen), __mbsnrtowcs_chk)
- __warnattr ("mbsnrtowcs called with dst buffer smaller than len "
- "* sizeof (wchar_t)");
+ __warnattr (__warn_mbsnrtowcs_buflen);
__fortify_function size_t
__NTH (mbsnrtowcs (wchar_t *__restrict __dst, const char **__restrict __src,
@@ -554,6 +871,8 @@ __NTH (mbsnrtowcs (wchar_t *__restrict __dst, const char **__restrict __src,
}
return __mbsnrtowcs_alias (__dst, __src, __nmc, __len, __ps);
}
+# endif
+# undef __warn_mbsnrtowcs_buflen
extern size_t __wcsnrtombs_chk (char *__restrict __dst,
@@ -566,13 +885,38 @@ extern size_t __REDIRECT_NTH (__wcsnrtombs_alias,
const wchar_t **__restrict __src,
size_t __nwc, size_t __len,
mbstate_t *__restrict __ps), wcsnrtombs);
+
+# define __warn_wcsnrtombs_buflen \
+ "wcsnrtombs called with dst buffer smaller than len"
+# ifdef __use_clang_fortify
+__fortify_overload __clang_warning (__warn_wcsnrtombs_buflen) size_t
+__NTH (wcsnrtombs (char *__restrict const __clang_pass_object_size __dst,
+ const wchar_t **__restrict __src, size_t __nwc, size_t __len,
+ mbstate_t *__restrict __ps))
+ __clang_enable_if (__bos (__dst) != (size_t) -1 && __bos (__dst) < __len,
+ "selected if this call looks dangerous")
+{
+ return __wcsnrtombs_chk (__dst, __src, __nwc, __len, __ps,
+ __bos (__dst));
+}
+
+__fortify_overload size_t
+__NTH (wcsnrtombs (char *__restrict const __clang_pass_object_size __dst,
+ const wchar_t **__restrict __src, size_t __nwc, size_t __len,
+ mbstate_t *__restrict __ps))
+{
+ if (__bos (__dst) != (size_t) -1)
+ return __wcsnrtombs_chk (__dst, __src, __nwc, __len, __ps, __bos (__dst));
+ return __wcsnrtombs_alias (__dst, __src, __nwc, __len, __ps);
+}
+# else
extern size_t __REDIRECT_NTH (__wcsnrtombs_chk_warn,
(char *__restrict __dst,
const wchar_t **__restrict __src,
size_t __nwc, size_t __len,
mbstate_t *__restrict __ps,
size_t __dstlen), __wcsnrtombs_chk)
- __warnattr ("wcsnrtombs called with dst buffer smaller than len");
+ __warnattr (__warn_wcsnrtombs_buflen);
__fortify_function size_t
__NTH (wcsnrtombs (char *__restrict __dst, const wchar_t **__restrict __src,
@@ -590,4 +934,6 @@ __NTH (wcsnrtombs (char *__restrict __dst, const wchar_t **__restrict __src,
}
return __wcsnrtombs_alias (__dst, __src, __nwc, __len, __ps);
}
+# endif
+# undef __warn_wcsnrtombs_buflen
#endif
--- wcsmbs/wchar.h
+++ wcsmbs/wchar.h
@@ -144,20 +144,26 @@ __USING_NAMESPACE_STD(tm)
__BEGIN_NAMESPACE_STD
/* Copy SRC to DEST. */
+__fortify_overloadable
extern wchar_t *wcscpy (wchar_t *__restrict __dest,
- const wchar_t *__restrict __src) __THROW;
+ const wchar_t *__restrict __src)
+ __THROW __CLANG_NO_MANGLE (wcscpy);
/* Copy no more than N wide-characters of SRC to DEST. */
+__fortify_overloadable
extern wchar_t *wcsncpy (wchar_t *__restrict __dest,
const wchar_t *__restrict __src, size_t __n)
- __THROW;
+ __THROW __CLANG_NO_MANGLE (wcsncpy);
/* Append SRC onto DEST. */
+__fortify_overloadable
extern wchar_t *wcscat (wchar_t *__restrict __dest,
- const wchar_t *__restrict __src) __THROW;
+ const wchar_t *__restrict __src) __THROW
+ __CLANG_NO_MANGLE (wcscat);
/* Append no more than N wide-characters of SRC onto DEST. */
+__fortify_overloadable
extern wchar_t *wcsncat (wchar_t *__restrict __dest,
const wchar_t *__restrict __src, size_t __n)
- __THROW;
+ __THROW __CLANG_NO_MANGLE (wcsncat);
/* Compare S1 and S2. */
extern int wcscmp (const wchar_t *__s1, const wchar_t *__s2)
@@ -326,24 +332,30 @@ extern int wmemcmp (const wchar_t *__s1, const wchar_t *__s2, size_t __n)
__THROW __attribute_pure__;
/* Copy N wide characters of SRC to DEST. */
+__fortify_overloadable
extern wchar_t *wmemcpy (wchar_t *__restrict __s1,
- const wchar_t *__restrict __s2, size_t __n) __THROW;
+ const wchar_t *__restrict __s2, size_t __n)
+ __THROW __CLANG_NO_MANGLE (wmemcpy);
/* Copy N wide characters of SRC to DEST, guaranteeing
correct behavior for overlapping strings. */
+__fortify_overloadable
extern wchar_t *wmemmove (wchar_t *__s1, const wchar_t *__s2, size_t __n)
- __THROW;
+ __THROW __CLANG_NO_MANGLE (wmemmove);
/* Set N wide characters of S to C. */
-extern wchar_t *wmemset (wchar_t *__s, wchar_t __c, size_t __n) __THROW;
+__fortify_overloadable
+extern wchar_t *wmemset (wchar_t *__s, wchar_t __c, size_t __n)
+ __THROW __CLANG_NO_MANGLE (wmemset);
__END_NAMESPACE_STD
#ifdef __USE_GNU
/* Copy N wide characters of SRC to DEST and return pointer to following
wide character. */
+__fortify_overloadable
extern wchar_t *wmempcpy (wchar_t *__restrict __s1,
const wchar_t *__restrict __s2, size_t __n)
- __THROW;
+ __THROW __CLANG_NO_MANGLE (wmempcpy);
#endif
@@ -367,8 +379,10 @@ extern size_t mbrtowc (wchar_t *__restrict __pwc,
mbstate_t *__restrict __p) __THROW;
/* Write multibyte representation of wide character WC to S. */
+__fortify_overloadable
extern size_t wcrtomb (char *__restrict __s, wchar_t __wc,
- mbstate_t *__restrict __ps) __THROW;
+ mbstate_t *__restrict __ps)
+ __THROW __CLANG_NO_MANGLE (wcrtomb);
/* Return number of bytes in multibyte character pointed to by S. */
extern size_t __mbrlen (const char *__restrict __s, size_t __n,
@@ -405,31 +419,39 @@ __NTH (mbrlen (const char *__restrict __s, size_t __n,
__BEGIN_NAMESPACE_STD
/* Write wide character representation of multibyte character string
SRC to DST. */
+__fortify_overloadable
extern size_t mbsrtowcs (wchar_t *__restrict __dst,
const char **__restrict __src, size_t __len,
- mbstate_t *__restrict __ps) __THROW;
+ mbstate_t *__restrict __ps)
+ __THROW __CLANG_NO_MANGLE (mbsrtowcs);
/* Write multibyte character representation of wide character string
SRC to DST. */
+__fortify_overloadable
extern size_t wcsrtombs (char *__restrict __dst,
const wchar_t **__restrict __src, size_t __len,
- mbstate_t *__restrict __ps) __THROW;
+ mbstate_t *__restrict __ps)
+ __THROW __CLANG_NO_MANGLE (wcsrtombs);
__END_NAMESPACE_STD
#ifdef __USE_XOPEN2K8
/* Write wide character representation of at most NMC bytes of the
multibyte character string SRC to DST. */
+__fortify_overloadable
extern size_t mbsnrtowcs (wchar_t *__restrict __dst,
const char **__restrict __src, size_t __nmc,
- size_t __len, mbstate_t *__restrict __ps) __THROW;
+ size_t __len, mbstate_t *__restrict __ps)
+ __THROW __CLANG_NO_MANGLE (mbsnrtowcs);
/* Write multibyte character representation of at most NWC characters
from the wide character string SRC to DST. */
+__fortify_overloadable
extern size_t wcsnrtombs (char *__restrict __dst,
const wchar_t **__restrict __src,
size_t __nwc, size_t __len,
- mbstate_t *__restrict __ps) __THROW;
+ mbstate_t *__restrict __ps)
+ __THROW __CLANG_NO_MANGLE (wcsnrtombs);
#endif /* use POSIX 2008 */
@@ -563,14 +585,17 @@ extern long double wcstold_l (const wchar_t *__restrict __nptr,
#ifdef __USE_XOPEN2K8
/* Copy SRC to DEST, returning the address of the terminating L'\0' in
DEST. */
+__fortify_overloadable
extern wchar_t *wcpcpy (wchar_t *__restrict __dest,
- const wchar_t *__restrict __src) __THROW;
+ const wchar_t *__restrict __src)
+ __THROW __CLANG_NO_MANGLE (wcpcpy);
/* Copy no more than N characters of SRC to DEST, returning the address of
the last character written into DEST. */
+__fortify_overloadable
extern wchar_t *wcpncpy (wchar_t *__restrict __dest,
const wchar_t *__restrict __src, size_t __n)
- __THROW;
+ __THROW __CLANG_NO_MANGLE (wcpncpy);
/* Wide character I/O functions. */
@@ -601,9 +626,11 @@ extern int fwprintf (__FILE *__restrict __stream,
extern int wprintf (const wchar_t *__restrict __format, ...)
/* __attribute__ ((__format__ (__wprintf__, 1, 2))) */;
/* Write formatted output of at most N characters to S. */
+__fortify_overloadable
extern int swprintf (wchar_t *__restrict __s, size_t __n,
const wchar_t *__restrict __format, ...)
- __THROW /* __attribute__ ((__format__ (__wprintf__, 3, 4))) */;
+ __THROW /* __attribute__ ((__format__ (__wprintf__, 3, 4))) */
+ __CLANG_NO_MANGLE (swprintf);
/* Write formatted output to S from argument list ARG.
@@ -622,10 +649,12 @@ extern int vwprintf (const wchar_t *__restrict __format,
/* __attribute__ ((__format__ (__wprintf__, 1, 0))) */;
/* Write formatted output of at most N character to S from argument
list ARG. */
+__fortify_overloadable
extern int vswprintf (wchar_t *__restrict __s, size_t __n,
const wchar_t *__restrict __format,
__gnuc_va_list __arg)
- __THROW /* __attribute__ ((__format__ (__wprintf__, 3, 0))) */;
+ __THROW /* __attribute__ ((__format__ (__wprintf__, 3, 0))) */
+ __CLANG_NO_MANGLE (vswprintf);
/* Read formatted input from STREAM.
@@ -771,8 +800,10 @@ extern wint_t putwchar (wchar_t __wc);
This function is a possible cancellation point and therefore not
marked with __THROW. */
+__fortify_overloadable
extern wchar_t *fgetws (wchar_t *__restrict __ws, int __n,
- __FILE *__restrict __stream);
+ __FILE *__restrict __stream)
+ __CLANG_NO_MANGLE (fgetws);
/* Write a string to STREAM.
@@ -834,8 +865,10 @@ extern wint_t putwchar_unlocked (wchar_t __wc);
cancellation point. But due to similarity with an POSIX interface
or due to the implementation it is a cancellation point and
therefore not marked with __THROW. */
+__fortify_overloadable
extern wchar_t *fgetws_unlocked (wchar_t *__restrict __ws, int __n,
- __FILE *__restrict __stream);
+ __FILE *__restrict __stream)
+ __CLANG_NO_MANGLE (fgetws_unlocked);
/* This function does the same as `fputws' but does not lock the stream.