diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2023-04-13 12:59:31 +0300 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2023-04-13 12:59:31 +0300 |
commit | ba0875373d2250e3a6d63d5269ff1a4a89a280ed (patch) | |
tree | 46dbb4d2c3a66d650e52ab3d54affd78f556e3cb /src | |
parent | a105a8a0875224ecf8fa9ec0f337d1a4f30de76c (diff) | |
download | sciteco-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.c | 27 |
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; |