]> granicus.if.org Git - strace/blobdiff - wait.c
Robustify mpers.awk against invalid input
[strace] / wait.c
diff --git a/wait.c b/wait.c
index 53808641e238b902e77eb890650cd38de036e243..2e495dbf94117a5acf861a28eecff4a5a7b8c35b 100644 (file)
--- a/wait.c
+++ b/wait.c
@@ -2,16 +2,6 @@
 
 #include <sys/wait.h>
 
-#ifndef __WNOTHREAD
-# define __WNOTHREAD   0x20000000
-#endif
-#ifndef __WALL
-# define __WALL                0x40000000
-#endif
-#ifndef __WCLONE
-# define __WCLONE      0x80000000
-#endif
-
 #include "xlat/wait4_options.h"
 
 #if !defined WCOREFLAG && defined WCOREFLG
 #ifndef W_EXITCODE
 # define W_EXITCODE(ret, sig)  ((ret) << 8 | (sig))
 #endif
+#ifndef W_CONTINUED
+# define W_CONTINUED 0xffff
+#endif
+
+#include "ptrace.h"
+#include "xlat/ptrace_events.h"
 
 static int
 printstatus(int status)
@@ -41,9 +37,11 @@ printstatus(int status)
         * are no wait status constructors it will have to do.
         */
        if (WIFSTOPPED(status)) {
-               tprintf("[{WIFSTOPPED(s) && WSTOPSIG(s) == %s}",
-                       signame(WSTOPSIG(status)));
-               status &= ~W_STOPCODE(WSTOPSIG(status));
+               int sig = WSTOPSIG(status);
+               tprintf("[{WIFSTOPPED(s) && WSTOPSIG(s) == %s%s}",
+                       signame(sig & 0x7f),
+                       sig & 0x80 ? " | 0x80" : "");
+               status &= ~W_STOPCODE(sig);
        }
        else if (WIFSIGNALED(status)) {
                tprintf("[{WIFSIGNALED(s) && WTERMSIG(s) == %s%s}",
@@ -57,15 +55,29 @@ printstatus(int status)
                exited = 1;
                status &= ~W_EXITCODE(WEXITSTATUS(status), 0);
        }
+#ifdef WIFCONTINUED
+       else if (WIFCONTINUED(status)) {
+               tprints("[{WIFCONTINUED(s)}");
+               status &= ~W_CONTINUED;
+       }
+#endif
        else {
                tprintf("[%#x]", status);
                return 0;
        }
 
-       if (status == 0)
-               tprints("]");
-       else
-               tprintf(" | %#x]", status);
+       if (status) {
+               unsigned int event = (unsigned int) status >> 16;
+               if (event) {
+                       tprints(" | ");
+                       printxval(ptrace_events, event, "PTRACE_EVENT_???");
+                       tprints(" << 16");
+                       status &= 0xffff;
+               }
+               if (status)
+                       tprintf(" | %#x", status);
+       }
+       tprints("]");
 
        return exited;
 }
@@ -86,13 +98,9 @@ printwaitn(struct tcb *tcp, int n, int bitness)
                tprintf("%d, ", pid);
        } else {
                /* status */
-               if (!tcp->u_arg[1])
-                       tprints("NULL");
-               else if (syserror(tcp) || tcp->u_rval == 0)
-                       tprintf("%#lx", tcp->u_arg[1]);
-               else if (umove(tcp, tcp->u_arg[1], &status) < 0)
-                       tprints("[?]");
-               else
+               if (tcp->u_rval == 0)
+                       printaddr(tcp->u_arg[1]);
+               else if (!umove_or_printaddr(tcp, tcp->u_arg[1], &status))
                        printstatus(status);
                /* options */
                tprints(", ");
@@ -100,9 +108,7 @@ printwaitn(struct tcb *tcp, int n, int bitness)
                if (n == 4) {
                        tprints(", ");
                        /* usage */
-                       if (!tcp->u_arg[3])
-                               tprints("NULL");
-                       else if (tcp->u_rval > 0) {
+                       if (tcp->u_rval > 0) {
 #ifdef ALPHA
                                if (bitness)
                                        printrusage32(tcp, tcp->u_arg[3]);
@@ -111,27 +117,24 @@ printwaitn(struct tcb *tcp, int n, int bitness)
                                        printrusage(tcp, tcp->u_arg[3]);
                        }
                        else
-                               tprintf("%#lx", tcp->u_arg[3]);
+                               printaddr(tcp->u_arg[3]);
                }
        }
        return 0;
 }
 
-int
-sys_waitpid(struct tcb *tcp)
+SYS_FUNC(waitpid)
 {
        return printwaitn(tcp, 3, 0);
 }
 
-int
-sys_wait4(struct tcb *tcp)
+SYS_FUNC(wait4)
 {
        return printwaitn(tcp, 4, 0);
 }
 
 #ifdef ALPHA
-int
-sys_osf_wait4(struct tcb *tcp)
+SYS_FUNC(osf_wait4)
 {
        return printwaitn(tcp, 4, 1);
 }
@@ -139,14 +142,12 @@ sys_osf_wait4(struct tcb *tcp)
 
 #include "xlat/waitid_types.h"
 
-int
-sys_waitid(struct tcb *tcp)
+SYS_FUNC(waitid)
 {
        if (entering(tcp)) {
                printxval(waitid_types, tcp->u_arg[0], "P_???");
                tprintf(", %ld, ", tcp->u_arg[1]);
-       }
-       else {
+       } else {
                /* siginfo */
                printsiginfo_at(tcp, tcp->u_arg[2]);
                /* options */
@@ -155,12 +156,7 @@ sys_waitid(struct tcb *tcp)
                if (tcp->s_ent->nargs > 4) {
                        /* usage */
                        tprints(", ");
-                       if (!tcp->u_arg[4])
-                               tprints("NULL");
-                       else if (tcp->u_error)
-                               tprintf("%#lx", tcp->u_arg[4]);
-                       else
-                               printrusage(tcp, tcp->u_arg[4]);
+                       printrusage(tcp, tcp->u_arg[4]);
                }
        }
        return 0;