From 605ea4a8f7460920b6de9e432757bd13f80f0dba Mon Sep 17 00:00:00 2001 From: Jim Warner Date: Tue, 30 Jun 2020 00:00:00 -0500 Subject: [PATCH] library: make that 'escape_str' private to our library In that commit referenced below, a promise was made to revisit an 'escape_str' function in efforts to make it private to the library. The problem was it's needed by both ps plus the library which is why it was exported. So, in an effort to remove it from libprocps.sym, this patch duplicates all the required code in ps/output.c. Now, each version can be made private to their caller. [ along the way we'll use this opportunity to remove ] [ the 'restrict' qualifiers from function parameters ] [ while swatting a compiler warning referenced below ] Reference(s): . April 2016, most escape functions made private commit d916d5db86cbbf552401026aab15c3663412d662 proc/escape.c: In function `escape_command': proc/escape.c:182:23: warning: initialization of `const char **' from incompatible pointer type `char **' [-Wincompatible-pointer-types] 182 | const char **lc = (char**)pp->cmdline; | ^ Signed-off-by: Jim Warner --- Makefile.am | 1 - proc/escape.c | 29 +++++------ proc/escape.h | 6 +-- proc/libprocps.sym | 1 - ps/common.h | 4 +- ps/output.c | 117 ++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 129 insertions(+), 29 deletions(-) diff --git a/Makefile.am b/Makefile.am index 3c21658e..e49dc10f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -276,7 +276,6 @@ proc_libprocps_la_includedir = $(includedir)/procps/ proc_libprocps_la_include_HEADERS = \ proc/devname.h \ proc/diskstats.h \ - proc/escape.h \ proc/meminfo.h \ proc/namespace.h \ proc/numa.h \ diff --git a/proc/escape.c b/proc/escape.c index 9546ed77..8d358403 100644 --- a/proc/escape.c +++ b/proc/escape.c @@ -17,21 +17,19 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include #include #include -#include +#include /* MB_CUR_MAX */ #include +#include +#include +#include #include "escape.h" #include "readproc.h" -#if (__GNU_LIBRARY__ >= 6) && (!defined(__UCLIBC__) || defined(__UCLIBC_HAS_WCHAR__)) -# include -# include -# include /* MB_CUR_MAX */ -# include -# include -#endif #define SECURE_ESCAPE_ARGS(dst, bytes, cells) do { \ if ((bytes) <= 0) return 0; \ @@ -42,8 +40,7 @@ } while (0) -#if (__GNU_LIBRARY__ >= 6) && (!defined(__UCLIBC__) || defined(__UCLIBC_HAS_WCHAR__)) -static int escape_str_utf8(char *restrict dst, const char *restrict src, int bufsize, int *maxcells){ +static int escape_str_utf8 (char *dst, const char *src, int bufsize, int *maxcells) { int my_cells = 0; int my_bytes = 0; mbstate_t s; @@ -107,10 +104,9 @@ static int escape_str_utf8(char *restrict dst, const char *restrict src, int buf return my_bytes; // bytes of text, excluding the NUL } -#endif /* __GNU_LIBRARY__ */ /* sanitize a string via one-way mangle */ -int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *maxcells){ +int escape_str (char *dst, const char *src, int bufsize, int *maxcells) { unsigned char c; int my_cells = 0; int my_bytes = 0; @@ -124,7 +120,6 @@ int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *m "????????????????????????????????" "????????????????????????????????"; -#if (__GNU_LIBRARY__ >= 6) && (!defined(__UCLIBC__) || defined(__UCLIBC_HAS_WCHAR__)) static int utf_init=0; if(utf_init==0){ @@ -136,7 +131,6 @@ int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *m /* UTF8 locales */ return escape_str_utf8(dst, src, bufsize, maxcells); } -#endif SECURE_ESCAPE_ARGS(dst, bufsize, *maxcells); @@ -163,7 +157,7 @@ int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *m // escape an argv or environment string array // // bytes arg means sizeof(buf) -static int escape_strlist(char *restrict dst, char *restrict const *restrict src, size_t bytes, int *cells){ +static int escape_strlist (char *dst, const char **src, size_t bytes, int *cells) { size_t i = 0; for(;;){ @@ -180,12 +174,12 @@ static int escape_strlist(char *restrict dst, char *restrict const *restrict src /////////////////////////////////////////////////// -int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, int bytes, int *cells, unsigned flags){ +int escape_command (char *const outbuf, const proc_t *pp, int bytes, int *cells, unsigned flags) { int overhead = 0; int end = 0; if(flags & ESC_ARGS){ - char **lc = (char**)pp->cmdline; + const char **lc = (const char**)pp->cmdline; if(lc && *lc) return escape_strlist(outbuf, lc, bytes, cells); } if(flags & ESC_BRACKETS){ @@ -217,4 +211,3 @@ int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, outbuf[end] = '\0'; return end; // bytes, not including the NUL } - diff --git a/proc/escape.h b/proc/escape.h index 75e830bf..684eba1d 100644 --- a/proc/escape.h +++ b/proc/escape.h @@ -3,14 +3,12 @@ #include "readproc.h" - #define ESC_ARGS 0x1 // try to use cmdline instead of cmd #define ESC_BRACKETS 0x2 // if using cmd, put '[' and ']' around it #define ESC_DEFUNCT 0x4 // mark zombies with " " -int escape_command(char *__restrict const outbuf, const proc_t *__restrict const pp, int bytes, int *cells, unsigned flags); +int escape_command (char *outbuf, const proc_t *pp, int bytes, int *cells, unsigned flags); -#define ESC_STRETCH 1 // since we mangle to '?' this is 1 (would be 4 for octal escapes) -int escape_str(char *__restrict dst, const char *__restrict src, int bufsize, int *maxcells); +int escape_str (char *dst, const char *src, int bufsize, int *maxcells); #endif diff --git a/proc/libprocps.sym b/proc/libprocps.sym index 8853048d..9cdbd248 100644 --- a/proc/libprocps.sym +++ b/proc/libprocps.sym @@ -1,6 +1,5 @@ LIBPROCPS_0 { global: - escape_str; fatal_proc_unmounted; procps_cpu_count; procps_diskstats_new; diff --git a/ps/common.h b/ps/common.h index 097b89d2..9511c32c 100644 --- a/ps/common.h +++ b/ps/common.h @@ -13,7 +13,6 @@ #define PROCPS_PS_H #include "../include/nls.h" -#include #include #include #include @@ -204,7 +203,6 @@ makEXT(noop) * Try not to overflow the output buffer: * 32 pages for env+cmd * 64 kB pages on IA-64 - * 4 chars for "\377", or 1 when mangling to '?' (ESC_STRETCH) * plus some slack for other stuff * That is about 8.5 MB on IA-64, or 0.6 MB on i386 * @@ -214,7 +212,7 @@ makEXT(noop) */ /* output buffer size */ -#define OUTBUF_SIZE (2 * 64*1024 * ESC_STRETCH) +#define OUTBUF_SIZE (2 * 64*1024) /******************* PS DEFINE *******************/ diff --git a/ps/output.c b/ps/output.c index b5945924..20f9a534 100644 --- a/ps/output.c +++ b/ps/output.c @@ -49,8 +49,10 @@ #if ENABLE_LIBSELINUX #include #endif +#include #include #include +#include #include #include #include @@ -58,13 +60,14 @@ #include #include #include +#include +#include #include #include #include #include - #include "../include/c.h" #include "common.h" @@ -79,7 +82,6 @@ static unsigned max_rightward = OUTBUF_SIZE-1; /* space for RIGHT stuff */ static unsigned max_leftward = OUTBUF_SIZE-1; /* space for LEFT stuff */ - static int wide_signals; /* true if we have room */ static time_t seconds_since_1970; @@ -135,6 +137,117 @@ static int escaped_copy(char *restrict dst, const char *restrict src, int bufsiz return n; } +// duplicated from proc/escape.c so both can be made private +static int escape_str_utf8 (char *dst, const char *src, int bufsize, int *maxcells) { + int my_cells = 0; + int my_bytes = 0; + mbstate_t s; + + SECURE_ESCAPE_ARGS(dst, bufsize, *maxcells); + + memset(&s, 0, sizeof (s)); + + for(;;) { + wchar_t wc; + int len = 0; + + if(my_cells >= *maxcells || my_bytes+1 >= bufsize) + break; + + if (!(len = mbrtowc (&wc, src, MB_CUR_MAX, &s))) + /* 'str' contains \0 */ + break; + + if (len < 0) { + /* invalid multibyte sequence -- zeroize state */ + memset (&s, 0, sizeof (s)); + *(dst++) = '?'; + src++; + my_cells++; + my_bytes++; + + } else if (len==1) { + /* non-multibyte */ + *(dst++) = isprint(*src) ? *src : '?'; + src++; + my_cells++; + my_bytes++; + + } else if (!iswprint(wc)) { + /* multibyte - no printable */ + *(dst++) = '?'; + src+=len; + my_cells++; + my_bytes++; + + } else { + /* multibyte - maybe, kinda "printable" */ + int wlen = wcwidth(wc); + // Got space? + if (wlen > *maxcells-my_cells || len >= bufsize-(my_bytes+1)) break; + // safe multibyte + memcpy(dst, src, len); + dst += len; + src += len; + my_bytes += len; + if (wlen > 0) my_cells += wlen; + } + //fprintf(stdout, "cells: %d\n", my_cells); + } + *dst = '\0'; + + // fprintf(stderr, "maxcells: %d, my_cells; %d\n", *maxcells, my_cells); + + *maxcells -= my_cells; + return my_bytes; // bytes of text, excluding the NUL +} + +// duplicated from proc/escape.c so both can be made private +static int escape_str (char *dst, const char *src, int bufsize, int *maxcells) { + unsigned char c; + int my_cells = 0; + int my_bytes = 0; + const char codes[] = + "Z..............................." + "||||||||||||||||||||||||||||||||" + "||||||||||||||||||||||||||||||||" + "|||||||||||||||||||||||||||||||." + "????????????????????????????????" + "????????????????????????????????" + "????????????????????????????????" + "????????????????????????????????"; + static int utf_init=0; + + if(utf_init==0){ + /* first call -- check if UTF stuff is usable */ + char *enc = nl_langinfo(CODESET); + utf_init = enc && strcasecmp(enc, "UTF-8")==0 ? 1 : -1; + } + if (utf_init==1 && MB_CUR_MAX>1) { + /* UTF8 locales */ + return escape_str_utf8(dst, src, bufsize, maxcells); + } + + SECURE_ESCAPE_ARGS(dst, bufsize, *maxcells); + + if(bufsize > *maxcells+1) bufsize=*maxcells+1; // FIXME: assumes 8-bit locale + + for(;;){ + if(my_cells >= *maxcells || my_bytes+1 >= bufsize) + break; + c = (unsigned char) *(src++); + if(!c) break; + if(codes[c]!='|') c=codes[c]; + my_cells++; + my_bytes++; + *(dst++) = c; + } + *dst = '\0'; + + *maxcells -= my_cells; + return my_bytes; // bytes of text, excluding the NUL +} + /***************************************************************************/ /************ Lots of format functions, starting with the NOP **************/ -- 2.40.0