Commit 9e9b211f authored by Vladislav Vaintroub's avatar Vladislav Vaintroub Committed by Sergei Golubchik

MDEV-27089 Windows : incorrect handling of non-ASCIIs in get_tty_password

Prior to patch, get_password would echo multple mask characters '*', for
a single multibyte input character.

Fixed the behavior by using "wide" version of getch, _getwch.
Also take care of possible characters outside of BMP (i.e we do not print
'*' for high surrogates).

The function will now internally construct the "wide" password string,
and conver to the console codepage. Some characters could still be lost
in that conversion, unless the codepage is utf8, but this is not any new
bug.
parent 6208228b
...@@ -62,35 +62,58 @@ ...@@ -62,35 +62,58 @@
char *get_tty_password(const char *opt_message) char *get_tty_password(const char *opt_message)
{ {
char to[80]; wchar_t wbuf[80];
char *pos=to,*end=to+sizeof(to)-1; char *to;
int to_len;
UINT cp;
wchar_t *pos=wbuf,*end=wbuf + array_elements(wbuf)-1;
DBUG_ENTER("get_tty_password"); DBUG_ENTER("get_tty_password");
_cputs(opt_message ? opt_message : "Enter password: "); _cputs(opt_message ? opt_message : "Enter password: ");
for (;;) for (;;)
{ {
char tmp; int wc;
tmp=_getch(); wc=_getwch();
if (tmp == '\b' || (int) tmp == 127) if (wc == '\b' || wc == 127)
{ {
if (pos != to) if (pos != wbuf)
{ {
_cputs("\b \b"); _cputs("\b \b");
pos--; pos--;
continue; continue;
} }
} }
if (tmp == '\n' || tmp == '\r' || tmp == 3) if (wc == '\n' || wc == '\r' || wc == 3 || pos == end)
break; break;
if (iscntrl(tmp) || pos == end) if (iswcntrl(wc))
continue; continue;
/* Do not print '*' for half-unicode char(high surrogate)*/
if (wc < 0xD800 || wc > 0xDBFF)
{
_cputs("*"); _cputs("*");
*(pos++) = tmp;
} }
while (pos != to && isspace(pos[-1]) == ' ') *(pos++)= (wchar_t)wc;
pos--; /* Allow dummy space at end */ }
*pos=0; *pos=0;
_cputs("\n"); _cputs("\n");
DBUG_RETURN(my_strdup(PSI_INSTRUMENT_ME, to,MYF(MY_FAE)));
/*
Allocate output string, and convert UTF16 password to output codepage.
*/
cp= GetConsoleCP();
if (!(to_len= WideCharToMultiByte(cp, 0, wbuf, -1, NULL, 0, NULL, NULL)))
DBUG_RETURN(NULL);
if (!(to= my_malloc(PSI_INSTRUMENT_ME, to_len, MYF(MY_FAE))))
DBUG_RETURN(NULL);
if (!WideCharToMultiByte(cp, 0, wbuf, -1, to, to_len, NULL, NULL))
{
my_free(to);
DBUG_RETURN(NULL);
}
DBUG_RETURN(to);
} }
#else #else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment