tCheck for XBufferOverflow when handling keys; misc fixes - ledit - Text editor… | |
git clone git://lumidify.org/ledit.git (fast, but not encrypted) | |
git clone https://lumidify.org/git/ledit.git (encrypted, but very slow) | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 53f769b1d999f6964bc2431b316cf07a3b8166ec | |
parent feafabfe8d714cc8d08d0000a91a7a6e8baf8492 | |
Author: lumidify <[email protected]> | |
Date: Thu, 7 Jul 2022 13:14:00 +0200 | |
Check for XBufferOverflow when handling keys; misc fixes | |
Diffstat: | |
M keys.c | 49 ++++++++++++++++++++++++++---… | |
M keys.h | 5 +++-- | |
M keys_basic.c | 6 +++--- | |
M keys_command.c | 8 +++++--- | |
M ledit.c | 2 +- | |
M leditrc.5 | 4 ++-- | |
M leditrc.example | 4 ++-- | |
7 files changed, 58 insertions(+), 20 deletions(-) | |
--- | |
diff --git a/keys.c b/keys.c | |
t@@ -19,16 +19,31 @@ | |
/* LockMask and Mod2Mask in particular are disabled (caps lock and numlock usu… | |
static unsigned int importantmod = ShiftMask | ControlMask | Mod1Mask | Mod3Ma… | |
+#define KEY_TEXT_INITIAL_SIZE 32 | |
+static char *key_text = NULL; | |
+static size_t key_text_alloc = 0; | |
+ | |
+void | |
+key_processing_cleanup(void) { | |
+ free(key_text); | |
+} | |
+ | |
int | |
match_key(unsigned int mask, unsigned int state) | |
{ | |
return mask == XK_ANY_MOD || mask == (state & importantmod); | |
} | |
+#ifdef X_HAVE_UTF8_STRING | |
+#define LOOKUP_STRING_FUNC Xutf8LookupString | |
+#else | |
+#define LOOKUP_STRING_FUNC XmbLookupString | |
+#endif | |
+ | |
void | |
preprocess_key( | |
- ledit_window *window, XEvent *event, KeySym *sym_ret, | |
- char *buf_ret, int buf_size, int *buf_len_ret) { | |
+ ledit_window *window, XKeyEvent *event, KeySym *sym_ret, | |
+ char **buf_ret, int *buf_len_ret) { | |
/* | |
* FIXME: I don't understand how key handling works with different key… | |
* If, for instance, you run "setxkbmap pk" and then type "Ctrl+c", the | |
t@@ -52,9 +67,29 @@ preprocess_key( | |
* keys don't use control in normal mode, and it just messes with all … | |
* keys that do use control because ledit does its own mapping. | |
*/ | |
- event->xkey.state &= ~ControlMask; | |
- /* FIXME: X_HAVE_UTF8_STRING See XmbLookupString(3) */ | |
- *buf_len_ret = Xutf8LookupString( | |
- window->xic, &event->xkey, buf_ret, buf_size, sym_ret, NULL | |
- ); | |
+ if (key_text_alloc == 0) { | |
+ key_text = ledit_malloc(KEY_TEXT_INITIAL_SIZE); | |
+ key_text_alloc = KEY_TEXT_INITIAL_SIZE; | |
+ } | |
+ event->state &= ~ControlMask; | |
+ | |
+ int len = 0; | |
+ Status status; | |
+ if (window->xic && event->type == KeyPress) { | |
+ len = LOOKUP_STRING_FUNC(window->xic, event, key_text, key_tex… | |
+ if (status == XBufferOverflow) { | |
+ key_text_alloc = ideal_array_size(key_text_alloc, len … | |
+ key_text = ledit_realloc(key_text, key_text_alloc); | |
+ len = LOOKUP_STRING_FUNC(window->xic, event, key_text,… | |
+ } | |
+ } else { | |
+ /* FIXME: anything equivalent to XBufferOverflow here? */ | |
+ len = XLookupString(event, key_text, key_text_alloc - 1, sym_r… | |
+ status = XLookupBoth; | |
+ } | |
+ *buf_len_ret = len >= (int)key_text_alloc ? (int)key_text_alloc - 1 : … | |
+ key_text[*buf_len_ret] = '\0'; | |
+ if (status != XLookupBoth && status != XLookupKeySym) | |
+ *sym_ret = NoSymbol; | |
+ *buf_ret = key_text; | |
} | |
diff --git a/keys.h b/keys.h | |
t@@ -15,9 +15,10 @@ int get_language_index(char *lang); | |
int match_key(unsigned int mask, unsigned int state); | |
/* preprocess key, i.e. get the KeySym and text corresponding to it */ | |
void preprocess_key( | |
- ledit_window *window, XEvent *event, KeySym *sym_ret, | |
- char *buf_ret, int buf_size, int *buf_len_ret | |
+ ledit_window *window, XKeyEvent *event, KeySym *sym_ret, | |
+ char **buf_ret, int *buf_len_ret | |
); | |
+void key_processing_cleanup(void); | |
/* FIXME: documentation */ | |
#define GEN_CB_MAP_HELPERS(name, typename, cmp_entry) \ | |
diff --git a/keys_basic.c b/keys_basic.c | |
t@@ -2622,12 +2622,12 @@ repeat_command(ledit_view *view, char *text, size_t le… | |
struct action | |
basic_key_handler(ledit_view *view, XEvent *event, int lang_index) { | |
- char buf[64]; | |
- KeySym sym; | |
+ char *buf = NULL; | |
+ KeySym sym = NoSymbol; | |
int n; | |
unsigned int key_state = event->xkey.state; | |
- preprocess_key(view->window, event, &sym, buf, sizeof(buf), &n); | |
+ preprocess_key(view->window, &event->xkey, &sym, &buf, &n); | |
struct repetition_stack_elem *re = push_repetition_stack(); | |
re->key_text = ledit_strndup(buf, (size_t)n); | |
diff --git a/keys_command.c b/keys_command.c | |
t@@ -214,6 +214,8 @@ static int parse_range( | |
); | |
static int handle_cmd(ledit_view *view, char *cmd, size_t len, size_t lang_ind… | |
+/* FIXME: USE LEN EVERYWHERE INSTEAD OF RELYING ON cmd BEING NUL-TERMINATED */ | |
+/* FIXME: return error so write_quit knows when to quit */ | |
static int | |
handle_write(ledit_view *view, char *cmd, size_t l1, size_t l2) { | |
(void)l1; | |
t@@ -946,13 +948,13 @@ edit_discard(ledit_view *view, char *key_text, size_t le… | |
struct action | |
command_key_handler(ledit_view *view, XEvent *event, int lang_index) { | |
- char buf[64]; | |
- KeySym sym; | |
+ char *buf = NULL; | |
+ KeySym sym = NoSymbol; | |
int n; | |
command_key_array *cur_keys = config_get_command_keys(lang_index); | |
size_t num_keys = cur_keys->num_keys; | |
unsigned int key_state = event->xkey.state; | |
- preprocess_key(view->window, event, &sym, buf, sizeof(buf), &n); | |
+ preprocess_key(view->window, &event->xkey, &sym, &buf, &n); | |
int grabkey = 1, found = 0; | |
command_key_cb_flags flags = KEY_FLAG_NONE; | |
for (size_t i = 0; i < num_keys; i++) { | |
diff --git a/ledit.c b/ledit.c | |
t@@ -114,7 +114,6 @@ mainloop(void) { | |
change_kbd = 1; | |
continue; | |
} | |
- /* FIXME: why None? */ | |
if (XFilterEvent(&event, None)) | |
continue; | |
ledit_view *view = NULL; | |
t@@ -450,6 +449,7 @@ ledit_cleanup(void) { | |
search_cleanup(); | |
basic_key_cleanup(); | |
command_key_cleanup(); | |
+ key_processing_cleanup(); | |
if (buffer) | |
buffer_destroy(buffer); | |
config_cleanup(&common); | |
diff --git a/leditrc.5 b/leditrc.5 | |
t@@ -619,12 +619,12 @@ Note that this command works with soft lines, regardless… | |
.It Ar scroll-with-cursor-down Oo normal, insert Oc Oo num Oc | |
Move | |
.Ar num | |
-lines down, attemting to leave the cursor in its current line and character po… | |
+lines down, attempting to leave the cursor in its current line and character p… | |
Note that this command works with soft lines, regardless of the current mode. | |
.It Ar scroll-with-cursor-up Oo normal, insert Oc Oo num Oc | |
Move | |
.Ar num | |
-lines up, attemting to leave the cursor in its current line and character posi… | |
+lines up, attempting to leave the cursor in its current line and character pos… | |
Note that this command works with soft lines, regardless of the current mode. | |
.It Ar search-next Op normal, insert | |
Move to the next search result. | |
diff --git a/leditrc.example b/leditrc.example | |
t@@ -221,7 +221,7 @@ language-mapping = { | |
map "^" "^" | |
} | |
command-mapping = { | |
- map "वग" "wq" | |
+ map "व" "wq" | |
map "व" "w" | |
map "" "q" | |
map "ड" "v" | |
t@@ -293,7 +293,7 @@ language-mapping = { | |
map "^" "^" | |
} | |
command-mapping = { | |
- map "وگ" "wq" | |
+ map "وق" "wq" | |
map "و" "w" | |
map "ق" "q" | |
map "ط" "v" |