[sharutils PATCH] build: avoid range errors in use of ctype functions
Eric Blake <[email protected]> Tue, 6 Jan 2015 17:27:16 -0700
| Newsgroups | gmane.comp.gnu.utils.bugs |
|---|---|
| Message-ID | <[email protected]> |
On platforms where 'char' is signed, using ctype functions on 'char' arguments produces undefined behavior for arguments that are larger than 127. In particular, on Cygwin, isspace((char)255) MUST return the same 0 result as isspace(EOF), while there are some single-byte locales in which isspace((unsigned char)255) returns 1. POSIX is explicit that the ctype functions are only well-defined on the range of EOF plus the values of unsigned char. There are also a number of ctype abuses in libopts/makeshell.c, but as that file is generated rather than owned by sharutils, it will need to be fixed upstream in the autogen package. * src/shar.c (to_uchar): New helper, borrowed from coreutils. (ISASCII, IS_GRAPH, process_shar_input, trim): Avoid range errors. Signed-off-by: Eric Blake <[email protected]> --- ChangeLog | 4 ++++ src/shar.c | 21 +++++++++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4c7fa2a..8e0e590 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2015-01-06 Eric Blake <[email protected]> + build: avoid range errors in use of ctype functions + * src/shar.c (to_uchar): New helper, borrowed from coreutils. + (ISASCII, IS_GRAPH, process_shar_input, trim): Avoid range errors. + build: avoid error message failure on 64-bit hosts * src/scribble.c (xscribble_get): Use correct specifier. diff --git a/src/shar.c b/src/shar.c index e2b315a..91e7e53 100644 --- a/src/shar.c +++ b/src/shar.c @@ -85,14 +85,19 @@ static const char cright_years_z[] = /* System related declarations. */ +/* Convert a possibly-signed character to an unsigned character. This is + a bit safer than casting to unsigned char, since it catches some type + errors that the cast doesn't. */ +static inline unsigned char to_uchar (char ch) { return ch; } + #if STDC_HEADERS # define ISASCII(Char) 1 #else # ifdef isascii -# define ISASCII(Char) isascii (Char) +# define ISASCII(Char) isascii (to_uchar (Char)) # else # if HAVE_ISASCII -# define ISASCII(Char) isascii (Char) +# define ISASCII(Char) isascii (to_uchar (Char)) # else # define ISASCII(Char) ((Char) & 0x7f == (unsigned char) (Char)) # endif @@ -100,9 +105,9 @@ static const char cright_years_z[] = #endif #ifdef isgraph -#define IS_GRAPH(_c) isgraph (_c) +#define IS_GRAPH(_c) isgraph (to_uchar (_c)) #else -#define IS_GRAPH(_c) (isprint (_c) && !isspace (_c)) +#define IS_GRAPH(_c) (isprint (to_uchar (_c)) && !isspace (to_uchar (_c))) #endif struct tm *localtime (); @@ -1580,8 +1585,8 @@ process_shar_input (FILE * input, off_t * size_left, int * split_flag, * Find the start of the last token */ e = p + strlen(p); - while ( isspace (e[-1]) && (e > p)) e--; - while (! isspace (e[-1]) && (e > p)) e--; + while ( isspace (to_uchar (e[-1])) && (e > p)) e--; + while (! isspace (to_uchar (e[-1])) && (e > p)) e--; fwrite (p, e - p, 1, output); fprintf (output, "_sh%05d/%s\n", (int)sharpid, cmpr_state->cmpr_mode); } @@ -2079,7 +2084,7 @@ static char * trim (char * pz) { char * res; - while (isspace (*pz)) pz++; + while (isspace (to_uchar (*pz))) pz++; switch (*pz) { case NUL: @@ -2088,7 +2093,7 @@ trim (char * pz) } res = pz; pz += strlen (pz); - while (isspace (pz[-1])) pz--; + while (isspace (to_uchar (pz[-1]))) pz--; *pz = NUL; return res; } -- 2.1.0