From bece41ddb0098f30d038cb4bcf6befe9c514c776 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Wed, 19 Apr 2023 14:21:32 +0100 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. (cherry picked from commit a76109c586944d9ace03ca6a54b7f8173f6c0deb) --- 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 9776eaf2..cb5f0af1 100644 --- a/ssh/sesschan.c +++ b/ssh/sesschan.c @@ -425,7 +425,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 d1368903..c2380954 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 b3f6d802..807783b2 100644 --- a/windows/unicode.c +++ b/windows/unicode.c @@ -1071,9 +1071,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; } @@ -1097,9 +1099,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 c42c7a0b..fe6bdbf7 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, int *argc, char ***argv, * 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, int *argc, char ***argv, bool quote; /* Skip whitespace searching for start of argument. */ - while (*p && isspace(*p)) p++; + while (*p && isspace((unsigned char)*p)) p++; if (!*p) break; /* We have an argument; start it. */ @@ -206,7 +206,7 @@ void split_into_argv(char *cmdline, int *argc, char ***argv, /* 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 == '\\') { diff --git a/windows/window.c b/windows/window.c index e59bebce..50ed35ac 100644 --- a/windows/window.c +++ b/windows/window.c @@ -912,7 +912,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] == '&')) {