]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.0006: is*() and to*() function may be unsafe v9.1.0006
authorKeith Thompson <Keith.S.Thompson@gmail.com>
Thu, 4 Jan 2024 20:19:04 +0000 (21:19 +0100)
committerChristian Brabandt <cb@256bit.org>
Thu, 4 Jan 2024 20:19:04 +0000 (21:19 +0100)
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 <Keith.S.Thompson@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
44 files changed:
runtime/tools/ccfilter.c
runtime/tools/xcmdsrv_client.c
src/buffer.c
src/charset.c
src/cmdhist.c
src/diff.c
src/dosinst.c
src/edit.c
src/eval.c
src/evalfunc.c
src/evalvars.c
src/ex_cmds.c
src/ex_docmd.c
src/filepath.c
src/findfile.c
src/getchar.c
src/gui.c
src/gui_haiku.cc
src/gui_photon.c
src/gui_xim.c
src/hardcopy.c
src/highlight.c
src/if_py_both.h
src/if_xcmdsrv.c
src/macros.h
src/mbyte.c
src/normal.c
src/ops.c
src/option.c
src/os_mswin.c
src/os_unix.c
src/os_win32.c
src/spellfile.c
src/tag.c
src/term.c
src/terminal.c
src/typval.c
src/uninstall.c
src/userfunc.c
src/version.c
src/vim9compile.c
src/vim9expr.c
src/viminfo.c
src/xxd/xxd.c

index 43489f16c290f73465e57a0298d5ecc16da2d239..ae1443e203cebb09a50fa11ab5ee45c9a3d3f968 100644 (file)
@@ -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\n", FileName, Row, Col, Severity, p );
          else
index e1aea10667914e4b96185904e7e49024c21c8da1..81ca66ceb984ce9c6fa56b0311529d0e174d144a 100644 (file)
@@ -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]));
 }
index 9ee74f54dd6fd3648dff55cee48b78324a163541..64e49264754fae3e4616ced311014140767b3721 100644 (file)
@@ -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] == '=')))
index bda3f911b685e3419b3518210f8b28b4cada5c13..0e4dbbe1dca99a76bb347863a4ccdd1265a40152 100644 (file)
@@ -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
index 96a9b3e95b86f18c00dd25013abec42bdbbee603..6342f02bdd704dac8dce62e9444a5b92d021b219 100644 (file)
@@ -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)
index 158870402ba11a2712d50632da29d647ab08e401..9b8c816b5b5c785aaa587b1b4dfa8f3b89d35d74 100644 (file)
@@ -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;
index 4eae5aadc4c27d9042a4690a655812ba1acc5d59..35625a7946c0a049670af5ff7e229ca04810b063 100644 (file)
@@ -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);
index 9435fd6fc7e2d104f786e9faf13fe9c5e875727b..f89d43eec628b433489844840aaf71a46b6c0e25 100644 (file)
@@ -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;
index 8563aa6d79f5dc745eee9319c604954c4fe82f96..815d13d42aa9384f6bc60021a6152fc6aaba3459 100644 (file)
@@ -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;
index f87c08ffc5988a305edeb475cb23d268cd6c1d56..513ddccdbe7f8ffd944b641e127b3af862bc06b1 100644 (file)
@@ -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)
index ea039cbed1ff49f10230d5e60c760d2bb122418c..8e42c5a307e403184ef191d699e6bb47c4bbf145 100644 (file)
@@ -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)
        {
index d2149336262155a6d1b9be20fffe03f6afd99a26..d8e891c2baa8fc524f453750abc6db2211cfb00b 100644 (file)
@@ -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;
index 534cd7e0380e39018e5fd7517ece1955c9f17367..c18a9107ec77ce09571d0a366bf6756506e9b404 100644 (file)
@@ -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);
                }
            }
index 1ea062386716e57204e4d9a84424471c9be42b5b..cbf2da41360bd781b4a7b7fbf074fa136c197323 100644 (file)
@@ -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;
index 246a81898a5063d316a02a5e05a1f45f556ac819..263660925041697cca594e03e3b5f0376b697f94 100644 (file)
@@ -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);
        }
     }
index da0503370965f2ef843c788ac7626eedbd1152ee..3427a9f8da63fa65ef24b08e4eb5ff97627265b1 100644 (file)
@@ -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;
index 9c9aa3cbecdcf94a5bd9cc24f697cd4426a61390..16c1b54c67926b1f832830207f53eaf0d8d77cb0 100644 (file)
--- 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)
index c8b05e1be2a4709216452e2ab6eb2944adc92704..d083226547afb94d5fe5d3f67351615a180f802b 100644 (file)
@@ -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.
  *
index b987e9b8a8752daadf2a79f0346ec0583366e5e6..9bce94ddfaa125a4a48e8c86bcfafed44b7c0347 100644 (file)
@@ -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;
index 88de7a4e98e1ae71fdad8f7f005d88366f84a7ef..c9b1c6cb4da79d7930ba8b27478eeaf00b90e849 100644 (file)
@@ -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 = '\0';
 
index e91a7dc2d7362b5cb5bb2a9907f6585aa323a96d..8abfff210737711ffb686122c26d01f16e2c64dd 100644 (file)
@@ -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++;
     }
index 31c3280e8592b9b3286721837f030600d03647f3..318564c74b921d316e0478c9343dd2082caddca2 100644 (file)
@@ -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')
index f8438639e61e49b25d34d878215bcdc4b24a9ac2..42db5101d8a05541623343aa465e2005a82898ca 100644 (file)
@@ -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))
        {
index d9408398d9e119591acfc0a4d5b4642b3a7aac9e..716665a7be69e4313695ed5e3428583f56f33c05 100644 (file)
@@ -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)
index cc2d11fdd162a86253674cfcb9ceb33377f08bf6..190778eca39e80dd80ce273d919a3776fba1631b 100644 (file)
  */
 #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
 #  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
 
index 34592bd56ce1da4bd4beaa4a417b7c97a607f55a..ee2834cf42f81cc299cf13248f3eb6b4ab28164e 100644 (file)
@@ -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;
index 61a19c13a43c905ecfc5cb219bd1e9a79a43f2c1..fd89b00fd4ae6cb85a9cc56de17b2cb1bf1609c7 100644 (file)
@@ -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)
        {
index 46101a43597a72b59a97348e84effb45b6264a82..f6d765bd71d1f9f9bd9f28406af0b64d49e7b76a 100644 (file)
--- 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;
index 4d12834f2e5a97fcc6c6374ba9e18346a4cc4ccc..7cac89e5cfb0a3e3e70749fe895a6752193458cc 100644 (file)
@@ -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';
index 46f73752f9b5681f7dc27a230957a768955faee4..21b7db31f3daebba5963201186592721dd37d23e 100644 (file)
@@ -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;
index 11448c5c62b7171185838b737f495b02136aaa8f..af8f00604c677033ae2e6a6175b28e4203046e6a 100644 (file)
@@ -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;
index e5cfac7294bde19bce991e15684cef6807d0ec37..dbfc4eeca70fc5b9c2d749ab7c5d88c6d9bf9bcd 100644 (file)
@@ -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')
            {
index d3351ef23a2e170aac6f099acfee952e59059fcb..24df042b764af79a22642b99efe35f044e3609f1 100644 (file)
@@ -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);
                }
index 8003156f0f957b89c5a05c5f1663b5efb8824ea1..893415f699df25a9dcf2621736c808fc756f3069 100644 (file)
--- 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
index 0fdb33e6d7c89ed0fa14c5106349dda032394472..dd59fdf65dc179a60fa68300b39d214e4a9732d1 100644 (file)
@@ -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;
index f79d102e8cba97a26f3dd3ecff91b1fff61ddf9b..a641a850b0c943b963a22ba70fcdb22ad181dcb3 100644 (file)
@@ -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');
                }
index 35c9e24eb8559867bff15aefb2106e183783d958..af96b3170b64803e74f4b3c6f566c7af0c392af8 100644 (file)
@@ -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;
index 78b2b7d3cf0946bac80874932806b1a33ac3eab4..907ed3797644a3df1704eb0924c5fa22bd7614d7 100644 (file)
@@ -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
index c0a2487b46611763cd63daab9346589315dec5d6..64761ecdb7ba80e40422769d0c5f7b0b22638969 100644 (file)
@@ -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)
index 42d58897e585194f8f1aaa22385f118bacec3b64..3dc537d1803d3f357cabae82313d464c7fd670ec 100644 (file)
@@ -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);
            }
index ad1f6b4aa8717605fe0e27247301afb967202d5a..d6faa7bb9751f4f997910be22f195ab88f2111e2 100644 (file)
@@ -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.
index 31fa824a7bcda79eb52c7ce6a836c9df2d50c923..38a65d4424546bfab7d099c0e7abf59c115a1bbb 100644 (file)
@@ -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;
index 58bf419194a519abbbccbb6af60618772a8b63f4..540422c8ca57e32fe874d20ba551eeaea004f7bf 100644 (file)
@@ -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 == '\'')
index c90bc027e8daebec50fadcc4e5f27a5501d7354f..26f8d8365d79a39951e1a32ef8028859858f08aa 100644 (file)
@@ -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++] = '\033'; \
@@ -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("[] = {\n", fpo);
        }
 
@@ -972,9 +972,9 @@ main(int argc, char *argv[])
       if (varname != NULL)
        {
          fputs_or_die("};\n", 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;\n", capitalize ? "LEN" : "len", p));
        }