patch 9.1.0006: is*() and to*() function may be unsafe

Commit: 
https://github.com/vim/vim/commit/184f71cc6868a240dc872ed2852542bbc1d43e28
Author: Keith Thompson <[email protected]>
Date:   Thu Jan 4 21:19:04 2024 +0100

    patch 9.1.0006: is*() and to*() function may be unsafe
    
    Problem:  is*() and to*() function may be unsafe
    Solution: Add SAFE_* macros and start using those instead
              (Keith Thompson)
    
    Use SAFE_() macros for is*() and to*() functions
    
    The standard is*() and to*() functions declared in <ctype.h> have
    undefined behavior for negative arguments other than EOF.  If plain char
    is signed, passing an unchecked value from argv for from user input
    to one of these functions has undefined behavior.
    
    Solution: Add SAFE_*() macros that cast the argument to unsigned char.
    
    Most implementations behave sanely for negative arguments, and most
    character values in practice are non-negative, but it's still best
    to avoid undefined behavior.
    
    The change from #13347 has been omitted, as this has already been
    separately fixed in commit ac709e2fc0db6d31abb7da96f743c40956b60c3a
    (v9.0.2054)
    
    fixes: #13332
    closes: #13347
    
    Signed-off-by: Keith Thompson <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/runtime/tools/ccfilter.c b/runtime/tools/ccfilter.c
index 43489f16c..ae1443e20 100644
--- a/runtime/tools/ccfilter.c
+++ b/runtime/tools/ccfilter.c
@@ -249,7 +249,7 @@ int main( int argc, char *argv[] )
 
            stay = (echogets(Line2, echo) != NULL);
            while ( stay && (Line2[0] == '|') )
-             { for (p=&Line2[2]; (*p) && (isspace(*p)); p++);
+             { for (p=&Line2[2]; (*p) && (isspace((unsigned char)*p)); p++);
                strcat( Reason, ": " );
                strcat( Reason, p );
                Line2[0] = 0;
@@ -265,7 +265,7 @@ int main( int argc, char *argv[] )
            ok        = 0;
            if ( !strncmp(Line, "cfe: ", 5) )
              { p = &Line[5];
-               Severity = tolower(*p);
+               Severity = tolower((unsigned char)*p);
                p = strchr( &Line[5], ':' );
                if (p == NULL)
                  { ok = 0;
@@ -313,7 +313,7 @@ int main( int argc, char *argv[] )
        }
        else
        {
-         for (p=Reason; (*p) && (isspace(*p)); p++);
+         for (p=Reason; (*p) && (isspace((unsigned char)*p)); p++);
          if ( BasePath[CWDlen] == 0 )
              printf( "%s:%lu:%lu:%c:%s
", FileName, Row, Col, Severity, p );
          else
diff --git a/runtime/tools/xcmdsrv_client.c b/runtime/tools/xcmdsrv_client.c
index e1aea1066..81ca66ceb 100644
--- a/runtime/tools/xcmdsrv_client.c
+++ b/runtime/tools/xcmdsrv_client.c
@@ -336,7 +336,7 @@ LookupName(
     for (p = regProp; (p - regProp) < numItems; )
     {
        entry = p;
-       while ((*p != 0) && (!isspace(*p)))
+       while ((*p != 0) && (!isspace((unsigned char)*p)))
            p++;
        if ((*p != 0) && (strcasecmp(name, p + 1) == 0))
        {
@@ -353,7 +353,7 @@ LookupName(
        for (p = regProp; (p - regProp) < numItems; )
        {
            entry = p;
-           while ((*p != 0) && (!isspace(*p)))
+           while ((*p != 0) && (!isspace((unsigned char)*p)))
                p++;
            if ((*p != 0) && IsSerialName(p + 1)
                    && (strncmp(name, p + 1, strlen(name)) == 0))
@@ -574,5 +574,5 @@ IsSerialName(char *str)
 {
     int len = strlen(str);
 
-    return (len > 1 && isdigit(str[len - 1]));
+    return (len > 1 && isdigit((unsigned char)str[len - 1]));
 }
diff --git a/src/buffer.c b/src/buffer.c
index 9ee74f54d..64e492647 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -4022,7 +4022,7 @@ maketitle(void)
                                        buf + off, SPACE_FOR_DIR - off, TRUE);
 #ifdef BACKSLASH_IN_FILENAME
                // avoid "c:/name" to be reduced to "c"
-               if (isalpha(buf[off]) && buf[off + 1] == ':')
+               if (SAFE_isalpha(buf[off]) && buf[off + 1] == ':')
                    off += 2;
 #endif
                // remove the file name
@@ -5671,7 +5671,7 @@ chk_modeline(
                        && (s[0] != 'V'
                                  || STRNCMP(skipwhite(e + 1), "set", 3) == 0)
                        && (s[3] == ':'
-                           || (VIM_VERSION_100 >= vers && isdigit(s[3]))
+                           || (VIM_VERSION_100 >= vers && SAFE_isdigit(s[3]))
                            || (VIM_VERSION_100 < vers && s[3] == '<')
                            || (VIM_VERSION_100 > vers && s[3] == '>')
                            || (VIM_VERSION_100 == vers && s[3] == '=')))
diff --git a/src/charset.c b/src/charset.c
index bda3f911b..0e4dbbe1d 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -1958,7 +1958,7 @@ vim_islower(int c)
        if (enc_latin1like)
            return (latin1flags[c] & LATIN1LOWER) == LATIN1LOWER;
     }
-    return islower(c);
+    return SAFE_islower(c);
 }
 
     int
@@ -1982,7 +1982,7 @@ vim_isupper(int c)
        if (enc_latin1like)
            return (latin1flags[c] & LATIN1UPPER) == LATIN1UPPER;
     }
-    return isupper(c);
+    return SAFE_isupper(c);
 }
 
     int
diff --git a/src/cmdhist.c b/src/cmdhist.c
index 96a9b3e95..6342f02bd 100644
--- a/src/cmdhist.c
+++ b/src/cmdhist.c
@@ -674,7 +674,7 @@ remove_key_from_history(void)
        return;
 
     for ( ; *p; ++p)
-       if (STRNCMP(p, "key", 3) == 0 && !isalpha(p[3]))
+       if (STRNCMP(p, "key", 3) == 0 && !SAFE_isalpha(p[3]))
        {
            p = vim_strchr(p + 3, '=');
            if (p == NULL)
diff --git a/src/diff.c b/src/diff.c
index 158870402..9b8c816b5 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -1712,7 +1712,7 @@ diff_read(
                // --- file1       2018-03-20 13:23:35.783153140 +0100
                // +++ file2       2018-03-20 13:23:41.183156066 +0100
                // @@ -1,3 +1,5 @@
-               if (isdigit(*line))
+               if (SAFE_isdigit(*line))
                    diffstyle = DIFF_ED;
                else if ((STRNCMP(line, "@@ ", 3) == 0))
                    diffstyle = DIFF_UNIFIED;
@@ -1730,7 +1730,7 @@ diff_read(
 
            if (diffstyle == DIFF_ED)
            {
-               if (!isdigit(*line))
+               if (!SAFE_isdigit(*line))
                    continue;   // not the start of a diff block
                if (parse_diff_ed(line, hunk) == FAIL)
                    continue;
diff --git a/src/dosinst.c b/src/dosinst.c
index 4eae5aadc..35625a794 100644
--- a/src/dosinst.c
+++ b/src/dosinst.c
@@ -2760,7 +2760,7 @@ main(int argc, char **argv)
            rewind(stdin);
            if (scanf("%99s", buf) == 1)
            {
-               if (isdigit(buf[0]))
+               if (isdigit((unsigned char)buf[0]))
                {
                    // Change a choice.
                    i = atoi(buf);
diff --git a/src/edit.c b/src/edit.c
index 9435fd6fc..f89d43eec 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -5318,7 +5318,7 @@ ins_ctrl_ey(int tc)
            // was typed after a CTRL-V, and pretend 'textwidth'
            // wasn't set.  Digits, 'o' and 'x' are special after a
            // CTRL-V, don't use it for these.
-           if (c < 256 && !isalnum(c))
+           if (c < 256 && !SAFE_isalnum(c))
                AppendToRedobuff((char_u *)CTRL_V_STR); // CTRL-V
            tw_save = curbuf->b_p_tw;
            curbuf->b_p_tw = -1;
diff --git a/src/eval.c b/src/eval.c
index 8563aa6d7..815d13d42 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -4276,7 +4276,7 @@ eval9(
        return FAIL;
     end_leader = *arg;
 
-    if (**arg == '.' && (!isdigit(*(*arg + 1)) || in_old_script(2)))
+    if (**arg == '.' && (!SAFE_isdigit(*(*arg + 1)) || in_old_script(2)))
     {
        semsg(_(e_invalid_expression_str), *arg);
        ++*arg;
diff --git a/src/evalfunc.c b/src/evalfunc.c
index f87c08ffc..513ddccdb 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -6744,7 +6744,7 @@ f_has(typval_T *argvars, typval_T *rettv)
                                     && has_patch(atoi(end + 3))))));
                }
            }
-           else if (isdigit(name[5]))
+           else if (SAFE_isdigit(name[5]))
                n = has_patch(atoi((char *)name + 5));
        }
        else if (STRICMP(name, "vim_starting") == 0)
diff --git a/src/evalvars.c b/src/evalvars.c
index ea039cbed..8e42c5a30 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -3332,7 +3332,7 @@ find_var(char_u *name, hashtab_T **htp, int no_autoload)
     dictitem_T *
 find_var_also_in_script(char_u *name, hashtab_T **htp, int no_autoload)
 {
-    if (STRNCMP(name, "<SNR>", 5) == 0 && isdigit(name[5]))
+    if (STRNCMP(name, "<SNR>", 5) == 0 && SAFE_isdigit(name[5]))
     {
        char_u      *p = name + 5;
        int         sid = getdigits(&p);
@@ -4975,7 +4975,7 @@ get_callback(typval_T *arg)
     else
     {
        if (arg->v_type == VAR_STRING && arg->vval.v_string != NULL
-                                              && isdigit(*arg->vval.v_string))
+                                              && 
SAFE_isdigit(*arg->vval.v_string))
            r = FAIL;
        else if (arg->v_type == VAR_FUNC || arg->v_type == VAR_STRING)
        {
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index d21493362..d8e891c2b 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -3707,7 +3707,7 @@ skip_substitute(char_u *start, int delimiter)
     static int
 check_regexp_delim(int c)
 {
-    if (isalpha(c))
+    if (SAFE_isalpha(c))
     {
        emsg(_(e_regular_expressions_cant_be_delimited_by_letters));
        return FAIL;
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 534cd7e03..c18a9107e 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -7996,7 +7996,7 @@ ex_winsize(exarg_T *eap)
     char_u     *arg = eap->arg;
     char_u     *p;
 
-    if (!isdigit(*arg))
+    if (!SAFE_isdigit(*arg))
     {
        semsg(_(e_invalid_argument_str), arg);
        return;
@@ -8387,7 +8387,7 @@ ex_later(exarg_T *eap)
 
     if (*p == NUL)
        count = 1;
-    else if (isdigit(*p))
+    else if (SAFE_isdigit(*p))
     {
        count = getdigits(&p);
        switch (*p)
@@ -8490,7 +8490,7 @@ ex_redir(exarg_T *eap)
                        arg++;
                    // Make register empty when not using @A-@Z and the
                    // command is valid.
-                   if (*arg == NUL && !isupper(redir_reg))
+                   if (*arg == NUL && !SAFE_isupper(redir_reg))
                        write_reg_contents(redir_reg, (char_u *)"", -1, FALSE);
                }
            }
diff --git a/src/filepath.c b/src/filepath.c
index 1ea062386..cbf2da413 100644
--- a/src/filepath.c
+++ b/src/filepath.c
@@ -2953,7 +2953,7 @@ get_past_head(char_u *path)
 
 #if defined(MSWIN)
     // may skip "c:"
-    if (isalpha(path[0]) && path[1] == ':')
+    if (SAFE_isalpha(path[0]) && path[1] == ':')
        retval = path + 2;
     else
        retval = path;
diff --git a/src/findfile.c b/src/findfile.c
index 246a81898..263660925 100644
--- a/src/findfile.c
+++ b/src/findfile.c
@@ -1847,7 +1847,7 @@ grab_file_name(long count, linenr_T *file_lnum)
        if (get_visual_text(NULL, &ptr, &len) == FAIL)
            return NULL;
        // Only recognize ":123" here
-       if (file_lnum != NULL && ptr[len] == ':' && isdigit(ptr[len + 1]))
+       if (file_lnum != NULL && ptr[len] == ':' && SAFE_isdigit(ptr[len + 1]))
        {
            char_u *p = ptr + len + 1;
 
@@ -1981,10 +1981,10 @@ file_name_in_line(
            p = skipwhite(p);
        if (*p != NUL)
        {
-           if (!isdigit(*p))
+           if (!SAFE_isdigit(*p))
                ++p;                // skip the separator
            p = skipwhite(p);
-           if (isdigit(*p))
+           if (SAFE_isdigit(*p))
                *file_lnum = (int)getdigits(&p);
        }
     }
diff --git a/src/getchar.c b/src/getchar.c
index da0503370..3427a9f8d 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -870,7 +870,7 @@ start_redo(long count, int old_redo)
        {
            c = read_redo(FALSE, old_redo);
            add_char_buff(&readbuf2, c);
-           if (!isdigit(c))
+           if (!SAFE_isdigit(c))
                break;
        }
        c = read_redo(FALSE, old_redo);
@@ -1873,7 +1873,7 @@ vgetc(void)
 
                    // Handle <SID>{sid};  Do up to 20 digits for safety.
                    last_used_sid = 0;
-                   for (j = 0; j < 20 && isdigit(c = vgetorpeek(TRUE)); ++j)
+                   for (j = 0; j < 20 && SAFE_isdigit(c = vgetorpeek(TRUE)); 
++j)
                        last_used_sid = last_used_sid * 10 + (c - '0');
                    last_used_map = NULL;
                    continue;
diff --git a/src/gui.c b/src/gui.c
index 9c9aa3cbe..16c1b54c6 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -5030,7 +5030,7 @@ display_errors(void)
 
     // avoid putting up a message box with blanks only
     for (p = (char_u *)error_ga.ga_data; *p != NUL; ++p)
-       if (!isspace(*p))
+       if (!SAFE_isspace(*p))
        {
            // Truncate a very long message, it will go off-screen.
            if (STRLEN(p) > 2000)
diff --git a/src/gui_haiku.cc b/src/gui_haiku.cc
index c8b05e1be..d08322654 100644
--- a/src/gui_haiku.cc
+++ b/src/gui_haiku.cc
@@ -4031,17 +4031,6 @@ gui_mch_mousehide(int hide)
     // TODO
 }
 
-    static int
-hex_digit(int c)
-{
-    if (isdigit(c))
-       return c - '0';
-    c = TOLOWER_ASC(c);
-    if (c >= 'a' && c <= 'f')
-       return c - 'a' + 10;
-    return -1000;
-}
-
 /*
  * This function has been lifted from gui_w32.c and extended a bit.
  *
diff --git a/src/gui_photon.c b/src/gui_photon.c
index b987e9b8a..9bce94ddf 100644
--- a/src/gui_photon.c
+++ b/src/gui_photon.c
@@ -977,7 +977,7 @@ gui_ph_is_buffer_item(vimmenu_T *menu, vimmenu_T *parent)
        if (mark != NULL)
        {
            mark++;
-           while (isdigit(*mark))
+           while (SAFE_isdigit(*mark))
                mark++;
 
            if (*mark == ')')
@@ -2545,7 +2545,7 @@ gui_mch_add_menu(vimmenu_T *menu, int index)
 
            if (menu->mnemonic != 0)
            {
-               PtAddHotkeyHandler(gui.vimWindow, tolower(menu->mnemonic),
+               PtAddHotkeyHandler(gui.vimWindow, SAFE_tolower(menu->mnemonic),
                        Pk_KM_Alt, 0, menu, gui_ph_handle_pulldown_menu);
            }
        }
@@ -2829,7 +2829,7 @@ gui_ph_parse_font_name(
        {
            while (*mark != NUL && *mark++ == ':')
            {
-               switch (tolower(*mark++))
+               switch (SAFE_tolower(*mark++))
                {
                    case 'a': *font_flags |= PF_STYLE_ANTIALIAS; break;
                    case 'b': *font_flags |= PF_STYLE_BOLD; break;
diff --git a/src/gui_xim.c b/src/gui_xim.c
index 88de7a4e9..c9b1c6cb4 100644
--- a/src/gui_xim.c
+++ b/src/gui_xim.c
@@ -1471,7 +1471,7 @@ xim_real_init(Window x11_window, Display *x11_display)
                break;
            if ((ns = end = strchr(s, ',')) == NULL)
                end = s + strlen(s);
-           while (isspace(((char_u *)end)[-1]))
+           while (SAFE_isspace(end[-1]))
                end--;
            *end = NUL;
 
@@ -1533,7 +1533,7 @@ xim_real_init(Window x11_window, Display *x11_display)
     strcpy(tmp, gui.rsrc_preedit_type_name);
     for (s = tmp; s && !found; )
     {
-       while (*s && isspace((unsigned char)*s))
+       while (*s && SAFE_isspace(*s))
            s++;
        if (!*s)
            break;
@@ -1541,7 +1541,7 @@ xim_real_init(Window x11_window, Display *x11_display)
            ns++;
        else
            end = s + strlen(s);
-       while (isspace((unsigned char)*end))
+       while (SAFE_isspace(*end))
            end--;
        *end = '
 
diff --git a/src/hardcopy.c b/src/hardcopy.c
index e91a7dc2d..8abfff210 100644
--- a/src/hardcopy.c
+++ b/src/hardcopy.c
@@ -1745,7 +1745,7 @@ prt_resfile_skip_nonws(int offset)
     idx = prt_resfile.line_start + offset;
     while (idx < prt_resfile.line_end)
     {
-       if (isspace(prt_resfile.buffer[idx]))
+       if (SAFE_isspace(prt_resfile.buffer[idx]))
            return idx - prt_resfile.line_start;
        idx++;
     }
@@ -1760,7 +1760,7 @@ prt_resfile_skip_ws(int offset)
     idx = prt_resfile.line_start + offset;
     while (idx < prt_resfile.line_end)
     {
-       if (!isspace(prt_resfile.buffer[idx]))
+       if (!SAFE_isspace(prt_resfile.buffer[idx]))
            return idx - prt_resfile.line_start;
        idx++;
     }
diff --git a/src/highlight.c b/src/highlight.c
index 31c3280e8..318564c74 100644
--- a/src/highlight.c
+++ b/src/highlight.c
@@ -2307,7 +2307,7 @@ gui_adjust_rgb(guicolor_T c)
     static int
 hex_digit(int c)
 {
-    if (isdigit(c))
+    if (SAFE_isdigit(c))
        return c - '0';
     c = TOLOWER_ASC(c);
     if (c >= 'a' && c <= 'f')
diff --git a/src/if_py_both.h b/src/if_py_both.h
index f8438639e..42db5101d 100644
--- a/src/if_py_both.h
+++ b/src/if_py_both.h
@@ -3240,7 +3240,7 @@ FunctionNew(PyTypeObject *subtype, char_u *name, int 
argc, typval_T *argv,
     if (self == NULL)
        return NULL;
 
-    if (isdigit(*name))
+    if (isdigit((unsigned char)*name))
     {
        if (!translated_function_exists(name, FALSE))
        {
diff --git a/src/if_xcmdsrv.c b/src/if_xcmdsrv.c
index d9408398d..716665a7b 100644
--- a/src/if_xcmdsrv.c
+++ b/src/if_xcmdsrv.c
@@ -657,7 +657,7 @@ serverGetVimNames(Display *dpy)
     for (p = regProp; (long_u)(p - regProp) < numItems; p++)
     {
        entry = p;
-       while (*p != 0 && !isspace(*p))
+       while (*p != 0 && !SAFE_isspace(*p))
            p++;
        if (*p != 0)
        {
@@ -928,7 +928,7 @@ LookupName(
     for (p = regProp; (long_u)(p - regProp) < numItems; )
     {
        entry = p;
-       while (*p != 0 && !isspace(*p))
+       while (*p != 0 && !SAFE_isspace(*p))
            p++;
        if (*p != 0 && STRICMP(name, p + 1) == 0)
        {
@@ -945,7 +945,7 @@ LookupName(
        for (p = regProp; (long_u)(p - regProp) < numItems; )
        {
            entry = p;
-           while (*p != 0 && !isspace(*p))
+           while (*p != 0 && !SAFE_isspace(*p))
                p++;
            if (*p != 0 && IsSerialName(p + 1)
                    && STRNICMP(name, p + 1, STRLEN(name)) == 0)
diff --git a/src/macros.h b/src/macros.h
index cc2d11fdd..190778eca 100644
--- a/src/macros.h
+++ b/src/macros.h
@@ -50,6 +50,28 @@
  */
 #define BUFEMPTY() (curbuf->b_ml.ml_line_count == 1 && *ml_get((linenr_T)1) == 
NUL)
 
+// The is*() and to*() functions declared in <ctype.h> have
+// undefined behavior for values other than EOF outside the range of
+// unsigned char.  If plain char is signed, a call with a negative
+// value has undefined behavior.  These macros cast the argument to
+// unsigned char.  (Most implementations behave more or less sanely
+// with negative values, and most character values in practice are
+// positive, but we want to avoid undefined behavior anyway.)
+#define SAFE_isalnum(c)  (isalnum ((unsigned char)(c)))
+#define SAFE_isalpha(c)  (isalpha ((unsigned char)(c)))
+#define SAFE_isblank(c)  (isblank ((unsigned char)(c)))
+#define SAFE_iscntrl(c)  (iscntrl ((unsigned char)(c)))
+#define SAFE_isdigit(c)  (isdigit ((unsigned char)(c)))
+#define SAFE_isgraph(c)  (isgraph ((unsigned char)(c)))
+#define SAFE_islower(c)  (islower ((unsigned char)(c)))
+#define SAFE_isprint(c)  (isprint ((unsigned char)(c)))
+#define SAFE_ispunct(c)  (ispunct ((unsigned char)(c)))
+#define SAFE_isspace(c)  (isspace ((unsigned char)(c)))
+#define SAFE_isupper(c)  (isupper ((unsigned char)(c)))
+#define SAFE_isxdigit(c) (isxdigit((unsigned char)(c)))
+#define SAFE_tolower(c)  (tolower ((unsigned char)(c)))
+#define SAFE_toupper(c)  (toupper ((unsigned char)(c)))
+
 /*
  * toupper() and tolower() that use the current locale.
  * On some systems toupper()/tolower() only work on lower/uppercase
@@ -64,11 +86,11 @@
 #  define TOLOWER_LOC(c)       tolower_tab[(c) & 255]
 #else
 # ifdef BROKEN_TOUPPER
-#  define TOUPPER_LOC(c)       (islower(c) ? toupper(c) : (c))
-#  define TOLOWER_LOC(c)       (isupper(c) ? tolower(c) : (c))
+#  define TOUPPER_LOC(c)       (SAFE_islower(c) ? SAFE_toupper(c) : (c))
+#  define TOLOWER_LOC(c)       (SAFE_isupper(c) ? SAFE_tolower(c) : (c))
 # else
-#  define TOUPPER_LOC          toupper
-#  define TOLOWER_LOC          tolower
+#  define TOUPPER_LOC          SAFE_toupper
+#  define TOLOWER_LOC          SAFE_tolower
 # endif
 #endif
 
diff --git a/src/mbyte.c b/src/mbyte.c
index 34592bd56..ee2834cf4 100644
--- a/src/mbyte.c
+++ b/src/mbyte.c
@@ -4628,7 +4628,7 @@ enc_canonize(char_u *enc)
     }
 
     // "iso-8859n" -> "iso-8859-n"
-    if (STRNCMP(p, "iso-8859", 8) == 0 && isdigit(p[8]))
+    if (STRNCMP(p, "iso-8859", 8) == 0 && SAFE_isdigit(p[8]))
     {
        STRMOVE(p + 9, p + 8);
        p[8] = '-';
@@ -4705,7 +4705,7 @@ enc_locale_env(char *locale)
     if ((p = (char *)vim_strchr((char_u *)s, '.')) != NULL)
     {
        if (p > s + 2 && STRNICMP(p + 1, "EUC", 3) == 0
-                       && !isalnum((int)p[4]) && p[4] != '-' && p[-3] == '_')
+                       && !SAFE_isalnum((int)p[4]) && p[4] != '-' && p[-3] == 
'_')
        {
            // copy "XY.EUC" to "euc-XY" to buf[10]
            STRCPY(buf + 10, "euc-");
@@ -4721,7 +4721,7 @@ enc_locale_env(char *locale)
     {
        if (s[i] == '_' || s[i] == '-')
            buf[i] = '-';
-       else if (isalnum((int)s[i]))
+       else if (SAFE_isalnum(s[i]))
            buf[i] = TOLOWER_ASC(s[i]);
        else
            break;
diff --git a/src/normal.c b/src/normal.c
index 61a19c13a..fd89b00fd 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -4470,11 +4470,11 @@ nv_brackets(cmdarg_T *cap)
                return;
 
            find_pattern_in_path(ptr, 0, len, TRUE,
-               cap->count0 == 0 ? !isupper(cap->nchar) : FALSE,
+               cap->count0 == 0 ? !SAFE_isupper(cap->nchar) : FALSE,
                ((cap->nchar & 0xf) == ('d' & 0xf)) ?  FIND_DEFINE : FIND_ANY,
                cap->count1,
-               isupper(cap->nchar) ? ACTION_SHOW_ALL :
-                           islower(cap->nchar) ? ACTION_SHOW : ACTION_GOTO,
+               SAFE_isupper(cap->nchar) ? ACTION_SHOW_ALL :
+                           SAFE_islower(cap->nchar) ? ACTION_SHOW : 
ACTION_GOTO,
                cap->cmdchar == ']' ? curwin->w_cursor.lnum + 1 : (linenr_T)1,
                (linenr_T)MAXLNUM);
            vim_free(ptr);
@@ -5217,7 +5217,7 @@ v_visop(cmdarg_T *cap)
 
     // Uppercase means linewise, except in block mode, then "D" deletes till
     // the end of the line, and "C" replaces till EOL
-    if (isupper(cap->cmdchar))
+    if (SAFE_isupper(cap->cmdchar))
     {
        if (VIsual_mode != Ctrl_V)
        {
diff --git a/src/ops.c b/src/ops.c
index 46101a435..f6d765bd7 100644
--- a/src/ops.c
+++ b/src/ops.c
@@ -2734,7 +2734,7 @@ do_addsub(
        {
            if (CharOrd(firstdigit) < Prenum1)
            {
-               if (isupper(firstdigit))
+               if (SAFE_isupper(firstdigit))
                    firstdigit = 'A';
                else
                    firstdigit = 'a';
@@ -2746,7 +2746,7 @@ do_addsub(
        {
            if (26 - CharOrd(firstdigit) - 1 < Prenum1)
            {
-               if (isupper(firstdigit))
+               if (SAFE_isupper(firstdigit))
                    firstdigit = 'Z';
                else
                    firstdigit = 'z';
@@ -2875,9 +2875,9 @@ do_addsub(
        save_pos = curwin->w_cursor;
        for (i = 0; i < todel; ++i)
        {
-           if (c < 0x100 && isalpha(c))
+           if (c < 0x100 && SAFE_isalpha(c))
            {
-               if (isupper(c))
+               if (SAFE_isupper(c))
                    hexupper = TRUE;
                else
                    hexupper = FALSE;
diff --git a/src/option.c b/src/option.c
index 4d12834f2..7cac89e5c 100644
--- a/src/option.c
+++ b/src/option.c
@@ -7697,7 +7697,7 @@ ExpandSettings(
        {
            for (opt_idx = 0; (str = get_termcode(opt_idx)) != NULL; opt_idx++)
            {
-               if (!isprint(str[0]) || !isprint(str[1]))
+               if (!SAFE_isprint(str[0]) || !SAFE_isprint(str[1]))
                    continue;
 
                name_buf[0] = 't';
diff --git a/src/os_mswin.c b/src/os_mswin.c
index 46f73752f..21b7db31f 100644
--- a/src/os_mswin.c
+++ b/src/os_mswin.c
@@ -675,7 +675,7 @@ display_errors(void)
        {
            // avoid putting up a message box with blanks only
            for (p = (char_u *)error_ga.ga_data; *p; ++p)
-               if (!isspace(*p))
+               if (!SAFE_isspace(*p))
                {
                    // Only use a dialog when not using --gui-dialog-file:
                    // write text to a file.
@@ -759,7 +759,7 @@ mch_chdir(char *path)
        smsg("chdir(%s)", path);
        verbose_leave();
     }
-    if (isalpha(path[0]) && path[1] == ':')    // has a drive name
+    if (SAFE_isalpha(path[0]) && path[1] == ':')       // has a drive name
     {
        // If we can change to the drive, skip that part of the path.  If we
        // can't then the current directory may be invalid, try using chdir()
@@ -1751,7 +1751,7 @@ is_reparse_point_included(LPCWSTR fname)
     WCHAR      buf[MAX_PATH];
     DWORD      attr;
 
-    if (isalpha(p[0]) && p[1] == L':' && is_path_sep(p[2]))
+    if (SAFE_isalpha(p[0]) && p[1] == L':' && is_path_sep(p[2]))
        p += 3;
     else if (is_path_sep(p[0]) && is_path_sep(p[1]))
        p += 2;
diff --git a/src/os_unix.c b/src/os_unix.c
index 11448c5c6..af8f00604 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -6171,7 +6171,7 @@ mch_signal_job(job_T *job, char_u *how)
     else if (STRCMP(how, "winch") == 0)
        sig = SIGWINCH;
 #endif
-    else if (isdigit(*how))
+    else if (SAFE_isdigit(*how))
        sig = atoi((char *)how);
     else
        return FAIL;
diff --git a/src/os_win32.c b/src/os_win32.c
index e5cfac729..dbfc4eeca 100644
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -7443,7 +7443,7 @@ notsgr:
        {
            int l = 2;
 
-           if (isdigit(s[l]))
+           if (SAFE_isdigit(s[l]))
                l++;
            if (s[l] == ' ' && s[l + 1] == 'q')
            {
diff --git a/src/spellfile.c b/src/spellfile.c
index d3351ef23..24df042b7 100644
--- a/src/spellfile.c
+++ b/src/spellfile.c
@@ -2890,7 +2890,7 @@ spell_read_aff(spellinfo_T *spin, char_u *fname)
                     || is_aff_rule(items, itemcnt, "REPSAL", 2))
            {
                // Ignore REP/REPSAL count
-               if (!isdigit(*items[1]))
+               if (!SAFE_isdigit(*items[1]))
                    smsg(_("Expected REP(SAL) count in %s line %d"),
                                                                 fname, lnum);
            }
@@ -2925,7 +2925,7 @@ spell_read_aff(spellinfo_T *spin, char_u *fname)
                {
                    // First line contains the count.
                    found_map = TRUE;
-                   if (!isdigit(*items[1]))
+                   if (!SAFE_isdigit(*items[1]))
                        smsg(_("Expected MAP count in %s line %d"),
                                                                 fname, lnum);
                }
diff --git a/src/tag.c b/src/tag.c
index 8003156f0..893415f69 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -1194,7 +1194,7 @@ add_llist_tags(
        // Get the line number or the search pattern used to locate
        // the tag.
        lnum = 0;
-       if (isdigit(*tagp.command))
+       if (SAFE_isdigit(*tagp.command))
            // Line number is used to locate the tag
            lnum = atol((char *)tagp.command);
        else
diff --git a/src/term.c b/src/term.c
index 0fdb33e6d..dd59fdf65 100644
--- a/src/term.c
+++ b/src/term.c
@@ -3434,7 +3434,7 @@ ttest(int pairs)
 #endif
     {
        env_colors = mch_getenv((char_u *)"COLORS");
-       if (env_colors != NULL && isdigit(*env_colors))
+       if (env_colors != NULL && SAFE_isdigit(*env_colors))
        {
            int colors = atoi((char *)env_colors);
 
@@ -5849,7 +5849,7 @@ handle_dcs(char_u *tp, char_u *argp, int len, char_u 
*key_name, int *slen)
        // characters.
        for (i = j + 3; i < len; ++i)
        {
-           if (i - j == 3 && !isdigit(tp[i]))
+           if (i - j == 3 && !SAFE_isdigit(tp[i]))
                break;
            if (i - j == 4 && tp[i] != ' ')
                break;
@@ -6083,7 +6083,7 @@ check_termcode(
                        // The mouse termcode "ESC [" is also the prefix of
                        // "ESC [ I" (focus gained) and other keys.  Check some
                        // more bytes to find out.
-                       if (!isdigit(tp[2]))
+                       if (!SAFE_isdigit(tp[2]))
                        {
                            // ESC [ without number following: Only use it when
                            // there is no other match.
@@ -6166,7 +6166,7 @@ check_termcode(
                            // Skip over the digits, the final char must
                            // follow. URXVT can use a negative value, thus
                            // also accept '-'.
-                           for (j = slen - 2; j < len && (isdigit(tp[j])
+                           for (j = slen - 2; j < len && (SAFE_isdigit(tp[j])
                                       || tp[j] == '-' || tp[j] == ';'); ++j)
                                ;
                            ++j;
diff --git a/src/terminal.c b/src/terminal.c
index f79d102e8..a641a850b 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -853,13 +853,13 @@ ex_terminal(exarg_T *eap)
            else
                opt.jo_term_api = NULL;
        }
-       else if (OPTARG_HAS("rows") && ep != NULL && isdigit(ep[1]))
+       else if (OPTARG_HAS("rows") && ep != NULL && SAFE_isdigit(ep[1]))
        {
            opt.jo_set2 |= JO2_TERM_ROWS;
            opt.jo_term_rows = atoi((char *)ep + 1);
            p = skiptowhite(cmd);
        }
-       else if (OPTARG_HAS("cols") && ep != NULL && isdigit(ep[1]))
+       else if (OPTARG_HAS("cols") && ep != NULL && SAFE_isdigit(ep[1]))
        {
            opt.jo_set2 |= JO2_TERM_COLS;
            opt.jo_term_cols = atoi((char *)ep + 1);
@@ -5463,11 +5463,11 @@ read_dump_file(FILE *fd, VTermPos *cursor_pos)
                    // use same attr as previous cell
                    c = fgetc(fd);
                }
-               else if (isdigit(c))
+               else if (SAFE_isdigit(c))
                {
                    // get the decimal attribute
                    attr = 0;
-                   while (isdigit(c))
+                   while (SAFE_isdigit(c))
                    {
                        attr = attr * 10 + (c - '0');
                        c = fgetc(fd);
@@ -5499,9 +5499,9 @@ read_dump_file(FILE *fd, VTermPos *cursor_pos)
                            c = fgetc(fd);
                            blue = (blue << 4) + hex2nr(c);
                            c = fgetc(fd);
-                           if (!isdigit(c))
+                           if (!SAFE_isdigit(c))
                                dump_is_corrupt(&ga_text);
-                           while (isdigit(c))
+                           while (SAFE_isdigit(c))
                            {
                                index = index * 10 + (c - '0');
                                c = fgetc(fd);
@@ -5565,7 +5565,7 @@ read_dump_file(FILE *fd, VTermPos *cursor_pos)
                for (;;)
                {
                    c = fgetc(fd);
-                   if (!isdigit(c))
+                   if (!SAFE_isdigit(c))
                        break;
                    count = count * 10 + (c - '0');
                }
diff --git a/src/typval.c b/src/typval.c
index 35c9e24eb..af96b3170 100644
--- a/src/typval.c
+++ b/src/typval.c
@@ -2425,7 +2425,7 @@ eval_string(char_u **arg, typval_T *rettv, int evaluate, 
int interpolate)
                          if (vim_isxdigit(p[1]))
                          {
                              int       n, nr;
-                             int       c = toupper(*p);
+                             int       c = SAFE_toupper(*p);
 
                              if (c == 'X')
                                  n = 2;
diff --git a/src/uninstall.c b/src/uninstall.c
index 78b2b7d3c..907ed3797 100644
--- a/src/uninstall.c
+++ b/src/uninstall.c
@@ -29,7 +29,7 @@ confirm(void)
     char       answer[10];
 
     fflush(stdout);
-    return (scanf(" %c", answer) == 1 && toupper(answer[0]) == 'Y');
+    return (scanf(" %c", answer) == 1 && toupper((unsigned char)answer[0]) == 
'Y');
 }
 
     static int
diff --git a/src/userfunc.c b/src/userfunc.c
index c0a2487b4..64761ecdb 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -77,7 +77,7 @@ one_function_arg(
 
     while (ASCII_ISALNUM(*p) || *p == '_')
        ++p;
-    if (arg == p || isdigit(*arg)
+    if (arg == p || SAFE_isdigit(*arg)
            || (argtypes == NULL
                && ((p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0)
                    || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0))))
@@ -2272,7 +2272,7 @@ func_requires_g_prefix(ufunc_T *ufunc)
     return ufunc->uf_name[0] != K_SPECIAL
            && (ufunc->uf_flags & FC_LAMBDA) == 0
            && vim_strchr(ufunc->uf_name, AUTOLOAD_CHAR) == NULL
-           && !isdigit(ufunc->uf_name[0]);
+           && !SAFE_isdigit(ufunc->uf_name[0]);
 }
 
 /*
@@ -2448,8 +2448,8 @@ cleanup_function_call(funccall_T *fc)
     static int
 numbered_function(char_u *name)
 {
-    return isdigit(*name)
-           || (name[0] == 'g' && name[1] == ':' && isdigit(name[2]));
+    return SAFE_isdigit(*name)
+           || (name[0] == 'g' && name[1] == ':' && SAFE_isdigit(name[2]));
 }
 
 /*
@@ -4653,7 +4653,7 @@ list_functions(regmatch_T *regmatch)
                    && (regmatch == NULL
                        ? !message_filtered(fp->uf_name)
                            && !func_name_refcount(fp->uf_name)
-                       : !isdigit(*fp->uf_name)
+                       : !SAFE_isdigit(*fp->uf_name)
                            && vim_regexec(regmatch, fp->uf_name, 0)))
            {
                if (list_func_head(fp, FALSE) == FAIL)
diff --git a/src/version.c b/src/version.c
index 42d58897e..3dc537d18 100644
--- a/src/version.c
+++ b/src/version.c
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    6,
 /**/
     5,
 /**/
@@ -1328,9 +1330,9 @@ do_intro_line(
        if (highest_patch())
        {
            // Check for 9.9x or 9.9xx, alpha/beta version
-           if (isalpha((int)vers[3]))
+           if (SAFE_isalpha((int)vers[3]))
            {
-               int len = (isalpha((int)vers[4])) ? 5 : 4;
+               int len = (SAFE_isalpha((int)vers[4])) ? 5 : 4;
                sprintf((char *)vers + len, ".%d%s", highest_patch(),
                                                         mediumVersion + len);
            }
diff --git a/src/vim9compile.c b/src/vim9compile.c
index ad1f6b4aa..d6faa7bb9 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -3159,7 +3159,7 @@ get_cmd_count(char_u *line, exarg_T *eap)
     // skip over colons and white space
     for (p = line; *p == ':' || VIM_ISWHITE(*p); ++p)
        ;
-    if (!isdigit(*p))
+    if (!SAFE_isdigit(*p))
     {
        // The command or modifiers must be following.  Assume a lower case
        // character means there is a modifier.
diff --git a/src/vim9expr.c b/src/vim9expr.c
index 31fa824a7..38a65d442 100644
--- a/src/vim9expr.c
+++ b/src/vim9expr.c
@@ -1950,7 +1950,7 @@ get_compare_type(char_u *p, int *len, int *type_is)
                        if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
                            *len = 5;
                        i = p[*len];
-                       if (!isalnum(i) && i != '_')
+                       if (!SAFE_isalnum(i) && i != '_')
                        {
                            type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
                            *type_is = TRUE;
diff --git a/src/viminfo.c b/src/viminfo.c
index 58bf41919..540422c8c 100644
--- a/src/viminfo.c
+++ b/src/viminfo.c
@@ -1068,7 +1068,7 @@ barline_parse(vir_T *virp, char_u *text, garray_T *values)
            }
        }
 
-       if (isdigit(*p))
+       if (SAFE_isdigit(*p))
        {
            value->bv_type = BVAL_NR;
            value->bv_nr = getdigits(&p);
@@ -2485,7 +2485,7 @@ read_viminfo_filemark(vir_T *virp, int force)
     str = virp->vir_line + 1;
     if (*str <= 127
            && ((*virp->vir_line == '\''
-                                      && (VIM_ISDIGIT(*str) || isupper(*str)))
+                                      && (VIM_ISDIGIT(*str) || 
SAFE_isupper(*str)))
             || (*virp->vir_line == '-' && *str == '\'')))
     {
        if (*str == '\'')
diff --git a/src/xxd/xxd.c b/src/xxd/xxd.c
index c90bc027e..26f8d8365 100644
--- a/src/xxd/xxd.c
+++ b/src/xxd/xxd.c
@@ -96,8 +96,8 @@
 # include <unistd.h>
 #endif
 #include <stdlib.h>
-#include <string.h>    /* for strncmp() */
-#include <ctype.h>     /* for isalnum() */
+#include <string.h>
+#include <ctype.h>
 #include <limits.h>
 #if __MWERKS__ && !defined(BEBOX)
 # include <unix.h>     /* for fdopen() on MAC */
@@ -208,7 +208,7 @@ char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = 
hexxa;
 #define HEX_BITS 3             /* not hex a dump, but bits: 01111001 */
 #define HEX_LITTLEENDIAN 4
 
-#define CONDITIONAL_CAPITALIZE(c) (capitalize ? toupper((int)c) : c)
+#define CONDITIONAL_CAPITALIZE(c) (capitalize ? toupper((unsigned char)(c)) : 
(c))
 
 #define COLOR_PROLOGUE \
 l[c++] = '�'; \
@@ -952,9 +952,9 @@ main(int argc, char *argv[])
 
       if (varname != NULL)
        {
-         FPRINTF_OR_DIE((fpo, "unsigned char %s", isdigit((int)varname[0]) ? 
"__" : ""));
+         FPRINTF_OR_DIE((fpo, "unsigned char %s", isdigit((unsigned 
char)varname[0]) ? "__" : ""));
          for (e = 0; (c = varname[e]) != 0; e++)
-           putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
+           putc_or_die(isalnum((unsigned char)c) ? CONDITIONAL_CAPITALIZE(c) : 
'_', fpo);
          fputs_or_die("[] = {
", fpo);
        }
 
@@ -972,9 +972,9 @@ main(int argc, char *argv[])
       if (varname != NULL)
        {
          fputs_or_die("};
", fpo);
-         FPRINTF_OR_DIE((fpo, "unsigned int %s", isdigit((int)varname[0]) ? 
"__" : ""));
+         FPRINTF_OR_DIE((fpo, "unsigned int %s", isdigit((unsigned 
char)varname[0]) ? "__" : ""));
          for (e = 0; (c = varname[e]) != 0; e++)
-           putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
+           putc_or_die(isalnum((unsigned char)c) ? CONDITIONAL_CAPITALIZE(c) : 
'_', fpo);
          FPRINTF_OR_DIE((fpo, "_%s = %d;
", capitalize ? "LEN" : "len", p));
        }
 

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1rLULs-00D0CR-Cg%40256bit.org.

Raspunde prin e-mail lui