diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2013-11-09 20:46:55 +0100 |
---|---|---|
committer | Denys Vlasenko <dvlasenk@redhat.com> | 2013-11-09 20:46:55 +0100 |
commit | 64778cbfa62d9584c59d3a48b69ba1ebf8bd24e9 (patch) | |
tree | 6823f86d436dde7888bec09598797fb5d6a068de | |
parent | b338f2d65ea9d911a0fead3229ba336bc30e6214 (diff) | |
download | strace-64778cbfa62d9584c59d3a48b69ba1ebf8bd24e9.tar.gz strace-64778cbfa62d9584c59d3a48b69ba1ebf8bd24e9.tar.bz2 strace-64778cbfa62d9584c59d3a48b69ba1ebf8bd24e9.tar.xz |
Fix pathtrace_match() to match recent fixes to select decoding.
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
-rw-r--r-- | pathtrace.c | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/pathtrace.c b/pathtrace.c index d4c2dc4..f76f3ce 100644 --- a/pathtrace.c +++ b/pathtrace.c @@ -257,11 +257,12 @@ pathtrace_match(struct tcb *tcp) s->sys_func == sys_pselect6) { int i, j; - unsigned nfds; + int nfds; long *args, oldargs[5]; unsigned fdsize; fd_set *fds; + args = tcp->u_arg; if (s->sys_func == sys_oldselect) { if (umoven(tcp, tcp->u_arg[0], sizeof oldargs, (char*) oldargs) < 0) @@ -270,17 +271,17 @@ pathtrace_match(struct tcb *tcp) return 0; } args = oldargs; - } else - args = tcp->u_arg; + } - nfds = args[0]; + /* Kernel truncates arg[0] to int, we do the same. */ + nfds = (int) args[0]; + /* Kernel rejects negative nfds, so we don't parse it either. */ + if (nfds <= 0) + return 0; /* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */ - if (args[0] > 1024*1024) + if (nfds > 1024*1024) nfds = 1024*1024; - if (args[0] < 0) - nfds = 0; - fdsize = ((((nfds + 7) / 8) + sizeof(long) - 1) - & -sizeof(long)); + fdsize = (((nfds + 7) / 8) + current_wordsize-1) & -current_wordsize; fds = malloc(fdsize); if (!fds) die_out_of_memory(); @@ -288,17 +289,19 @@ pathtrace_match(struct tcb *tcp) for (i = 1; i <= 3; ++i) { if (args[i] == 0) continue; - if (umoven(tcp, args[i], fdsize, (char *) fds) < 0) { fprintf(stderr, "umoven() failed\n"); continue; } - - for (j = 0; j < nfds; ++j) - if (FD_ISSET(j, fds) && fdmatch(tcp, j)) { + for (j = 0;; j++) { + j = next_set_bit(fds, j, nfds); + if (j < 0) + break; + if (fdmatch(tcp, j)) { free(fds); return 1; } + } } free(fds); return 0; |