From 11030b73509f698973f81c0cd7b8d6c83598d867 Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Sun, 20 Mar 2022 20:59:17 +0000 Subject: [PATCH] Delete whole utf8 character on backspace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ...rather than just the last byte of the password buffer. Demostrate the need for this by taking the following steps: - Apply the patch below (before this commit). - Set keyboard layout to one where utf8 characters longer than one byte can be obtained, for example åäö using Swedish layout (XKB_DEFAULT_LAYOUT=se). - Type "åäö" then press backspace and observe that it takes two backspaces to delete each character fully, and therefore six backspaces to fully clear the password buffer. diff --git a/password.c b/password.c index e1a1d9a..b640cd3 100644 --- a/password.c +++ b/password.c @@ -29,6 +29,7 @@ void clear_password_buffer(struct swaylock_password *pw) { static bool backspace(struct swaylock_password *pw) { if (pw->len != 0) { pw->buffer[--pw->len] = 0; + fprintf(stderr, "%s\n", pw->buffer); return true; } return false; --- include/unicode.h | 8 ++++++++ password.c | 3 ++- unicode.c | 13 +++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/include/unicode.h b/include/unicode.h index e2ee958..56a48f1 100644 --- a/include/unicode.h +++ b/include/unicode.h @@ -9,6 +9,14 @@ #define UTF8_INVALID 0x80 +/** + * Gets the size in bytes of the last utf8 character in a NULL terminated string + * This function does not validate that the buffer contains correct utf8 data; + * it merely looks for the first byte that correctly denotes the beginning of a + * utf8 character. + */ +int utf8_last_size(const char *str); + /** * Grabs the next UTF-8 character and advances the string pointer */ diff --git a/password.c b/password.c index e1a1d9a..6880ccb 100644 --- a/password.c +++ b/password.c @@ -28,7 +28,8 @@ void clear_password_buffer(struct swaylock_password *pw) { static bool backspace(struct swaylock_password *pw) { if (pw->len != 0) { - pw->buffer[--pw->len] = 0; + pw->len -= utf8_last_size(pw->buffer); + pw->buffer[pw->len] = 0; return true; } return false; diff --git a/unicode.c b/unicode.c index 3d81a34..6d115a9 100644 --- a/unicode.c +++ b/unicode.c @@ -1,7 +1,20 @@ #include #include +#include #include "unicode.h" +int utf8_last_size(const char *str) { + int len = 0; + char *pos = strchr(str, '\0'); + while (pos > str) { + --pos; ++len; + if ((*pos & 0xc0) != 0x80) { + return len; + } + } + return 0; +} + size_t utf8_chsize(uint32_t ch) { if (ch < 0x80) { return 1;