From a9bfb186eb35770c8e3159fabac0b83342643ef6 Mon Sep 17 00:00:00 2001 From: Jim Warner Date: Thu, 25 Apr 2019 00:00:00 -0500 Subject: [PATCH] library: correct 'vectorized' string logic, api 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, api commit 09503dc59792ab0147de604ab48342b8508f2d7b Signed-off-by: Jim Warner --- proc/pids.c | 21 +-------------------- proc/pids.h | 2 +- proc/readproc.c | 46 ++++++++++++++++++++++++++++++++++++++++------ proc/readproc.h | 1 + 4 files changed, 43 insertions(+), 27 deletions(-) diff --git a/proc/pids.c b/proc/pids.c index ae439347..7ca8109e 100644 --- a/proc/pids.c +++ b/proc/pids.c @@ -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; } } diff --git a/proc/pids.h b/proc/pids.h index e8f7bcd7..ae137d70 100644 --- a/proc/pids.h +++ b/proc/pids.h @@ -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 ] diff --git a/proc/readproc.c b/proc/readproc.c index 73ca3469..39667c16 100644 --- a/proc/readproc.c +++ b/proc/readproc.c @@ -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); diff --git a/proc/readproc.h b/proc/readproc.h index d3d21ac9..94400962 100644 --- a/proc/readproc.h +++ b/proc/readproc.h @@ -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