]> granicus.if.org Git - procps-ng/commitdiff
top: address a defect with the library PROC_PID flag
authorJim Warner <james.warner@comcast.net>
Sun, 15 Apr 2012 20:15:15 +0000 (15:15 -0500)
committerCraig Small <csmall@enc.com.au>
Wed, 25 Apr 2012 03:46:17 +0000 (13:46 +1000)
The library does not weed out potential duplicate PID
values when sampling with the PROC_PID flag.  This was
treated as merely an inefficiency by top and safely
ignored prior to the advent of forest view mode.

Now, however, if the -p switch duplicates certain PIDs,
*and* those processes have no PPID, *and* top's forest
view mode is active or activated, then a SEGV will be
generated (and caught).

This rather obscure buglet is thus limited to pid #1
(/sbin/init) and pid #2 (kthreadd).  With any other
duplicate PIDs the worse case scenario was a '?' in
place of the usual forest view artwork.

This commit silently ignores any duplicate process ids
and thereby avoids the potential segmemtation fault.

Signed-off-by: Jim Warner <james.warner@comcast.net>
top/top.c

index 4e782749d64c9ac3d73754ff9e1861bee660fdaf..108805ba6bfce0cd0e638996b7a74e6765c442d8 100644 (file)
--- a/top/top.c
+++ b/top/top.c
@@ -2420,20 +2420,20 @@ static void parse_args (char **args) {
                break;
             case 'p':
                if (Curwin->usrseltyp) error_exit(N_txt(SELECT_clash_txt));
-               do {
+               do { int i, pid;
                   if (cp[1]) cp++;
                   else if (*args) cp = *args++;
                   else error_exit(fmtmk(N_fmt(MISSING_args_fmt), ch));
                   if (Monpidsidx >= MONPIDMAX)
                      error_exit(fmtmk(N_fmt(LIMIT_exceed_fmt), MONPIDMAX));
-                  if (1 != sscanf(cp, "%d", &Monpids[Monpidsidx])
-                  || 0 > Monpids[Monpidsidx])
+                  if (1 != sscanf(cp, "%d", &pid) || 0 > pid)
                      error_exit(fmtmk(N_fmt(BAD_mon_pids_fmt), cp));
-                  if (!Monpids[Monpidsidx])
-                     Monpids[Monpidsidx] = getpid();
-                  Monpidsidx++;
-                  if (!(p = strchr(cp, ',')))
-                     break;
+                  if (!pid) pid = getpid();
+                  for (i = 0; i < Monpidsidx; i++)
+                     if (Monpids[i] == pid) goto next_pid;
+                  Monpids[Monpidsidx++] = pid;
+               next_pid:
+                  if (!(p = strchr(cp, ','))) break;
                   cp = p;
                } while (*cp);
                break;