bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[sharutils PATCH] build: avoid range errors in use of ctype functions


From: Eric Blake
Subject: [sharutils PATCH] build: avoid range errors in use of ctype functions
Date: Tue, 6 Jan 2015 17:27:16 -0700

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 <address@hidden>
---
 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  <address@hidden>

+       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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]