about summary refs log tree commit diff
path: root/misc/sys/cdefs.h
diff options
context:
space:
mode:
Diffstat (limited to 'misc/sys/cdefs.h')
-rw-r--r--misc/sys/cdefs.h47
1 files changed, 47 insertions, 0 deletions
diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h
index f6ab95ab81..c353d2ec4d 100644
--- a/misc/sys/cdefs.h
+++ b/misc/sys/cdefs.h
@@ -150,6 +150,53 @@
 # define __glibc_objsize(__o) __bos (__o)
 #endif
 
+/* Compile time conditions to choose between the regular, _chk and _chk_warn
+   variants.  These conditions should get evaluated to constant and optimized
+   away.  */
+
+#define __glibc_safe_len_cond(__l, __s, __osz) ((__l) <= (__osz) / (__s))
+#define __glibc_unsigned_or_positive(__l) \
+  ((__typeof (__l)) 0 < (__typeof (__l)) -1				      \
+   || (__builtin_constant_p (__l) && (__l) > 0))
+
+/* Length is known to be safe at compile time if the __L * __S <= __OBJSZ
+   condition can be folded to a constant and if it is true.  The -1 check is
+   redundant because since it implies that __glibc_safe_len_cond is true.  */
+#define __glibc_safe_or_unknown_len(__l, __s, __osz) \
+  (__glibc_unsigned_or_positive (__l)					      \
+   && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l),     \
+						   __s, __osz))		      \
+   && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz))
+
+/* Conversely, we know at compile time that the length is safe if the
+   __L * __S <= __OBJSZ condition can be folded to a constant and if it is
+   false.  */
+#define __glibc_unsafe_len(__l, __s, __osz) \
+  (__glibc_unsigned_or_positive (__l)					      \
+   && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l),     \
+						   __s, __osz))		      \
+   && !__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz))
+
+/* Fortify function f.  __f_alias, __f_chk and __f_chk_warn must be
+   declared.  */
+
+#define __glibc_fortify(f, __l, __s, __osz, ...) \
+  (__glibc_safe_or_unknown_len (__l, __s, __osz)			      \
+   ? __ ## f ## _alias (__VA_ARGS__)					      \
+   : (__glibc_unsafe_len (__l, __s, __osz)				      \
+      ? __ ## f ## _chk_warn (__VA_ARGS__, __osz)			      \
+      : __ ## f ## _chk (__VA_ARGS__, __osz)))			      \
+
+/* Fortify function f, where object size argument passed to f is the number of
+   elements and not total size.  */
+
+#define __glibc_fortify_n(f, __l, __s, __osz, ...) \
+  (__glibc_safe_or_unknown_len (__l, __s, __osz)			      \
+   ? __ ## f ## _alias (__VA_ARGS__)					      \
+   : (__glibc_unsafe_len (__l, __s, __osz)				      \
+      ? __ ## f ## _chk_warn (__VA_ARGS__, (__osz) / (__s))		      \
+      : __ ## f ## _chk (__VA_ARGS__, (__osz) / (__s))))		      \
+
 #if __GNUC_PREREQ (4,3)
 # define __warnattr(msg) __attribute__((__warning__ (msg)))
 # define __errordecl(name, msg) \