From: Kevin McCarthy <[email protected]>

Add check_sec.sh test for isspace.

For more background on this change see commit
40228035ce0f397e682c985201df51dead3be3dc and the thread in mutt-users
starting at <[email protected]>:
https://lists.mutt.org/pipermail/mutt-users/Week-of-Mon-20220801/003616.html

On some platforms, isspace() returns true for unexpected 8-bit chars,
such as 0xa0 or 0x85.  Given that, I don't think Mutt should be using
it in most (if not all) cases, and especially not when parsing
protocols and emails.  (Note: iswspace() is a different story; enter.c
makes use of wchar_t, for instance.)

I originally kept the locale checks in a few prompts and the builtin
editor.  But the more I considered, the more I decided it was better
to explicitly use the ASCII version in each case.

I've kept the locale-specific versions in lib.h, in case it it needs
to be reverted in a few places.
---
NOTE: This is a request for comments.  I need to test more, and clean up
the commit message, but I wanted to get feedback from others on the list
about this change.


 browser.c      |  4 ++--
 check_sec.sh   |  1 +
 crypt.c        |  4 ++--
 edit.c         |  4 ++--
 from.c         | 16 ++++++++--------
 handler.c      |  4 ++--
 headers.c      |  2 +-
 help.c         |  2 +-
 hook.c         |  4 ++--
 imap/command.c | 16 ++++++++--------
 imap/imap.c    | 12 ++++++------
 imap/message.c | 16 ++++++++--------
 imap/util.c    |  6 +++---
 init.c         | 26 +++++++++++++-------------
 keymap.c       |  2 +-
 lib.c          |  8 ++++----
 lib.h          | 41 ++++++++++++++++++++++++++++-------------
 mbyte.c        |  4 ++--
 mutt_lisp.c    | 10 +++++-----
 muttlib.c      |  2 +-
 pager.c        |  2 +-
 parse.c        |  6 +++---
 pattern.c      | 16 ++++++++--------
 pgp.c          |  2 +-
 pgpmicalg.c    |  2 +-
 pop_lib.c      |  2 +-
 rfc1524.c      |  6 +++---
 sendlib.c      |  6 +++---
 28 files changed, 121 insertions(+), 105 deletions(-)

diff --git a/browser.c b/browser.c
index 86653824..9ff9fc60 100644
--- a/browser.c
+++ b/browser.c
@@ -1348,11 +1348,11 @@ void _mutt_buffer_select_file (BUFFER *f, int flags, 
char ***files, int *numfile
           /* assume that the user wants to see everything */
           if (!(mutt_buffer_len (buf)))
             mutt_buffer_strcpy (buf, ".");
-          SKIPWS (s);
+          SKIP_ASCII_WS (s);
           if (*s == '!')
           {
             s++;
-            SKIPWS (s);
+            SKIP_ASCII_WS (s);
             not = 1;
           }
 
diff --git a/check_sec.sh b/check_sec.sh
index 3bd08804..fe7f8b48 100755
--- a/check_sec.sh
+++ b/check_sec.sh
@@ -38,6 +38,7 @@ do_check '\<sprintf.*%s' __SPRINTF_CHECKED__ "Alert: 
Unchecked sprintf calls."
 do_check '\<strncat' __STRNCAT_CHECKED__ "You probably meant safe_strcat here."
 do_check '\<safe_free' __SAFE_FREE_CHECKED__ "You probably meant FREE here."
 do_check '\<FREE[ ]?\([^&]' __FREE_CHECKED__ "You probably meant FREE(&...) 
here."
+do_check '\<isspace' __SAFE_ISSPACE_CHECKED__ "You probably meant IS_ASCII_WS 
here."
 
 # don't do this check on others' code.
 do_check_files '\<(malloc|realloc|free|strdup)[        ]*\(' __MEM_CHECKED__ 
"Alert: Use of traditional memory management calls." \
diff --git a/crypt.c b/crypt.c
index cc6c376d..4adf436c 100644
--- a/crypt.c
+++ b/crypt.c
@@ -1221,7 +1221,7 @@ const char* crypt_get_fingerprint_or_id (char *p, const 
char **pphint,
    * if an ID was found and to simplify logic in the key loop's inner
    * condition of the caller. */
 
-  pf = mutt_skip_whitespace (p);
+  pf = mutt_skip_ascii_ws (p);
   if (!mutt_strncasecmp (pf, "0x", 2))
     pf += 2;
 
@@ -1258,7 +1258,7 @@ const char* crypt_get_fingerprint_or_id (char *p, const 
char **pphint,
     s1 = s2 = pfcopy;
     do
     {
-      *(s1++) = *(s2 = mutt_skip_whitespace (s2));
+      *(s1++) = *(s2 = mutt_skip_ascii_ws (s2));
     } while (*(s2++));
 
     phint = pfcopy;
diff --git a/edit.c b/edit.c
index 143118e4..b8db756e 100644
--- a/edit.c
+++ b/edit.c
@@ -360,11 +360,11 @@ int mutt_builtin_editor (SEND_CONTEXT *sctx)
     {
       /* remove trailing whitespace from the line */
       p = tmp + mutt_strlen (tmp) - 1;
-      while (p >= tmp && ISSPACE (*p))
+      while (p >= tmp && IS_ASCII_WS (*p))
         *p-- = 0;
 
       p = tmp + 2;
-      SKIPWS (p);
+      SKIP_ASCII_WS (p);
 
       switch (tmp[1])
       {
diff --git a/from.c b/from.c
index 662709ba..6426cab1 100644
--- a/from.c
+++ b/from.c
@@ -28,9 +28,9 @@
 
 static const char *next_word (const char *s)
 {
-  while (*s && !ISSPACE (*s))
+  while (*s && !IS_ASCII_WS (*s))
     s++;
-  SKIPWS (s);
+  SKIP_ASCII_WS (s);
   return s;
 }
 
@@ -38,9 +38,9 @@ static const char *prev_word (const char * const bos, const 
char *cur)
 {
   if (cur <= bos)
     return bos;
-  while (cur > bos && ISSPACE (*(cur-1)))
+  while (cur > bos && IS_ASCII_WS (*(cur-1)))
     cur--;
-  while (cur > bos && !ISSPACE (*(cur-1)))
+  while (cur > bos && !IS_ASCII_WS (*(cur-1)))
     cur--;
   return cur;
 }
@@ -59,7 +59,7 @@ static int is_day_name (const char *s)
 {
   int i;
 
-  if ((strlen (s) < 3) || !*(s + 3) || !ISSPACE (*(s+3)))
+  if ((strlen (s) < 3) || !*(s + 3) || !IS_ASCII_WS (*(s+3)))
     return 0;
   for (i=0; i<7; i++)
     if (mutt_strncasecmp (s, Weekdays[i], 3) == 0)
@@ -100,7 +100,7 @@ static int is_from_forward_scan (const char *s,
     size_t len;
     short q = 0;
 
-    for (p = s; *p && (q || !ISSPACE (*p)); p++)
+    for (p = s; *p && (q || !IS_ASCII_WS (*p)); p++)
     {
       if (*p == '\\')
       {
@@ -137,7 +137,7 @@ static int is_from_forward_scan (const char *s,
     }
 
     s = p + 1;
-    SKIPWS (s);
+    SKIP_ASCII_WS (s);
     if (!*s)
       return 0;
 
@@ -268,7 +268,7 @@ static int is_from_reverse_scan (const char * const bos,
   }
 
   /* return path? */
-  while (cur > bos && ISSPACE (*(cur-1)))
+  while (cur > bos && IS_ASCII_WS (*(cur-1)))
     cur--;
   if (cur != bos && path)
   {
diff --git a/handler.c b/handler.c
index 58a3f077..ebba86d6 100644
--- a/handler.c
+++ b/handler.c
@@ -269,7 +269,7 @@ static void mutt_decode_quoted (STATE *s, LOFF_T len, int 
istext, iconv_t cd)
     /* chop trailing whitespace if we got the full line */
     if (last == '\n')
     {
-      while (linelen > 0 && ISSPACE (line[linelen-1]))
+      while (linelen > 0 && IS_ASCII_WS (line[linelen-1]))
         linelen--;
       line[linelen]=0;
     }
@@ -390,7 +390,7 @@ static void mutt_decode_uuencoded (STATE *s, LOFF_T len, 
int istext, iconv_t cd)
     if ((fgets(tmps, sizeof(tmps), s->fpin)) == NULL)
       goto cleanup;
     len -= mutt_strlen(tmps);
-    if ((!mutt_strncmp (tmps, "begin", 5)) && ISSPACE (tmps[5]))
+    if ((!mutt_strncmp (tmps, "begin", 5)) && IS_ASCII_WS (tmps[5]))
       break;
   }
   while (len > 0)
diff --git a/headers.c b/headers.c
index f62dee8c..dbec2f1d 100644
--- a/headers.c
+++ b/headers.c
@@ -325,7 +325,7 @@ int mutt_label_message(HEADER *hdr)
     return 0;
 
   new = buf;
-  SKIPWS(new);
+  SKIP_ASCII_WS(new);
   if (*new == '\0')
     new = NULL;
 
diff --git a/help.c b/help.c
index 6e6bd718..5094313c 100644
--- a/help.c
+++ b/help.c
@@ -256,7 +256,7 @@ static void format_line (FILE *f, int ismacro,
 
       if (ismacro >= 0)
       {
-        SKIPWS(t3);
+        SKIP_ASCII_WS(t3);
         n = get_wrapped_width (t3, n);
       }
 
diff --git a/hook.c b/hook.c
index feb9e80e..5db5b307 100644
--- a/hook.c
+++ b/hook.c
@@ -63,7 +63,7 @@ int mutt_parse_hook (BUFFER *buf, BUFFER *s, union 
pointer_long_t udata, BUFFER
   if (*s->dptr == '!')
   {
     s->dptr++;
-    SKIPWS (s->dptr);
+    SKIP_ASCII_WS (s->dptr);
     not = 1;
   }
 
@@ -346,7 +346,7 @@ int mutt_parse_idxfmt_hook (BUFFER *buf, BUFFER *s, union 
pointer_long_t udata,
   if (*s->dptr == '!')
   {
     s->dptr++;
-    SKIPWS (s->dptr);
+    SKIP_ASCII_WS (s->dptr);
     not = 1;
   }
   mutt_extract_token (pattern, s, 0);
diff --git a/imap/command.c b/imap/command.c
index b85304c7..e9b632b2 100644
--- a/imap/command.c
+++ b/imap/command.c
@@ -591,7 +591,7 @@ static int cmd_handle_untagged (IMAP_DATA* idata)
 
     /* server shut down our connection */
     s += 3;
-    SKIPWS (s);
+    SKIP_ASCII_WS (s);
     mutt_error ("%s", s);
     mutt_sleep (2);
     cmd_handle_fatal (idata);
@@ -812,7 +812,7 @@ static void cmd_parse_fetch (IMAP_DATA* idata, char* s)
 
   while (*s)
   {
-    SKIPWS (s);
+    SKIP_ASCII_WS (s);
 
     if (ascii_strncasecmp ("FLAGS", s, 5) == 0)
     {
@@ -821,7 +821,7 @@ static void cmd_parse_fetch (IMAP_DATA* idata, char* s)
         break;
 
       s += 5;
-      SKIPWS(s);
+      SKIP_ASCII_WS(s);
       if (*s != '(')
       {
         muttdbg(1, "bogus FLAGS response: %s", s);
@@ -841,7 +841,7 @@ static void cmd_parse_fetch (IMAP_DATA* idata, char* s)
     else if (ascii_strncasecmp ("UID", s, 3) == 0)
     {
       s += 3;
-      SKIPWS (s);
+      SKIP_ASCII_WS (s);
       if (mutt_atoui (s, &uid, MUTT_ATOI_ALLOW_TRAILING) < 0)
       {
         muttdbg(1, "cmd_parse_fetch: Illegal UID.  Skipping update.");
@@ -860,7 +860,7 @@ static void cmd_parse_fetch (IMAP_DATA* idata, char* s)
     else if (ascii_strncasecmp ("MODSEQ", s, 6) == 0)
     {
       s += 6;
-      SKIPWS(s);
+      SKIP_ASCII_WS(s);
       if (*s != '(')
       {
         muttdbg (1, "bogus MODSEQ response: %s", s);
@@ -970,7 +970,7 @@ static void cmd_parse_list (IMAP_DATA* idata, char* s)
     {
       *s = '\0';
       s++;
-      SKIPWS(s);
+      SKIP_ASCII_WS(s);
     }
   }
   else
@@ -1041,7 +1041,7 @@ static void cmd_parse_myrights (IMAP_DATA* idata, const 
char* s)
   /* zero out current rights set */
   memset (idata->ctx->rights, 0, sizeof (idata->ctx->rights));
 
-  while (*s && !isspace((unsigned char) *s))
+  while (*s && !IS_ASCII_WS((unsigned char) *s))
   {
     switch (*s)
     {
@@ -1150,7 +1150,7 @@ static void cmd_parse_status (IMAP_DATA* idata, char* s)
     s = mailbox + litlen;
     *s = '\0';
     s++;
-    SKIPWS(s);
+    SKIP_ASCII_WS(s);
   }
   else
   {
diff --git a/imap/imap.c b/imap/imap.c
index 3368112d..89694067 100644
--- a/imap/imap.c
+++ b/imap/imap.c
@@ -749,7 +749,7 @@ static char* imap_get_flags (LIST** hflags, char* s)
     return NULL;
   }
   s += 5;
-  SKIPWS(s);
+  SKIP_ASCII_WS(s);
   if (*s != '(')
   {
     muttdbg (1, "bogus FLAGS response: %s", s);
@@ -763,9 +763,9 @@ static char* imap_get_flags (LIST** hflags, char* s)
   while (*s && *s != ')')
   {
     s++;
-    SKIPWS(s);
+    SKIP_ASCII_WS(s);
     flag_word = s;
-    while (*s && (*s != ')') && !ISSPACE (*s))
+    while (*s && (*s != ')') && !IS_ASCII_WS (*s))
       s++;
     ctmp = *s;
     *s = '\0';
@@ -1398,7 +1398,7 @@ int imap_sync_message_for_copy (IMAP_DATA *idata, HEADER 
*hdr, BUFFER *cmd,
   if (mutt_bit_isset (idata->ctx->rights, MUTT_ACL_WRITE))
     imap_add_keywords (flags, hdr, idata->flags, sizeof (flags));
 
-  mutt_remove_trailing_ws (flags);
+  mutt_remove_trailing_ascii_ws (flags);
 
   /* UW-IMAP is OK with null flags, Cyrus isn't. The only solution is to
    * explicitly revoke all system flags (if we have permission) */
@@ -1411,7 +1411,7 @@ int imap_sync_message_for_copy (IMAP_DATA *idata, HEADER 
*hdr, BUFFER *cmd,
     imap_set_flag (idata, MUTT_ACL_DELETE, !HEADER_DATA(hdr)->deleted,
                    "\\Deleted ", flags, sizeof (flags));
 
-    mutt_remove_trailing_ws (flags);
+    mutt_remove_trailing_ascii_ws (flags);
 
     mutt_buffer_addstr (cmd, " -FLAGS.SILENT (");
   }
@@ -2247,7 +2247,7 @@ static int imap_compile_search (const pattern_t* pat, 
BUFFER* buf)
         /* and field */
         *delim = ':';
         delim++;
-        SKIPWS(delim);
+        SKIP_ASCII_WS(delim);
         imap_quote_string (term, sizeof (term), delim);
         mutt_buffer_addstr (buf, term);
         break;
diff --git a/imap/message.c b/imap/message.c
index 6260113d..dbc91034 100644
--- a/imap/message.c
+++ b/imap/message.c
@@ -1924,7 +1924,7 @@ static int msg_parse_fetch (IMAP_HEADER *h, char *s)
 
   while (*s)
   {
-    SKIPWS (s);
+    SKIP_ASCII_WS (s);
 
     if (ascii_strncasecmp ("FLAGS", s, 5) == 0)
     {
@@ -1934,7 +1934,7 @@ static int msg_parse_fetch (IMAP_HEADER *h, char *s)
     else if (ascii_strncasecmp ("UID", s, 3) == 0)
     {
       s += 3;
-      SKIPWS (s);
+      SKIP_ASCII_WS (s);
       if (mutt_atoui (s, &h->data->uid, MUTT_ATOI_ALLOW_TRAILING) < 0)
         return -1;
 
@@ -1943,7 +1943,7 @@ static int msg_parse_fetch (IMAP_HEADER *h, char *s)
     else if (ascii_strncasecmp ("INTERNALDATE", s, 12) == 0)
     {
       s += 12;
-      SKIPWS (s);
+      SKIP_ASCII_WS (s);
       if (*s != '\"')
       {
         muttdbg(1, "bogus INTERNALDATE entry: %s", s);
@@ -1966,7 +1966,7 @@ static int msg_parse_fetch (IMAP_HEADER *h, char *s)
     else if (ascii_strncasecmp ("RFC822.SIZE", s, 11) == 0)
     {
       s += 11;
-      SKIPWS (s);
+      SKIP_ASCII_WS (s);
       ptmp = tmp;
       dlen = sizeof(tmp) - 1;
       while (isdigit ((unsigned char) *s) && dlen)
@@ -1987,7 +1987,7 @@ static int msg_parse_fetch (IMAP_HEADER *h, char *s)
     else if (ascii_strncasecmp ("MODSEQ", s, 6) == 0)
     {
       s += 6;
-      SKIPWS(s);
+      SKIP_ASCII_WS(s);
       if (*s != '(')
       {
         muttdbg (1, "bogus MODSEQ response: %s", s);
@@ -2029,7 +2029,7 @@ static char* msg_parse_flags (IMAP_HEADER* h, char* s)
     return NULL;
   }
   s += 5;
-  SKIPWS(s);
+  SKIP_ASCII_WS(s);
   if (*s != '(')
   {
     muttdbg (1, "bogus FLAGS response: %s", s);
@@ -2079,14 +2079,14 @@ static char* msg_parse_flags (IMAP_HEADER* h, char* s)
       if (!hd->keywords)
         hd->keywords = mutt_new_list ();
 
-      while (*s && !ISSPACE (*s) && *s != ')')
+      while (*s && !IS_ASCII_WS (*s) && *s != ')')
         s++;
       ctmp = *s;
       *s = '\0';
       mutt_add_list (hd->keywords, flag_word);
       *s = ctmp;
     }
-    SKIPWS(s);
+    SKIP_ASCII_WS(s);
   }
 
   /* wrap up, or note bad flags response */
diff --git a/imap/util.c b/imap/util.c
index 8d8b9fb7..9bb850b5 100644
--- a/imap/util.c
+++ b/imap/util.c
@@ -656,12 +656,12 @@ char *imap_next_word (char *s)
     }
     if (*s == '\"')
       quoted = quoted ? 0 : 1;
-    if (!quoted && ISSPACE (*s))
+    if (!quoted && IS_ASCII_WS (*s))
       break;
     s++;
   }
 
-  SKIPWS (s);
+  SKIP_ASCII_WS (s);
   return s;
 }
 
@@ -889,7 +889,7 @@ int imap_wordcasecmp(const char *a, const char *b)
   tmp[SHORT_STRING-1] = 0;
   for (i=0;i < SHORT_STRING-2;i++,s++)
   {
-    if (!*s || ISSPACE(*s))
+    if (!*s || IS_ASCII_WS(*s))
     {
       tmp[i] = 0;
       break;
diff --git a/init.c b/init.c
index 62aa4993..4a297a6e 100644
--- a/init.c
+++ b/init.c
@@ -184,13 +184,13 @@ int mutt_extract_token (BUFFER *dest, BUFFER *tok, int 
flags)
     mutt_buffer_increase_size (dest, STRING);
   mutt_buffer_clear (dest);
 
-  SKIPWS (tok->dptr);
+  SKIP_ASCII_WS (tok->dptr);
 
   if ((*tok->dptr == '(') && !(flags & MUTT_TOKEN_NOLISP) &&
       ((flags & MUTT_TOKEN_LISP) || option (OPTMUTTLISPINLINEEVAL)))
   {
     int rc = mutt_lisp_eval_list (dest, tok);
-    SKIPWS (tok->dptr);
+    SKIP_ASCII_WS (tok->dptr);
     return rc;
   }
 
@@ -198,7 +198,7 @@ int mutt_extract_token (BUFFER *dest, BUFFER *tok, int 
flags)
   {
     if (!qc)
     {
-      if ((ISSPACE (ch) && !(flags & MUTT_TOKEN_SPACE)) ||
+      if ((IS_ASCII_WS (ch) && !(flags & MUTT_TOKEN_SPACE)) ||
           (ch == '#' && !(flags & MUTT_TOKEN_COMMENT)) ||
           (ch == '=' && (flags & MUTT_TOKEN_EQUAL)) ||
           (ch == ';' && !(flags & MUTT_TOKEN_SEMICOLON)) ||
@@ -391,7 +391,7 @@ int mutt_extract_token (BUFFER *dest, BUFFER *tok, int 
flags)
     else
       mutt_buffer_addch (dest, ch);
   }
-  SKIPWS (tok->dptr);
+  SKIP_ASCII_WS (tok->dptr);
   return 0;
 }
 
@@ -2226,7 +2226,7 @@ static int parse_setenv(BUFFER *tmp, BUFFER *s, union 
pointer_long_t udata, BUFF
   if (*s->dptr == '=')
   {
     s->dptr++;
-    SKIPWS (s->dptr);
+    SKIP_ASCII_WS (s->dptr);
   }
 
   if (!MoreArgs (s))
@@ -2293,7 +2293,7 @@ static int parse_set (BUFFER *tmp, BUFFER *s, union 
pointer_long_t udata, BUFFER
       snprintf (err->data, err->dsize, _("%s: unknown variable"), tmp->data);
       return (-1);
     }
-    SKIPWS (s->dptr);
+    SKIP_ASCII_WS (s->dptr);
 
     if (reset)
     {
@@ -3067,7 +3067,7 @@ int mutt_parse_rc_buffer (BUFFER *line, BUFFER *token, 
BUFFER *err)
   /* Read from the beginning of line->data */
   mutt_buffer_rewind (line);
 
-  SKIPWS (line->dptr);
+  SKIP_ASCII_WS (line->dptr);
   while (*line->dptr)
   {
     if (*line->dptr == '#')
@@ -3165,11 +3165,11 @@ int mutt_command_complete (char *buffer, size_t len, 
int pos, int numtabs)
   int spaces; /* keep track of the number of leading spaces on the line */
   myvar_t *myv;
 
-  SKIPWS (buffer);
+  SKIP_ASCII_WS (buffer);
   spaces = buffer - pt;
 
   pt = buffer + pos - spaces;
-  while ((pt > buffer) && !isspace ((unsigned char) *pt))
+  while ((pt > buffer) && !IS_ASCII_WS ((unsigned char) *pt))
     pt--;
 
   if (pt == buffer) /* complete cmd */
@@ -3312,7 +3312,7 @@ int mutt_command_complete (char *buffer, size_t len, int 
pos, int numtabs)
   else if (!mutt_strncmp (buffer, "cd", 2))
   {
     pt = buffer + 2;
-    SKIPWS (pt);
+    SKIP_ASCII_WS (pt);
     if (numtabs == 1)
     {
       if (mutt_complete (pt, buffer + len - pt - spaces))
@@ -3364,11 +3364,11 @@ int mutt_var_value_complete (char *buffer, size_t len, 
int pos)
   if (buffer[0] == 0)
     return 0;
 
-  SKIPWS (buffer);
+  SKIP_ASCII_WS (buffer);
   spaces = buffer - pt;
 
   pt = buffer + pos - spaces;
-  while ((pt > buffer) && !isspace ((unsigned char) *pt))
+  while ((pt > buffer) && !IS_ASCII_WS ((unsigned char) *pt))
     pt--;
   pt++; /* move past the space */
   if (*pt == '=') /* abort if no var before the '=' */
@@ -4137,7 +4137,7 @@ int mutt_label_complete (char *buffer, size_t len, int 
numtabs)
   if (!Context || !Context->label_hash)
     return 0;
 
-  SKIPWS (buffer);
+  SKIP_ASCII_WS (buffer);
   spaces = buffer - pt;
 
   /* first TAB. Collect all the matches */
diff --git a/keymap.c b/keymap.c
index 2c9cdcc0..0a63e4b1 100644
--- a/keymap.c
+++ b/keymap.c
@@ -177,7 +177,7 @@ static int parse_keycode (const char *s)
   char *endChar;
   long int result = strtol(s+1, &endChar, 8);
   /* allow trailing whitespace, eg.  < 1001 > */
-  while (ISSPACE(*endChar))
+  while (IS_ASCII_WS(*endChar))
     ++endChar;
   /* negative keycodes don't make sense, also detect overflow */
   if (*endChar != '>' || result < 0 || result == LONG_MAX)
diff --git a/lib.c b/lib.c
index dd0c9c3a..7db581d9 100644
--- a/lib.c
+++ b/lib.c
@@ -742,17 +742,17 @@ const char *mutt_stristr (const char *haystack, const 
char *needle)
   return NULL;
 }
 
-char *mutt_skip_whitespace (char *p)
+char *mutt_skip_ascii_ws (char *p)
 {
-  SKIPWS (p);
+  SKIP_ASCII_WS (p);
   return p;
 }
 
-void mutt_remove_trailing_ws (char *s)
+void mutt_remove_trailing_ascii_ws (char *s)
 {
   char *p;
 
-  for (p = s + mutt_strlen (s) - 1 ; p >= s && ISSPACE (*p) ; p--)
+  for (p = s + mutt_strlen (s) - 1 ; p >= s && IS_ASCII_WS (*p) ; p--)
     *p = 0;
 }
 
diff --git a/lib.h b/lib.h
index b31a2ab4..1d0c8115 100644
--- a/lib.h
+++ b/lib.h
@@ -74,7 +74,6 @@
 
 # define FREE(x) safe_free(x)
 # define NONULL(x) x?x:""
-# define ISSPACE(c) isspace((unsigned char)c)
 
 #ifdef HAVE_MEMCCPY
 # define strfcpy(A,B,C) memccpy(A,B,0,(C)-1), *((A)+(C)-1)=0
@@ -106,27 +105,43 @@
 
 #define FOREVER while (1)
 
-/* this macro must check for *c == 0 since isspace(0) has unreliable behavior
-   on some systems */
-# define SKIPWS(c) while (*(c) && isspace ((unsigned char) *(c))) c++;
+/*
+ * ASCII Whitespace
+ * 0x09-0x0d (\t \n \v \f \r)
+ * 0x20      (space)
+ */
+#define IS_ASCII_WS(c) ((9 <= (c) && (c) <= 13) || (c) == 32)
 
+#define SKIP_ASCII_WS(c) while (IS_ASCII_WS (*(c))) c++;
+
+/*
+ * WSP as defined by RFC5322.
+ * This is used primarily for parsing header fields.
+ */
 #define EMAIL_WSP " \t\r\n"
 
-/* skip over WSP as defined by RFC5322.  This is used primarily for parsing
- * header fields. */
+static inline int is_email_wsp (char c)
+{
+  return c && (strchr(EMAIL_WSP, c) != NULL);
+}
 
-static inline char *skip_email_wsp(const char *s)
+static inline char *skip_email_wsp (const char *s)
 {
   if (s)
     return (char *)(s + strspn(s, EMAIL_WSP));
   return (char *)s;
 }
 
-static inline int is_email_wsp(char c)
-{
-  return c && (strchr(EMAIL_WSP, c) != NULL);
-}
+/*
+ * Locale-defined whitespace.
+ * This should only be used when dealing with user input, because
+ * some platforms return unexpected results with 8-bit values.
+ */
+#define IS_LOCALE_WS(c) isspace((unsigned char)c)
 
+/* this macro must check for *c == 0 since isspace(0) has unreliable behavior
+   on some systems */
+#define SKIP_LOCALE_WS(c) while (*(c) && IS_LOCALE_WS (*(c))) c++;
 
 /*
  * These functions aren't defined in lib.c, but
@@ -186,7 +201,7 @@ void mutt_debug_f (const char *, const int, const char *, 
const int err, const c
 
 char *mutt_concat_path (char *, const char *, const char *, size_t);
 char *mutt_read_line (char *, size_t *, FILE *, int *, int);
-char *mutt_skip_whitespace (char *);
+char *mutt_skip_ascii_ws (char *);
 char *mutt_strlower (char *);
 char *mutt_substrcpy (char *, const char *, const char *, size_t);
 char *mutt_substrdup (const char *, const char *);
@@ -236,7 +251,7 @@ size_t mutt_strlen (const char *);
 void *safe_calloc (size_t, size_t);
 void *safe_malloc (size_t);
 void mutt_nocurses_error (const char *, ...);
-void mutt_remove_trailing_ws (char *);
+void mutt_remove_trailing_ascii_ws (char *);
 void mutt_sanitize_filename (char *, int flags);
 void mutt_str_replace (char **p, const char *s);
 int mutt_mkdir (char *path, mode_t mode);
diff --git a/mbyte.c b/mbyte.c
index 762e7f25..34989356 100644
--- a/mbyte.c
+++ b/mbyte.c
@@ -265,9 +265,9 @@ int iswprint (wint_t wc)
 int iswspace (wint_t wc)
 {
   if (Charset_is_utf8 || charset_is_ja)
-    return (9 <= wc && wc <= 13) || wc == 32;
+    return IS_ASCII_WS (wc);
   else
-    return (0 <= wc && wc < 256) ? isspace (wc) : 0;
+    return (0 <= wc && wc < 256) ? isspace (wc) : 0;  /* 
__SAFE_ISSPACE_CHECKED__ */
 }
 
 int iswblank (wint_t wc)
diff --git a/mutt_lisp.c b/mutt_lisp.c
index 6707f772..152a0662 100644
--- a/mutt_lisp.c
+++ b/mutt_lisp.c
@@ -74,7 +74,7 @@ static int read_list (BUFFER *list, BUFFER *line)
   if (!line->dptr || !*line->dptr)
     return 0;
 
-  SKIPWS (line->dptr);
+  SKIP_ASCII_WS (line->dptr);
 
   if (*line->dptr != '(')
     return -1;
@@ -135,7 +135,7 @@ static int read_atom (BUFFER *atom, BUFFER *line)
   if (!line->dptr || !*line->dptr)
     return 0;
 
-  SKIPWS (line->dptr);
+  SKIP_ASCII_WS (line->dptr);
 
   while (*line->dptr)
   {
@@ -156,7 +156,7 @@ static int read_atom (BUFFER *atom, BUFFER *line)
     }
     else if (!quotechar)
     {
-      if (ISSPACE (ch) || ch == '(' || ch == ')')
+      if (IS_ASCII_WS (ch) || ch == '(' || ch == ')')
         break;
       if (ch == '"' || ch == '\'')
         quotechar = ch;
@@ -180,7 +180,7 @@ static int read_sexp (BUFFER *sexp, BUFFER *line)
   if (!line->dptr || !*line->dptr)
     return 0;
 
-  SKIPWS (line->dptr);
+  SKIP_ASCII_WS (line->dptr);
 
   if (*line->dptr == '(')
     rc = read_list (sexp, line);
@@ -472,7 +472,7 @@ int mutt_lisp_eval_list (BUFFER *result, BUFFER *line)
   function = mutt_buffer_new ();
   if (read_sexp (function, list) <= 0)
     goto cleanup;
-  SKIPWS (list->dptr);
+  SKIP_ASCII_WS (list->dptr);
 
   if (eval_function (result, mutt_b2s (function), list) < 0)
     goto cleanup;
diff --git a/muttlib.c b/muttlib.c
index b7e45d20..18f3ebf0 100644
--- a/muttlib.c
+++ b/muttlib.c
@@ -1400,7 +1400,7 @@ void mutt_safe_path (BUFFER *dest, ADDRESS *a)
 
   mutt_buffer_save_path (dest, a);
   for (p = dest->data; *p; p++)
-    if (*p == '/' || ISSPACE (*p) || !IsPrint ((unsigned char) *p))
+    if (*p == '/' || IS_ASCII_WS (*p) || !IsPrint ((unsigned char) *p))
       *p = '_';
 }
 
diff --git a/pager.c b/pager.c
index 950a430f..1598a59e 100644
--- a/pager.c
+++ b/pager.c
@@ -174,7 +174,7 @@ static int check_sig (const char *s, struct line_t *info, 
int n)
     /* check for a blank line */
     while (*s)
     {
-      if (!ISSPACE (*s))
+      if (!IS_ASCII_WS (*s))
         return 0;
       s++;
     }
diff --git a/parse.c b/parse.c
index 94573a4b..141947f4 100644
--- a/parse.c
+++ b/parse.c
@@ -335,7 +335,7 @@ void mutt_parse_content_type (char *s, BODY *ct)
   if ((pc = strchr(s, ';')) != NULL)
   {
     *pc++ = 0;
-    while (*pc && ISSPACE (*pc))
+    while (*pc && IS_ASCII_WS (*pc))
       pc++;
     ct->parameter = parse_parameters(pc, 0);
 
@@ -357,7 +357,7 @@ void mutt_parse_content_type (char *s, BODY *ct)
   if ((subtype = strchr(s, '/')))
   {
     *subtype++ = '\0';
-    for (pc = subtype; *pc && !ISSPACE(*pc) && *pc != ';'; pc++)
+    for (pc = subtype; *pc && !IS_ASCII_WS(*pc) && *pc != ';'; pc++)
       ;
     *pc = '\0';
     ct->subtype = safe_strdup (subtype);
@@ -737,7 +737,7 @@ static BODY *_parse_multipart (FILE *fp, const char 
*boundary, LOFF_T end_off,
       }
 
       /* Remove any trailing whitespace, up to the length of the boundary */
-      for (i = len - 1; ISSPACE (buffer[i]) && i >= blen + 2; i--)
+      for (i = len - 1; IS_ASCII_WS (buffer[i]) && i >= blen + 2; i--)
         buffer[i] = 0;
 
       /* Check for the end boundary */
diff --git a/pattern.c b/pattern.c
index a6518ac6..d6f64e8e 100644
--- a/pattern.c
+++ b/pattern.c
@@ -653,7 +653,7 @@ static int eat_range (pattern_t *pat, int flags, BUFFER *s, 
BUFFER *err)
   if (skip_quote && *tmp == '"')
     tmp++;
 
-  SKIPWS (tmp);
+  SKIP_ASCII_WS (tmp);
   s->dptr = tmp;
   return 0;
 }
@@ -814,7 +814,7 @@ static const char * parse_date_range (const char* pc, 
struct tm *min,
   {
     const char *pt;
     char ch = *pc++;
-    SKIPWS (pc);
+    SKIP_ASCII_WS (pc);
     switch (ch)
     {
       case '-':
@@ -878,7 +878,7 @@ static const char * parse_date_range (const char* pc, 
struct tm *min,
       default:
         flag |= MUTT_PDR_ERRORDONE;
     }
-    SKIPWS (pc);
+    SKIP_ASCII_WS (pc);
   }
   if ((flag & MUTT_PDR_ERROR) && !(flag & MUTT_PDR_ABSOLUTE))
   { /* getDate has its own error message, don't overwrite it here */
@@ -968,11 +968,11 @@ static int eval_date_minmax (pattern_t *pat, const char 
*s, BUFFER *err)
         return (-1);
       }
       haveMin = TRUE;
-      SKIPWS (pc);
+      SKIP_ASCII_WS (pc);
       if (*pc == '-')
       {
         const char *pt = pc + 1;
-        SKIPWS (pt);
+        SKIP_ASCII_WS (pt);
         untilNow = (*pt == '\0');
       }
     }
@@ -1172,7 +1172,7 @@ pattern_t *mutt_pattern_comp (/* const */ char *s, int 
flags, BUFFER *err)
   ps.dptr = s;
   ps.dsize = mutt_strlen (s);
 
-  SKIPWS (ps.dptr);
+  SKIP_ASCII_WS (ps.dptr);
   while (*ps.dptr)
   {
     switch (*ps.dptr)
@@ -1316,7 +1316,7 @@ pattern_t *mutt_pattern_comp (/* const */ char *s, int 
flags, BUFFER *err)
         tmp->op = entry->op;
 
         ps.dptr++; /* eat the operator and any optional whitespace */
-        SKIPWS (ps.dptr);
+        SKIP_ASCII_WS (ps.dptr);
 
         if (entry->eat_arg)
         {
@@ -1382,7 +1382,7 @@ pattern_t *mutt_pattern_comp (/* const */ char *s, int 
flags, BUFFER *err)
         mutt_pattern_free (&curlist);
         return NULL;
     }
-    SKIPWS (ps.dptr);
+    SKIP_ASCII_WS (ps.dptr);
   }
   if (!curlist)
   {
diff --git a/pgp.c b/pgp.c
index 355b8eca..c355b1d1 100644
--- a/pgp.c
+++ b/pgp.c
@@ -371,7 +371,7 @@ static void pgp_copy_clearsigned (FILE *fpin, STATE *s, 
char *charset)
 
     if (armor_header)
     {
-      char *p = mutt_skip_whitespace (buf);
+      char *p = mutt_skip_ascii_ws (buf);
       if (*p == '\0')
         armor_header = 0;
       continue;
diff --git a/pgpmicalg.c b/pgpmicalg.c
index 3d5c5421..4ed02486 100644
--- a/pgpmicalg.c
+++ b/pgpmicalg.c
@@ -95,7 +95,7 @@ static void pgp_dearmor (FILE *in, FILE *out)
 
   while ((r = fgets (line, sizeof (line), in)) != NULL)
   {
-    SKIPWS (r);
+    SKIP_ASCII_WS (r);
     if (!*r) break;
   }
   if (r == NULL)
diff --git a/pop_lib.c b/pop_lib.c
index 73136c6d..66494daa 100644
--- a/pop_lib.c
+++ b/pop_lib.c
@@ -92,7 +92,7 @@ void pop_error (POP_DATA *pop_data, char *msg)
   }
 
   strfcpy (t, c, sizeof (pop_data->err_msg) - strlen (pop_data->err_msg));
-  mutt_remove_trailing_ws (pop_data->err_msg);
+  mutt_remove_trailing_ascii_ws (pop_data->err_msg);
 }
 
 /* Parse CAPA output */
diff --git a/rfc1524.c b/rfc1524.c
index a9ea49a4..273614b1 100644
--- a/rfc1524.c
+++ b/rfc1524.c
@@ -173,20 +173,20 @@ static char *get_field (char *s)
       break;
     }
   }
-  mutt_remove_trailing_ws (s);
+  mutt_remove_trailing_ascii_ws (s);
   return ch;
 }
 
 static int get_field_text (char *field, char **entry,
                            const char *type, const char *filename, int line)
 {
-  field = mutt_skip_whitespace (field);
+  field = mutt_skip_ascii_ws (field);
   if (*field == '=')
   {
     if (entry)
     {
       field++;
-      field = mutt_skip_whitespace (field);
+      field = mutt_skip_ascii_ws (field);
       mutt_str_replace (entry, field);
     }
     return 1;
diff --git a/sendlib.c b/sendlib.c
index 07cb8395..f0e34d99 100644
--- a/sendlib.c
+++ b/sendlib.c
@@ -1028,13 +1028,13 @@ int mutt_lookup_mime_type (BODY *att, const char *path)
 
         /* remove any leading space. */
         ct = buf;
-        SKIPWS (ct);
+        SKIP_ASCII_WS (ct);
 
         /* position on the next field in this line */
         if ((p = strpbrk (ct, " \t")) == NULL)
           continue;
         *p++ = 0;
-        SKIPWS (p);
+        SKIP_ASCII_WS (p);
 
         /* cycle through the file extensions */
         while ((p = strtok (p, " \t\n")))
@@ -1053,7 +1053,7 @@ int mutt_lookup_mime_type (BODY *att, const char *path)
             }
             *p++ = 0;
 
-            for (q = p; *q && !ISSPACE (*q); q++)
+            for (q = p; *q && !IS_ASCII_WS (*q); q++)
               ;
 
             mutt_substrcpy (subtype, p, q, sizeof (subtype));
-- 
2.53.0

Reply via email to