Skip to content

Commit

Permalink
MDEV-27089 Windows : incorrect handling of non-ASCIIs in get_tty_pass…
Browse files Browse the repository at this point in the history
…word

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.
  • Loading branch information
vaintroub authored and vuvova committed Dec 15, 2021
1 parent 6208228 commit 9e9b211
Showing 1 changed file with 39 additions and 16 deletions.
55 changes: 39 additions & 16 deletions mysys/get_password.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,35 +62,58 @@

char *get_tty_password(const char *opt_message)
{
char to[80];
char *pos=to,*end=to+sizeof(to)-1;
wchar_t wbuf[80];
char *to;
int to_len;
UINT cp;
wchar_t *pos=wbuf,*end=wbuf + array_elements(wbuf)-1;
DBUG_ENTER("get_tty_password");
_cputs(opt_message ? opt_message : "Enter password: ");
for (;;)
{
char tmp;
tmp=_getch();
if (tmp == '\b' || (int) tmp == 127)
int wc;
wc=_getwch();
if (wc == '\b' || wc == 127)
{
if (pos != to)
if (pos != wbuf)
{
_cputs("\b \b");
pos--;
continue;
_cputs("\b \b");
pos--;
continue;
}
}
if (tmp == '\n' || tmp == '\r' || tmp == 3)
if (wc == '\n' || wc == '\r' || wc == 3 || pos == end)
break;
if (iscntrl(tmp) || pos == end)
if (iswcntrl(wc))
continue;
_cputs("*");
*(pos++) = tmp;

/* Do not print '*' for half-unicode char(high surrogate)*/
if (wc < 0xD800 || wc > 0xDBFF)
{
_cputs("*");
}
*(pos++)= (wchar_t)wc;
}
while (pos != to && isspace(pos[-1]) == ' ')
pos--; /* Allow dummy space at end */
*pos=0;
_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
Expand Down

0 comments on commit 9e9b211

Please sign in to comment.