summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Thompson <Keith.S.Thompson@gmail.com>2024-01-04 21:19:04 +0100
committerChristian Brabandt <cb@256bit.org>2024-01-04 21:19:04 +0100
commit184f71cc6868a240dc872ed2852542bbc1d43e28 (patch)
tree314948c5cf288feb24305b329d58cbd750157560
parent4d8cb683b1543ec02563cdd2d068ce5f82f90539 (diff)
patch 9.1.0006: is*() and to*() function may be unsafev9.1.0006
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>
-rw-r--r--runtime/tools/ccfilter.c6
-rw-r--r--runtime/tools/xcmdsrv_client.c6
-rw-r--r--src/buffer.c4
-rw-r--r--src/charset.c4
-rw-r--r--src/cmdhist.c2
-rw-r--r--src/diff.c4
-rw-r--r--src/dosinst.c2
-rw-r--r--src/edit.c2
-rw-r--r--src/eval.c2
-rw-r--r--src/evalfunc.c2
-rw-r--r--src/evalvars.c4
-rw-r--r--src/ex_cmds.c2
-rw-r--r--src/ex_docmd.c6
-rw-r--r--src/filepath.c2
-rw-r--r--src/findfile.c6
-rw-r--r--src/getchar.c4
-rw-r--r--src/gui.c2
-rw-r--r--src/gui_haiku.cc11
-rw-r--r--src/gui_photon.c6
-rw-r--r--src/gui_xim.c6
-rw-r--r--src/hardcopy.c4
-rw-r--r--src/highlight.c2
-rw-r--r--src/if_py_both.h2
-rw-r--r--src/if_xcmdsrv.c6
-rw-r--r--src/macros.h30
-rw-r--r--src/mbyte.c6
-rw-r--r--src/normal.c8
-rw-r--r--src/ops.c8
-rw-r--r--src/option.c2
-rw-r--r--src/os_mswin.c6
-rw-r--r--src/os_unix.c2
-rw-r--r--src/os_win32.c2
-rw-r--r--src/spellfile.c4
-rw-r--r--src/tag.c2
-rw-r--r--src/term.c8
-rw-r--r--src/terminal.c14
-rw-r--r--src/typval.c2
-rw-r--r--src/uninstall.c2
-rw-r--r--src/userfunc.c10
-rw-r--r--src/version.c6
-rw-r--r--src/vim9compile.c2
-rw-r--r--src/vim9expr.c2
-rw-r--r--src/viminfo.c4
-rw-r--r--src/xxd/xxd.c14
44 files changed, 122 insertions, 109 deletions
diff --git a/runtime/tools/ccfilter.c b/runtime/tools/ccfilter.c
index 43489f16c2..ae1443e203 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\n", FileName, Row, Col, Severity, p );
else
diff --git a/runtime/tools/xcmdsrv_client.c b/runtime/tools/xcmdsrv_client.c
index e1aea10667..81ca66ceb9 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 9ee74f54dd..64e4926475 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 bda3f911b6..0e4dbbe1dc 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 96a9b3e95b..6342f02bdd 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 158870402b..9b8c816b5b 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 4eae5aadc4..35625a7946 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 9435fd6fc7..f89d43eec6 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 8563aa6d79..815d13d42a 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 f87c08ffc5..513ddccdbe 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 ea039cbed1..8e42c5a307 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 d214933626..d8e891c2ba 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 534cd7e038..c18a9107ec 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 1ea0623867..cbf2da4136 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 246a81898a..2636609250 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 da05033709..3427a9f8da 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 9c9aa3cbec..16c1b54c67 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 c8b05e1be2..d083226547 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 b987e9b8a8..9bce94ddfa 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 88de7a4e98..c9b1c6cb4d 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 = '\0';
diff --git a/src/hardcopy.c b/src/hardcopy.c
index e91a7dc2d7..8abfff2107 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 31c3280e85..318564c74b 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 f8438639e6..42db5101d8 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 d9408398d9..716665a7be 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 cc2d11fdd1..190778eca3 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 34592bd56c..ee2834cf42 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 61a19c13a4..fd89b00fd4 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 46101a4359..f6d765bd71 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 4d12834f2e..7cac89e5cf 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 46f73752f9..21b7db31f3 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':' &