Add argument checking to sigemptyset(3) and friends.
You could argue that this is hurting people smart enough to have manually
allocated a large-enough sigset_t, but those people are smart enough to
implement their own sigset functions too.
I wonder whether our least unpleasant way out of our self-inflicted 32-bit
cesspool is to have equivalents of _FILE_OFFSET_BITS such as _SIGSET_T_BITS,
so calling code could opt in? You'd have to be careful passing sigset_t
arguments between code compiled with different options.
Bug: 5828899
Change-Id: I0ae60ee8544835b069a2b20568f38ec142e0737b
diff --git a/libc/include/signal.h b/libc/include/signal.h
index 6432c18..9d3badc 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -28,6 +28,7 @@
#ifndef _SIGNAL_H_
#define _SIGNAL_H_
+#include <errno.h>
#include <sys/cdefs.h>
#include <limits.h> /* For LONG_BIT */
#include <string.h> /* For memset() */
@@ -53,45 +54,57 @@
# define _NSIG 64
#endif
-extern const char * const sys_siglist[];
-extern const char * const sys_signame[];
+extern const char* const sys_siglist[];
+extern const char* const sys_signame[];
-static __inline__ int sigismember(sigset_t *set, int signum)
-{
- unsigned long *local_set = (unsigned long *)set;
- signum--;
- return (int)((local_set[signum/LONG_BIT] >> (signum%LONG_BIT)) & 1);
+static __inline__ int sigismember(sigset_t* set, int signum) {
+ if (set == NULL || signum < 1 || signum >= 8*sizeof(sigset_t)) {
+ errno = EINVAL;
+ return -1;
+ }
+ unsigned long* local_set = (unsigned long*) set;
+ signum--;
+ return (int) ((local_set[signum/LONG_BIT] >> (signum%LONG_BIT)) & 1);
}
-
-static __inline__ int sigaddset(sigset_t *set, int signum)
-{
- unsigned long *local_set = (unsigned long *)set;
- signum--;
- local_set[signum/LONG_BIT] |= 1UL << (signum%LONG_BIT);
- return 0;
+static __inline__ int sigaddset(sigset_t* set, int signum) {
+ if (set == NULL || signum < 1 || signum >= 8*sizeof(sigset_t)) {
+ errno = EINVAL;
+ return -1;
+ }
+ unsigned long* local_set = (unsigned long*) set;
+ signum--;
+ local_set[signum/LONG_BIT] |= 1UL << (signum%LONG_BIT);
+ return 0;
}
-
-static __inline__ int sigdelset(sigset_t *set, int signum)
-{
- unsigned long *local_set = (unsigned long *)set;
- signum--;
- local_set[signum/LONG_BIT] &= ~(1UL << (signum%LONG_BIT));
- return 0;
+static __inline__ int sigdelset(sigset_t* set, int signum) {
+ if (set == NULL || signum < 1 || signum >= 8*sizeof(sigset_t)) {
+ errno = EINVAL;
+ return -1;
+ }
+ unsigned long* local_set = (unsigned long*) set;
+ signum--;
+ local_set[signum/LONG_BIT] &= ~(1UL << (signum%LONG_BIT));
+ return 0;
}
-
-static __inline__ int sigemptyset(sigset_t *set)
-{
- memset(set, 0, sizeof *set);
- return 0;
+static __inline__ int sigemptyset(sigset_t* set) {
+ if (set == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ memset(set, 0, sizeof *set);
+ return 0;
}
-static __inline__ int sigfillset(sigset_t *set)
-{
- memset(set, ~0, sizeof *set);
- return 0;
+static __inline__ int sigfillset(sigset_t* set) {
+ if (set == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ memset(set, ~0, sizeof *set);
+ return 0;
}