summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry V. Levin <ldv@altlinux.org>2013-11-05 22:46:43 +0000
committerDmitry V. Levin <ldv@altlinux.org>2013-11-05 22:46:43 +0000
commitf3696b3c8bdd32b5621f0fa126c269f13c11bfc4 (patch)
tree2fb6342c050cdae90ca88fe1a94fe9c8d9aaf396
parent1f65c3cd2ac24c6fcc6a8eb3eb88cd6161c25c88 (diff)
downloadstrace-f3696b3c8bdd32b5621f0fa126c269f13c11bfc4.tar.gz
strace-f3696b3c8bdd32b5621f0fa126c269f13c11bfc4.tar.bz2
strace-f3696b3c8bdd32b5621f0fa126c269f13c11bfc4.tar.xz
More select decoding fixes
* desc.c (decode_select): Actually print arg[0] as int on entering syscall. When arg[0] is negative, do not attempt to fetch and decode descriptor sets on entering syscall, kernel will reject it anyway. On exiting syscall, stop checking descriptor sets as soon as all returned descriptors are found.
-rw-r--r--desc.c46
1 files changed, 26 insertions, 20 deletions
diff --git a/desc.c b/desc.c
index bbdc087..3547d96 100644
--- a/desc.c
+++ b/desc.c
@@ -486,31 +486,39 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
const char *sep;
long arg;
- /* Kernel truncates arg[0] to int, we do the same */
- fdsize = (int)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) {
+ nfds = 0;
+ fds = NULL;
+ }
/* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */
- if (fdsize > 1024*1024)
- fdsize = 1024*1024;
- if (fdsize < 0)
- fdsize = 0;
- nfds = fdsize;
- fdsize = (((fdsize + 7) / 8) + sizeof(long)-1) & -sizeof(long);
- /* We had bugs a-la "while (j < args[0])" and "umoven(args[0])" below.
+ if (nfds > 1024*1024)
+ nfds = 1024*1024;
+
+ /*
+ * We had bugs a-la "while (j < args[0])" and "umoven(args[0])" below.
* Instead of args[0], use nfds for fd count, fdsize for array lengths.
*/
+ fdsize = (((nfds + 7) / 8) + sizeof(long)-1) & -sizeof(long);
if (entering(tcp)) {
- fds = malloc(fdsize);
- if (!fds)
- die_out_of_memory();
- tprintf("%ld", args[0]);
+ tprintf("%d", (int) args[0]);
+
+ if (fdsize > 0) {
+ fds = malloc(fdsize);
+ if (!fds)
+ die_out_of_memory();
+ }
for (i = 0; i < 3; i++) {
arg = args[i+1];
if (arg == 0) {
tprints(", NULL");
continue;
}
- if (!verbose(tcp)) {
+ if (!verbose(tcp) || !fds) {
tprintf(", %#lx", arg);
continue;
}
@@ -536,8 +544,7 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
static char outstr[1024];
char *outptr;
#define end_outstr (outstr + sizeof(outstr))
- const char *sep;
- long ready_fds;
+ int ready_fds;
if (syserror(tcp))
return 0;
@@ -554,7 +561,7 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
outptr = outstr;
sep = "";
- for (i = 0; i < 3; i++) {
+ for (i = 0; i < 3 && ready_fds > 0; i++) {
int first = 1;
arg = args[i+1];
@@ -577,13 +584,12 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
outptr += sprintf(outptr, " %u", j);
}
}
- ready_fds--;
+ if (--ready_fds == 0)
+ break;
}
}
if (outptr != outstr)
*outptr++ = ']';
- if (ready_fds == 0)
- break;
}
free(fds);
/* This contains no useful information on SunOS. */