tex: prevent buffer overflow after expanding % and # - neatvi - [fork] simple vi-type editor with UTF-8 support (HTM) git clone git://src.adamsgaard.dk/neatvi (DIR) Log (DIR) Files (DIR) Refs (DIR) README --- (DIR) commit 86745f7e230cc2ceb023cab75ff3105d713bb6d6 (DIR) parent 3932f52736caa572c60ab3dae7b5302ce361146a (HTM) Author: Ali Gholami Rudi <ali@rudi.ir> Date: Fri, 24 Sep 2021 12:27:39 +0330 ex: prevent buffer overflow after expanding % and # Diffstat: M ex.c | 59 +++++++++++++++++++------------ 1 file changed, 37 insertions(+), 22 deletions(-) --- (DIR) diff --git a/ex.c b/ex.c t@@ -149,7 +149,7 @@ static char *ex_cmd(char *src, char *cmd) src = ex_loc(src, cmd); while (*src == ' ' || *src == '\t') src++; - while (isalpha((unsigned char) *src)) + while (isalpha((unsigned char) *src) && cmd < cmd0 + 16) if ((*cmd++ = *src++) == 'k' && cmd == cmd0 + 1) break; if (*src == '!' || *src == '=') t@@ -159,35 +159,35 @@ static char *ex_cmd(char *src, char *cmd) } /* read ex file argument */ -static char *ex_filearg(char *src, char *dst, int spaceallowed) +static char *ex_filearg(char *src, int spaceallowed) { + struct sbuf *sb = sbuf_make(); while (*src && *src != '\n' && (spaceallowed || (*src != ' ' && *src != '\t'))) { if (*src == '%') { if (!bufs[0].path || !bufs[0].path[0]) { ex_show("\"%\" is unset\n"); + sbuf_free(sb); return NULL; } - strcpy(dst, bufs[0].path); - dst = strchr(dst, '\0'); + sbuf_str(sb, bufs[0].path); src++; continue; } if (*src == '#') { if (!bufs[1].path || !bufs[1].path[0]) { ex_show("\"#\" is unset\n"); + sbuf_free(sb); return NULL; } - strcpy(dst, bufs[1].path); - dst = strchr(dst, '\0'); + sbuf_str(sb, bufs[1].path); src++; continue; } if (*src == '\\' && src[1]) src++; - *dst++ = *src++; + sbuf_chr(sb, *src++); } - *dst = '\0'; - return src; + return sbuf_done(sb); } /* the previous search keyword */ t@@ -372,17 +372,18 @@ static int ec_edit(char *ec) char msg[128]; char cmd[EXLEN]; char arg[EXLEN]; - char path[EXLEN]; + char *path; int fd; ex_cmd(ec, cmd); ex_arg(ec, arg); - if (!ex_filearg(arg, path, 0)) - return 1; if (!strchr(cmd, '!')) if (xb && ex_modifiedbuffer("buffer modified\n")) return 1; + if (!(path = ex_filearg(arg, 0))) + return 1; if (path[0] && bufs_find(path) >= 0) { bufs_switch(bufs_find(path)); + free(path); return 0; } if (path[0] || !bufs[0].path) t@@ -403,6 +404,7 @@ static int ec_edit(char *ec) xrow = MAX(0, MIN(xrow, lbuf_len(xb) - 1)); xoff = 0; xtop = MAX(0, MIN(xtop, lbuf_len(xb) - 1)); + free(path); return 0; } t@@ -421,12 +423,13 @@ static int ec_read(char *ec) return 1; if (arg[0] == '!') { int pos = MIN(xrow + 1, lbuf_len(xb)); - char ecmd[EXLEN * 2]; - if (!ex_filearg(arg, ecmd, 1)) + char *ecmd = ex_filearg(arg, 1); + if (!ecmd) return 1; obuf = cmd_pipe(ecmd + 1, NULL, 0, 1); if (obuf) lbuf_edit(xb, obuf, pos, pos); + free(ecmd); free(obuf); } else { int fd = open(path, O_RDONLY); t@@ -469,12 +472,13 @@ static int ec_write(char *ec) end = lbuf_len(xb); } if (arg[0] == '!') { - char ecmd[EXLEN * 2]; - if (!ex_filearg(arg, ecmd, 1)) + char *ecmd = ex_filearg(arg, 1); + if (!ecmd) return 1; ibuf = lbuf_cp(xb, beg, end); ex_print(NULL); cmd_pipe(ecmd + 1, ibuf, 1, 0); + free(ecmd); free(ibuf); } else { int fd; t@@ -751,25 +755,31 @@ static int ec_exec(char *ec) { char loc[EXLEN]; char arg[EXLEN]; - char ecmd[EXLEN * 2]; int beg, end; char *text; char *rep; + char *ecmd; ex_modifiedbuffer(NULL); ex_loc(ec, loc); ex_arg(ec, arg); - if (!ex_filearg(arg, ecmd, 1)) + if (!(ecmd = ex_filearg(arg, 1))) return 1; if (!loc[0]) { + int ret; ex_print(NULL); - return cmd_exec(ecmd); + ret = cmd_exec(ecmd); + free(ecmd); + return ret; } - if (ex_region(loc, &beg, &end)) + if (ex_region(loc, &beg, &end)) { + free(ecmd); return 1; + } text = lbuf_cp(xb, beg, end); rep = cmd_pipe(ecmd, text, 1, 1); if (rep) lbuf_edit(xb, rep, beg, end); + free(ecmd); free(text); free(rep); return 0; t@@ -779,12 +789,13 @@ static int ec_make(char *ec) { char arg[EXLEN]; char make[EXLEN]; - char target[EXLEN * 2]; + char *target; ex_modifiedbuffer(NULL); ex_arg(ec, arg); - if (!ex_filearg(arg, target, 0)) + if (!(target = ex_filearg(arg, 0))) return 1; sprintf(make, "make %s", target); + free(target); ex_print(NULL); if (cmd_exec(make)) return 1; t@@ -1049,6 +1060,10 @@ static int ex_exec(char *ln) int ret = 0; while (*ln) { ex_cmd(ln, cmd); + if (strlen(ln) >= EXLEN) { + ex_show("command too long"); + return 1; + } ln = ex_line(ln, ec); if ((idx = ex_idx(cmd)) >= 0) ret = excmds[idx].ec(ec);