aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2023-04-13 12:59:31 +0300
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2023-04-13 12:59:31 +0300
commitba0875373d2250e3a6d63d5269ff1a4a89a280ed (patch)
tree46dbb4d2c3a66d650e52ab3d54affd78f556e3cb /src
parenta105a8a0875224ecf8fa9ec0f337d1a4f30de76c (diff)
downloadsciteco-ba0875373d2250e3a6d63d5269ff1a4a89a280ed.tar.gz
cmdline.c: fixed rubbing out words (^W) and possible chrashes
* This would sometimes rub out more than expected due to reading undefined memory. Actually even crashes were not impossible. * This is because SCI_GETWORDCHARS does not null-terminate the buffer it writes but this was assumed. In effect, we could easily read beyond the allocated memory in wchars if there doesn't happen to be a null-char following the buffer. * Consequently, null-chars in word chars were also not supported, although this would hardly trouble anybody. * Instead, we now store the word chars in a teco_string_t which supports non-null-terminated strings natively. Still we null-terminate the string to keep teco_string_t's promises about degrading to null-terminated char *. This is currently not necessary. * teco_is_wordchar() has been replaced by teco_string_contains().
Diffstat (limited to 'src')
-rw-r--r--src/cmdline.c27
1 files changed, 10 insertions, 17 deletions
diff --git a/src/cmdline.c b/src/cmdline.c
index 1cdaa40..58d48b4 100644
--- a/src/cmdline.c
+++ b/src/cmdline.c
@@ -421,16 +421,6 @@ teco_state_caseinsensitive_process_edit_cmd(teco_machine_t *ctx, teco_machine_t
return teco_state_process_edit_cmd(ctx, parent_ctx, key, error);
}
-/*
- * NOTE: The wordchars are null-terminated, so the null byte
- * is always considered to be a non-wordchar.
- */
-static inline gboolean
-teco_is_wordchar(const gchar *wordchars, gchar c)
-{
- return c != '\0' && strchr(wordchars, c);
-}
-
gboolean
teco_state_stringbuilding_start_process_edit_cmd(teco_machine_stringbuilding_t *ctx, teco_machine_t *parent_ctx,
gchar key, GError **error)
@@ -441,21 +431,24 @@ teco_state_stringbuilding_start_process_edit_cmd(teco_machine_stringbuilding_t *
case TECO_CTL_KEY('W'): { /* rubout/reinsert word */
teco_interface_popup_clear();
- g_autofree gchar *wchars = g_malloc(teco_interface_ssm(SCI_GETWORDCHARS, 0, 0));
- teco_interface_ssm(SCI_GETWORDCHARS, 0, (sptr_t)wchars);
+ g_auto(teco_string_t) wchars;
+ wchars.len = teco_interface_ssm(SCI_GETWORDCHARS, 0, 0);
+ wchars.data = g_malloc(wchars.len + 1);
+ teco_interface_ssm(SCI_GETWORDCHARS, 0, (sptr_t)wchars.data);
+ wchars.data[wchars.len] = '\0';
if (teco_cmdline.modifier_enabled) {
/* reinsert word chars */
while (ctx->parent.current == current &&
teco_cmdline.effective_len < teco_cmdline.str.len &&
- teco_is_wordchar(wchars, teco_cmdline.str.data[teco_cmdline.effective_len]))
+ teco_string_contains(&wchars, teco_cmdline.str.data[teco_cmdline.effective_len]))
if (!teco_cmdline_rubin(error))
return FALSE;
/* reinsert non-word chars */
while (ctx->parent.current == current &&
teco_cmdline.effective_len < teco_cmdline.str.len &&
- !teco_is_wordchar(wchars, teco_cmdline.str.data[teco_cmdline.effective_len]))
+ !teco_string_contains(&wchars, teco_cmdline.str.data[teco_cmdline.effective_len]))
if (!teco_cmdline_rubin(error))
return FALSE;
@@ -475,7 +468,7 @@ teco_state_stringbuilding_start_process_edit_cmd(teco_machine_stringbuilding_t *
* rubout the entire command.
*/
if (ctx->result && ctx->result->len > 0) {
- gboolean is_wordchar = teco_is_wordchar(wchars, teco_cmdline.str.data[teco_cmdline.effective_len-1]);
+ gboolean is_wordchar = teco_string_contains(&wchars, teco_cmdline.str.data[teco_cmdline.effective_len-1]);
teco_cmdline_rubout();
if (ctx->parent.current != current) {
/* rub out string building command */
@@ -490,13 +483,13 @@ teco_state_stringbuilding_start_process_edit_cmd(teco_machine_stringbuilding_t *
*/
if (!is_wordchar) {
while (ctx->result->len > 0 &&
- !teco_is_wordchar(wchars, teco_cmdline.str.data[teco_cmdline.effective_len-1]))
+ !teco_string_contains(&wchars, teco_cmdline.str.data[teco_cmdline.effective_len-1]))
teco_cmdline_rubout();
}
/* rubout word chars */
while (ctx->result->len > 0 &&
- teco_is_wordchar(wchars, teco_cmdline.str.data[teco_cmdline.effective_len-1]))
+ teco_string_contains(&wchars, teco_cmdline.str.data[teco_cmdline.effective_len-1]))
teco_cmdline_rubout();
return TRUE;