Fix select decoding for glibc in _FORTIFY_SOURCE mode
glibc in _FORTIFY_SOURCE mode raises SIGABRT when descriptor greater
or equal to FD_SETSIZE is passed to FD_ISSET. Select family syscalls,
however, can legitimately accept such descriptors. To overcome this
limitation, we have to replace FD_ISSET with an equivalent that imposes
no such restrictions.
* desc.c (fd_isset): New function.
(decode_select): Use it instead of FD_ISSET.
diff --git a/desc.c b/desc.c
index 3547d96..e18735c 100644
--- a/desc.c
+++ b/desc.c
@@ -478,6 +478,14 @@
#endif
static int
+fd_isset(int d, fd_set *fds)
+{
+ const int bpl = 8 * sizeof(long);
+ long *s = (long *) fds;
+ return !!(s[d / bpl] & (1L << (d % bpl)));
+}
+
+static int
decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
{
int i, j;
@@ -528,7 +536,7 @@
}
tprints(", [");
for (j = 0, sep = ""; j < nfds; j++) {
- if (FD_ISSET(j, fds)) {
+ if (fd_isset(j, fds)) {
tprints(sep);
printfd(tcp, j);
sep = " ";
@@ -568,7 +576,7 @@
if (!arg || umoven(tcp, arg, fdsize, (char *) fds) < 0)
continue;
for (j = 0; j < nfds; j++) {
- if (FD_ISSET(j, fds)) {
+ if (fd_isset(j, fds)) {
/* +2 chars needed at the end: ']',NUL */
if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) {
if (first) {