commit bb07c6cc2ec6dc7f63f1fa4c921e5a947ac53e8b
parent 86c7e6038c1f96cc8920b0ea91981506fd85e98d
Author: Claudio Alessi <smoppy@gmail.com>
Date: Tue, 23 Aug 2022 23:41:37 +0200
Fix buffer management in cmdln_submit().
The old implementation was ignoring the fact that parsecmd() may cause sel to
be changed or even destroyed. Since there's no way to know if the current
buffer has been free()ed before accessing the associated data, we just copy the
data and pass it around to parsecmd() which cannot interfere with the buffer
anymore. Finally, we free() the data and we're done.
Diffstat:
M | circo.c | | | 43 | +++++++++++++++++++++++-------------------- |
1 file changed, 23 insertions(+), 20 deletions(-)
diff --git a/circo.c b/circo.c
@@ -175,7 +175,7 @@ void nickdel(Buffer *b, char *name);
Nick *nickget(Buffer *b, char *name);
void nicklist(Buffer *b, char *list);
void nickmv(char *old, char *new);
-void parsecmd(void);
+void parsecmd(char *cmd);
void parsesrv(void);
void privmsg(char *to, char *txt);
void quit(char *msg);
@@ -613,32 +613,35 @@ cmdln_cursor(const Arg *arg) {
void
cmdln_submit(const Arg *arg) {
- logw(sel->cmdbuf);
- logw("\n");
+ char *buf;
+
if(sel->cmdbuf[0] == '\0')
return;
- if(sel->cmdbuf[0] == '/') {
- if(sel->cmdlen == 1)
- return;
+ buf = ecalloc(1, sel->cmdlen);
+ memcpy(buf, sel->cmdbuf, sel->cmdlen);
+
+ logw(buf);
+ logw("\n");
+
+ sel->cmdlen = sel->cmdoff = sel->histlnoff = 0;
+ sel->cmdbuf[sel->cmdlen] = '\0';
+ sel->need_redraw |= REDRAW_CMDLN;
+
+ if(buf[0] == '/') {
histpush(sel->cmdbuf, sel->cmdlen);
- /* Note: network latency may delay drawings
- * causing visual glitches. */
- parsecmd();
+ /* Note: network latency may cause visual glitches. */
+ parsecmd(buf);
}
else {
histpush(sel->cmdbuf, sel->cmdlen);
- if(sel == status) {
+ if(sel == status)
bprintf(sel, "Cannot send text here.\n");
- return;
- }
else if(!srv)
bprintf(sel, "Not connected.\n");
else
privmsg(sel->name, sel->cmdbuf);
}
- sel->cmdlen = sel->cmdoff = sel->histlnoff = 0;
- sel->cmdbuf[sel->cmdlen] = '\0';
- sel->need_redraw |= REDRAW_CMDLN;
+ free(buf);
}
void
@@ -882,10 +885,10 @@ ecalloc(size_t nmemb, size_t size) {
void
focus(Buffer *b) {
- sel = b;
- sel->need_redraw |= REDRAW_ALL;
if(b->notify)
b->notify = 0;
+ sel = b;
+ sel->need_redraw |= REDRAW_ALL;
}
void
@@ -1161,11 +1164,11 @@ nickmv(char *old, char *new) {
}
void
-parsecmd(void) {
+parsecmd(char *cmd) {
char *p, *tp;
int i, len;
- p = &sel->cmdbuf[1];
+ p = &cmd[1]; /* skip the slash */
if(!*p)
return;
tp = p + 1;
@@ -1178,7 +1181,7 @@ parsecmd(void) {
}
}
if(srv)
- sout("%s %s", p, tp);
+ sout("%s %s", p, tp); /* raw */
else
bprintf(sel, "/%s: not connected.\n", p);
}