]> granicus.if.org Git - procps-ng/commitdiff
library: correct 'vectorized' string logic, <PIDS> api
authorJim Warner <james.warner@comcast.net>
Thu, 25 Apr 2019 05:00:00 +0000 (00:00 -0500)
committerCraig Small <csmall@enc.com.au>
Thu, 16 May 2019 11:23:06 +0000 (21:23 +1000)
The commit referenced below addressed (some) anomalies
surrounding 'strv' pointers. However, there remained a
couple quirks involving a potential NULL return value.

Any NULL values returned from the old library readproc
guys would cause no real harm for newlib. But they did
produce the misleading "[ duplicate ENUM_ID ]" result.

The following all represent potential NULL results and
suggest shortcomings in testing of that earlier patch.

. kernel threads do not have cgroup, cmdline & environ
. even if present environ could require root to access

So, this patch reverts a portion of the earlier commit
and ensures when some vectored string is not available
a traditional dash ('-') is the 'strv' returned value.

[ and we'll also correct one typo in the header file ]

Reference(s):
. eliminated a final potential NULL, <PIDS> api
commit 09503dc59792ab0147de604ab48342b8508f2d7b

Signed-off-by: Jim Warner <james.warner@comcast.net>
proc/pids.c
proc/pids.h
proc/readproc.c
proc/readproc.h

index ae439347f22426f9e834ff9224d94757089527f9..7ca8109e16b7ee8c56160717ca2ee19ad8a923e0 100644 (file)
@@ -94,25 +94,6 @@ struct pids_info {
 
 // ___ Results 'Set' Support ||||||||||||||||||||||||||||||||||||||||||||||||||
 
-static char** pids_vectorize_this (const char* src) {
- #define pSZ  (sizeof(char*))
-    char *cpy, **vec;
-    size_t adj, tot;
-
-    tot = strlen(src) + 1;                       // prep for our vectors
-    if (tot < 1 || tot >= INT_MAX) tot = INT_MAX-1; // integer overflow?
-    adj = (pSZ-1) - ((tot + pSZ-1) & (pSZ-1));   // calc alignment bytes
-    cpy = calloc(1, tot + adj + (2 * pSZ));      // get new larger buffer
-    if (!cpy) return NULL;                       // oops, looks like ENOMEM
-    snprintf(cpy, tot, "%s", src);               // duplicate their string
-    vec = (char**)(cpy + tot + adj);             // prep pointer to pointers
-    *vec = cpy;                                  // point 1st vector to string
-    *(vec+1) = NULL;                             // null ptr 'list' delimit
-    return vec;                                  // ==> free(*vec) to dealloc
- #undef pSZ
-} // end: pids_vectorize_this
-
-
 #define setNAME(e) set_pids_ ## e
 #define setDECL(e) static void setNAME(e) \
     (struct pids_info *I, struct pids_result *R, proc_t *P)
@@ -136,7 +117,7 @@ static char** pids_vectorize_this (const char* src) {
    some sort of hint that they duplicated this char ** item ... */
 #define VEC_set(e,x) setDECL(e) { \
     if (NULL != P-> x) { R->result.strv = P-> x;  P-> x = NULL; } \
-    else { R->result.strv = pids_vectorize_this("[ duplicate " STRINGIFY(e) " ]"); \
+    else { R->result.strv = vectorize_this_str("[ duplicate " STRINGIFY(e) " ]"); \
       if (!R->result.str) I->seterr = 1; } }
 
 
index e8f7bcd78351bfed8a9bbd745e0998de3745285a..ae137d70161f3401325047b11fcab4be3a13fd56 100644 (file)
@@ -132,7 +132,7 @@ enum pids_item {
     PIDS_TICS_USER,         //  ull_int        stat: utime
     PIDS_TICS_USER_C,       //  ull_int        stat: utime + cutime
     PIDS_TIME_ALL,          //  ull_int      [ derived from (utime + stime) / hertz ]
-    PIDS_TIME_ELAPSED,      //  ull_int      [ derived from /proc/uptime - (starttime / hertz) }
+    PIDS_TIME_ELAPSED,      //  ull_int      [ derived from /proc/uptime - (starttime / hertz) ]
     PIDS_TIME_START,        //  ull_int        stat: starttime
     PIDS_TTY,               //    s_int        stat: tty_nr
     PIDS_TTY_NAME,          //      str      [ derived from TTY ]
index 73ca3469305c002c7e9cb09873742ffa752cc91a..39667c1656a23d18e2b84404bcc05c033769ddfb 100644 (file)
@@ -835,6 +835,34 @@ static int read_unvectored(char *restrict const dst, unsigned sz, const char* wh
 }
 
 
+char** vectorize_this_str (const char* src) {
+ #define pSZ  (sizeof(char*))
+    char *cpy, **vec;
+    size_t adj, tot;
+
+    tot = strlen(src) + 1;                       // prep for our vectors
+    if (tot < 1 || tot >= INT_MAX) tot = INT_MAX-1; // integer overflow?
+    adj = (pSZ-1) - ((tot + pSZ-1) & (pSZ-1));   // calc alignment bytes
+    cpy = calloc(1, tot + adj + (2 * pSZ));      // get new larger buffer
+    if (!cpy) return NULL;                       // oops, looks like ENOMEM
+    snprintf(cpy, tot, "%s", src);               // duplicate their string
+    vec = (char**)(cpy + tot + adj);             // prep pointer to pointers
+    *vec = cpy;                                  // point 1st vector to string
+    *(vec+1) = NULL;                             // null ptr 'list' delimit
+    return vec;                                  // ==> free(*vec) to dealloc
+ #undef pSZ
+}
+
+
+    // This littl' guy just serves those true vectorized fields
+    // ( when a /proc source field didn't exist )
+static int vectorize_dash_rc (char*** vec) {
+    if (!(*vec = vectorize_this_str("-")))
+        return 1;
+    return 0;
+}
+
+
     // This routine reads a 'cgroup' for the designated proc_t and
     // guarantees the caller a valid proc_t.cgroup pointer.
 static int fill_cgroup_cvt (const char* directory, proc_t *restrict p) {
@@ -1094,17 +1122,20 @@ static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict cons
     }
 
     if (flags & PROC_FILLENV)                   // read /proc/#/environ
-        p->environ_v = file2strvec(path, "environ");
+        if (!(p->environ_v = file2strvec(path, "environ")))
+            rc += vectorize_dash_rc(&p->environ_v);
     if (flags & PROC_EDITENVRCVT)
         rc += fill_environ_cvt(path, p);
 
     if (flags & PROC_FILLARG)                   // read /proc/#/cmdline
-        p->cmdline_v = file2strvec(path, "cmdline");
+        if (!(p->cmdline_v = file2strvec(path, "cmdline")))
+            rc += vectorize_dash_rc(&p->cmdline_v);
     if (flags & PROC_EDITCMDLCVT)
         rc += fill_cmdline_cvt(path, p);
 
     if ((flags & PROC_FILLCGROUP))              // read /proc/#/cgroup
-        p->cgroup_v = file2strvec(path, "cgroup");
+        if (!(p->cgroup_v = file2strvec(path, "cgroup")))
+            rc += vectorize_dash_rc(&p->cgroup_v);
     if (flags & PROC_EDITCGRPCVT)
         rc += fill_cgroup_cvt(path, p);
 
@@ -1202,17 +1233,20 @@ static proc_t* simple_readtask(PROCTAB *restrict const PT, const proc_t *restric
     if (!IS_THREAD(t)) {
 #endif
     if (flags & PROC_FILLARG)                       // read /proc/#/task/#/cmdline
-        t->cmdline_v = file2strvec(path, "cmdline");
+        if (!(t->cmdline_v = file2strvec(path, "cmdline")))
+            rc += vectorize_dash_rc(&t->cmdline_v);
     if (flags & PROC_EDITCMDLCVT)
         rc += fill_cmdline_cvt(path, t);
 
     if (flags & PROC_FILLENV)                       // read /proc/#/task/#/environ
-        t->environ_v = file2strvec(path, "environ");
+        if (!(t->environ_v = file2strvec(path, "environ")))
+            rc += vectorize_dash_rc(&t->environ_v);
     if (flags & PROC_EDITENVRCVT)
         rc += fill_environ_cvt(path, t);
 
     if ((flags & PROC_FILLCGROUP))                  // read /proc/#/task/#/cgroup
-        t->cgroup_v = file2strvec(path, "cgroup");
+        if (!(t->cgroup_v = file2strvec(path, "cgroup")))
+            rc += vectorize_dash_rc(&t->cgroup_v);
     if (flags & PROC_EDITCGRPCVT)
         rc += fill_cgroup_cvt(path, t);
 
index d3d21ac9bab0033211534a8d15feb89f3e27cf9d..9440096206c95bb63486ad919c223b9b053f5dda 100644 (file)
@@ -260,5 +260,6 @@ proc_t* readproc(PROCTAB *__restrict const PT, proc_t *__restrict p);
 proc_t* readeither(PROCTAB *__restrict const PT, proc_t *__restrict x);
 int look_up_our_self(proc_t *p);
 void closeproc(PROCTAB* PT);
+char** vectorize_this_str(const char* src);
 
 #endif