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 <Keith.S.Thompson@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/buffer.c b/src/buffer.c
index 9ee74f5..64e4926 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -4022,7 +4022,7 @@
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 @@
&& (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 bda3f91..0e4dbbe 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -1958,7 +1958,7 @@
if (enc_latin1like)
return (latin1flags[c] & LATIN1LOWER) == LATIN1LOWER;
}
- return islower(c);
+ return SAFE_islower(c);
}
int
@@ -1982,7 +1982,7 @@
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 96a9b3e..6342f02 100644
--- a/src/cmdhist.c
+++ b/src/cmdhist.c
@@ -674,7 +674,7 @@
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 1588704..9b8c816 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -1712,7 +1712,7 @@
// --- 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 @@
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 4eae5aa..35625a7 100644
--- a/src/dosinst.c
+++ b/src/dosinst.c
@@ -2760,7 +2760,7 @@
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 9435fd6..f89d43e 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -5318,7 +5318,7 @@
// 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 8563aa6..815d13d 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -4276,7 +4276,7 @@
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 f87c08f..513ddcc 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -6744,7 +6744,7 @@
&& 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 ea039cb..8e42c5a 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -3332,7 +3332,7 @@
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 @@
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 d214933..d8e891c 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -3707,7 +3707,7 @@
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 534cd7e..c18a910 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -7996,7 +7996,7 @@
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 @@
if (*p == NUL)
count = 1;
- else if (isdigit(*p))
+ else if (SAFE_isdigit(*p))
{
count = getdigits(&p);
switch (*p)
@@ -8490,7 +8490,7 @@
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 1ea0623..cbf2da4 100644
--- a/src/filepath.c
+++ b/src/filepath.c
@@ -2953,7 +2953,7 @@
#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 246a818..2636609 100644
--- a/src/findfile.c
+++ b/src/findfile.c
@@ -1847,7 +1847,7 @@
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 @@
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 da05033..3427a9f 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -870,7 +870,7 @@
{
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 @@
// 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 9c9aa3c..16c1b54 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -5030,7 +5030,7 @@
// 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 c8b05e1..d083226 100644
--- a/src/gui_haiku.cc
+++ b/src/gui_haiku.cc
@@ -4031,17 +4031,6 @@
// 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 b987e9b..9bce94d 100644
--- a/src/gui_photon.c
+++ b/src/gui_photon.c
@@ -977,7 +977,7 @@
if (mark != NULL)
{
mark++;
- while (isdigit(*mark))
+ while (SAFE_isdigit(*mark))
mark++;
if (*mark == ')')
@@ -2545,7 +2545,7 @@
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 @@
{
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 88de7a4..c9b1c6c 100644
--- a/src/gui_xim.c
+++ b/src/gui_xim.c
@@ -1471,7 +1471,7 @@
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 @@
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 @@
ns++;
else
end = s + strlen(s);
- while (isspace((unsigned char)*end))
+ while (SAFE_isspace(*end))
end--;
*end = '\0';
diff --git a/src/hardcopy.c b/src/hardcopy.c
index e91a7dc..8abfff2 100644
--- a/src/hardcopy.c
+++ b/src/hardcopy.c
@@ -1745,7 +1745,7 @@
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 @@
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 31c3280..318564c 100644
--- a/src/highlight.c
+++ b/src/highlight.c
@@ -2307,7 +2307,7 @@
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 f843863..42db510 100644
--- a/src/if_py_both.h
+++ b/src/if_py_both.h
@@ -3240,7 +3240,7 @@
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 d940839..716665a 100644
--- a/src/if_xcmdsrv.c
+++ b/src/if_xcmdsrv.c
@@ -657,7 +657,7 @@
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 @@
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 @@
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 cc2d11f..190778e 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 34592bd..ee2834c 100644
--- a/src/mbyte.c
+++ b/src/mbyte.c
@@ -4628,7 +4628,7 @@
}
// "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 @@
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 @@
{
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 61a19c1..fd89b00 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -4470,11 +4470,11 @@
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 @@
// 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 46101a4..f6d765b 100644
--- a/src/ops.c
+++ b/src/ops.c
@@ -2734,7 +2734,7 @@
{
if (CharOrd(firstdigit) < Prenum1)
{
- if (isupper(firstdigit))
+ if (SAFE_isupper(firstdigit))
firstdigit = 'A';
else
firstdigit = 'a';
@@ -2746,7 +2746,7 @@
{
if (26 - CharOrd(firstdigit) - 1 < Prenum1)
{
- if (isupper(firstdigit))
+ if (SAFE_isupper(firstdigit))
firstdigit = 'Z';
else
firstdigit = 'z';
@@ -2875,9 +2875,9 @@
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 4d12834..7cac89e 100644
--- a/src/option.c
+++ b/src/option.c
@@ -7697,7 +7697,7 @@
{
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 46f7375..21b7db3 100644
--- a/src/os_mswin.c
+++ b/src/os_mswin.c
@@ -675,7 +675,7 @@
{
// 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 @@
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 @@
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 11448c5..af8f006 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -6171,7 +6171,7 @@
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 e5cfac7..dbfc4ee 100644
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -7443,7 +7443,7 @@
{
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 d3351ef..24df042 100644
--- a/src/spellfile.c
+++ b/src/spellfile.c
@@ -2890,7 +2890,7 @@
|| 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 @@
{
// 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 8003156..893415f 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -1194,7 +1194,7 @@
// 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 0fdb33e..dd59fdf 100644
--- a/src/term.c
+++ b/src/term.c
@@ -3434,7 +3434,7 @@
#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 @@
// 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 @@
// 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 @@
// 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 f79d102..a641a85 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -853,13 +853,13 @@
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 @@
// 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 @@
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 @@
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 35c9e24..af96b31 100644
--- a/src/typval.c
+++ b/src/typval.c
@@ -2425,7 +2425,7 @@
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 78b2b7d..907ed37 100644
--- a/src/uninstall.c
+++ b/src/uninstall.c
@@ -29,7 +29,7 @@
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 c0a2487..64761ec 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -77,7 +77,7 @@
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 @@
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 @@
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 @@
&& (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 42d5889..3dc537d 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 6,
+/**/
5,
/**/
4,
@@ -1328,9 +1330,9 @@
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 ad1f6b4..d6faa7b 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -3159,7 +3159,7 @@
// 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 31fa824..38a65d4 100644
--- a/src/vim9expr.c
+++ b/src/vim9expr.c
@@ -1950,7 +1950,7 @@
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 58bf419..540422c 100644
--- a/src/viminfo.c
+++ b/src/viminfo.c
@@ -1068,7 +1068,7 @@
}
}
- if (isdigit(*p))
+ if (SAFE_isdigit(*p))
{
value->bv_type = BVAL_NR;
value->bv_nr = getdigits(&p);
@@ -2485,7 +2485,7 @@
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 c90bc02..26f8d83 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 @@
#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 @@
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 @@
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));
}