From a76109c586944d9ace03ca6a54b7f8173f6c0deb Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 5 Mar 2023 13:15:57 +0000 Subject: [PATCH] Add some missing casts in ctype functions. I thought I'd found all of these before, but perhaps a few managed to slip in since I last looked. The character argument to the functions must have the value of an unsigned char or EOF; passing an ordinary char (unless you know char is unsigned on every platform the code will ever go near) risks mistaking '\xFF' for EOF, and causing outright undefined behaviour on byte values in the range 80-FE. Never do it. --- ssh/sesschan.c | 3 ++- utils/validate_manual_hostkey.c | 2 +- windows/pageant.c | 2 +- windows/unicode.c | 10 ++++++---- windows/utils/split_into_argv.c | 6 +++--- windows/window.c | 2 +- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/ssh/sesschan.c b/ssh/sesschan.c index b500f77d..55d868e0 100644 --- a/ssh/sesschan.c +++ b/ssh/sesschan.c @@ -426,7 +426,8 @@ bool sesschan_enable_x11_forwarding( const unsigned char *hex = authdata_hex.ptr; char hexbuf[3]; - if (!isxdigit(hex[i]) || !isxdigit(hex[i+1])) { + if (!isxdigit((unsigned char)hex[i]) || + !isxdigit((unsigned char)hex[i+1])) { strbuf_free(authdata_bin); return false; /* not hex */ } diff --git a/utils/validate_manual_hostkey.c b/utils/validate_manual_hostkey.c index 7c5d1b88..dd7c1aee 100644 --- a/utils/validate_manual_hostkey.c +++ b/utils/validate_manual_hostkey.c @@ -63,7 +63,7 @@ bool validate_manual_hostkey(char *key) if (r[3*i+2] != ':') goto not_fingerprint; /* sorry */ for (i = 0; i < 16*3 - 1; i++) - key[i] = tolower(r[i]); + key[i] = tolower((unsigned char)r[i]); key[16*3 - 1] = '\0'; return true; } diff --git a/windows/pageant.c b/windows/pageant.c index cb4c1186..9c7a5696 100644 --- a/windows/pageant.c +++ b/windows/pageant.c @@ -1835,7 +1835,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) args = strchr(command, ' '); if (args) { *args++ = 0; - while (*args && isspace(*args)) args++; + while (*args && isspace((unsigned char)*args)) args++; } spawn_cmd(command, args, show); } diff --git a/windows/unicode.c b/windows/unicode.c index 26ffcb6f..412db6ea 100644 --- a/windows/unicode.c +++ b/windows/unicode.c @@ -1076,9 +1076,11 @@ static int check_compose_internal(int first, int second, int recurse) if (recurse == 0) { nc = check_compose_internal(second, first, 1); if (nc == -1) - nc = check_compose_internal(toupper(first), toupper(second), 1); + nc = check_compose_internal(toupper((unsigned char)first), + toupper((unsigned char)second), 1); if (nc == -1) - nc = check_compose_internal(toupper(second), toupper(first), 1); + nc = check_compose_internal(toupper((unsigned char)second), + toupper((unsigned char)first), 1); } return nc; } @@ -1102,9 +1104,9 @@ int decode_codepage(const char *cp_name) s = cp_name; d = cpi->name; for (;;) { - while (*s && !isalnum(*s) && *s != ':') + while (*s && !isalnum((unsigned char)*s) && *s != ':') s++; - while (*d && !isalnum(*d) && *d != ':') + while (*d && !isalnum((unsigned char)*d) && *d != ':') d++; if (*s == 0) { codepage = cpi->codepage; diff --git a/windows/utils/split_into_argv.c b/windows/utils/split_into_argv.c index 1c17f0ce..b6daada4 100644 --- a/windows/utils/split_into_argv.c +++ b/windows/utils/split_into_argv.c @@ -173,7 +173,7 @@ void split_into_argv(char *cmdline, bool includes_program_name, * First deal with the simplest of all special cases: if there * aren't any arguments, return 0,NULL,NULL. */ - while (*cmdline && isspace(*cmdline)) cmdline++; + while (*cmdline && isspace((unsigned char)*cmdline)) cmdline++; if (!*cmdline) { if (argc) *argc = 0; if (argv) *argv = NULL; @@ -195,7 +195,7 @@ void split_into_argv(char *cmdline, bool includes_program_name, bool quote; /* Skip whitespace searching for start of argument. */ - while (*p && isspace(*p)) p++; + while (*p && isspace((unsigned char)*p)) p++; if (!*p) break; /* @@ -240,7 +240,7 @@ void split_into_argv(char *cmdline, bool includes_program_name, /* Copy data into the argument until it's finished. */ while (*p) { - if (!quote && isspace(*p)) + if (!quote && isspace((unsigned char)*p)) break; /* argument is finished */ if (*p == '"' || (*p == '\\' && backslash_special)) { diff --git a/windows/window.c b/windows/window.c index 9f666d47..21507829 100644 --- a/windows/window.c +++ b/windows/window.c @@ -863,7 +863,7 @@ char *handle_restrict_acl_cmdline_prefix(char *p) * pointer past the prefix. Returns the updated pointer (whether * it moved or not). */ - while (*p && isspace(*p)) + while (*p && isspace((unsigned char)*p)) p++; if (*p == '&' && p[1] == 'R' && (!p[2] || p[2] == '@' || p[2] == '&')) {