Module Name: src Committed By: christos Date: Fri Sep 3 12:20:38 UTC 2021
Modified Files: src/lib/libedit: readline.c Log Message: Try to refactor this in order to correct some of the memory issues reported by Christian Holler. To generate a diff of this commit: cvs rdiff -u -r1.164 -r1.165 src/lib/libedit/readline.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libedit/readline.c diff -u src/lib/libedit/readline.c:1.164 src/lib/libedit/readline.c:1.165 --- src/lib/libedit/readline.c:1.164 Sat Aug 21 08:38:56 2021 +++ src/lib/libedit/readline.c Fri Sep 3 08:20:38 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: readline.c,v 1.164 2021/08/21 12:38:56 christos Exp $ */ +/* $NetBSD: readline.c,v 1.165 2021/09/03 12:20:38 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: readline.c,v 1.164 2021/08/21 12:38:56 christos Exp $"); +__RCSID("$NetBSD: readline.c,v 1.165 2021/09/03 12:20:38 christos Exp $"); #endif /* not lint && not SCCSID */ #include <sys/types.h> @@ -460,14 +460,10 @@ readline(const char *p) ret = el_gets(e, &count); if (ret && count > 0) { - int lastidx; - buf = strdup(ret); if (buf == NULL) goto out; - lastidx = count - 1; - if (buf[lastidx] == '\n') - buf[lastidx] = '\0'; + buf[strcspn(buf, "\n")] = '\0'; } else buf = NULL; @@ -665,6 +661,120 @@ get_history_event(const char *cmd, int * return rptr; } +static int +getfrom(const char **cmdp, char **fromp, const char *search, int delim) +{ + size_t size = 16; + size_t len = 0; + const char *cmd = *cmdp; + char *what = el_realloc(*fromp, size * sizeof(*what)); + if (what == NULL){ + el_free(*fromp); + *fromp = NULL; + return 0; + } + for (; *cmd && *cmd != delim; cmd++) { + if (*cmd == '\\' && cmd[1] == delim) + cmd++; + if (len >= size) { + char *nwhat; + nwhat = el_realloc(what, (size <<= 1) * sizeof(*nwhat)); + if (nwhat == NULL) { + el_free(what); + el_free(*fromp); + *cmdp = cmd; + *fromp = NULL; + return 0; + } + what = nwhat; + } + what[len++] = *cmd; + } + what[len] = '\0'; + *fromp = what; + *cmdp = cmd; + if (*what == '\0') { + el_free(what); + if (search) { + *fromp = strdup(search); + if (*fromp == NULL) { + return 0; + } + } else { + *fromp = NULL; + return -1; + } + } + if (!*cmd) { + el_free(what); + return -1; + } + + cmd++; /* shift after delim */ + *cmdp = cmd; + + if (!*cmd) { + el_free(what); + return -1; + } + return 1; +} + +static int +getto(const char **cmdp, char **top, const char *from, int delim) +{ + size_t size = 16; + size_t len = 0; + size_t from_len = strlen(from); + const char *cmd = *cmdp; + char *with = el_realloc(*top, size * sizeof(*with)); + if (with == NULL) + goto out; + + for (; *cmd && *cmd != delim; cmd++) { + if (len + from_len + 1 >= size) { + char *nwith; + size += from_len + 1; + nwith = el_realloc(with, size * sizeof(*nwith)); + if (nwith == NULL) + goto out; + with = nwith; + } + if (*cmd == '&') { + /* safe */ + strcpy(&with[len], from); + len += from_len; + continue; + } + if (*cmd == '\\' && (*(cmd + 1) == delim || *(cmd + 1) == '&')) + cmd++; + with[len++] = *cmd; + } + if (!*cmd) + goto out; + with[len] = '\0'; + *top = with; + *cmdp = cmd; + return 1; +out: + el_free(with); + el_free(*top); + *top = NULL; + *cmdp = cmd; + return -1; +} + +static void +replace(char **tmp, int c) +{ + char *aptr; + if ((aptr = strrchr(*tmp, c)) == NULL) + return; + aptr = strdup(aptr + 1); // XXX: check + el_free(*tmp); + *tmp = aptr; +} + /* * the real function doing history expansion - takes as argument command * to do and data upon which the command should be executed @@ -679,11 +789,11 @@ static int _history_expand_command(const char *command, size_t offs, size_t cmdlen, char **result) { - char *tmp, *search = NULL, *aptr; + char *tmp, *search = NULL, *aptr, delim; const char *ptr, *cmd; static char *from = NULL, *to = NULL; int start, end, idx, has_mods = 0; - int p_on = 0, g_on = 0; + int p_on = 0, g_on = 0, ev; *result = NULL; aptr = NULL; @@ -747,7 +857,7 @@ _history_expand_command(const char *comm start = -1, cmd++; else if (*cmd == '*') start = 1, cmd++; - else if (*cmd == '-' || isdigit((unsigned char) *cmd)) { + else if (*cmd == '-' || isdigit((unsigned char) *cmd)) { start = 0; while (*cmd && '0' <= *cmd && *cmd <= '9') start = start * 10 + *cmd++ - '0'; @@ -790,132 +900,54 @@ _history_expand_command(const char *comm } for (; *cmd; cmd++) { - if (*cmd == ':') + switch (*cmd) { + case ':': continue; - else if (*cmd == 'h') { /* remove trailing path */ + case 'h': /* remove trailing path */ if ((aptr = strrchr(tmp, '/')) != NULL) *aptr = '\0'; - } else if (*cmd == 't') { /* remove leading path */ - if ((aptr = strrchr(tmp, '/')) != NULL) { - aptr = strdup(aptr + 1); - el_free(tmp); - tmp = aptr; - } - } else if (*cmd == 'r') { /* remove trailing suffix */ + continue; + case 't': /* remove leading path */ + replace(&tmp, '/'); + continue; + case 'r': /* remove trailing suffix */ if ((aptr = strrchr(tmp, '.')) != NULL) *aptr = '\0'; - } else if (*cmd == 'e') { /* remove all but suffix */ - if ((aptr = strrchr(tmp, '.')) != NULL) { - aptr = strdup(aptr); - el_free(tmp); - tmp = aptr; - } - } else if (*cmd == 'p') /* print only */ + continue; + case 'e': /* remove all but suffix */ + replace(&tmp, '.'); + continue; + case 'p': /* print only */ p_on = 1; - else if (*cmd == 'g') + continue; + case 'g': g_on = 2; - else if (*cmd == 's' || *cmd == '&') { - char *what, *with, delim; - size_t len, from_len; - size_t size; - - if (*cmd == '&' && (from == NULL || to == NULL)) + continue; + case '&': + if (from == NULL || to == NULL) continue; - else if (*cmd == 's') { - delim = *(++cmd), cmd++; - size = 16; - what = el_realloc(from, size * sizeof(*what)); - if (what == NULL) { - el_free(from); - el_free(tmp); - return 0; - } - len = 0; - for (; *cmd && *cmd != delim; cmd++) { - if (*cmd == '\\' && cmd[1] == delim) - cmd++; - if (len >= size) { - char *nwhat; - nwhat = el_realloc(what, - (size <<= 1) * - sizeof(*nwhat)); - if (nwhat == NULL) { - el_free(what); - el_free(tmp); - return 0; - } - what = nwhat; - } - what[len++] = *cmd; - } - what[len] = '\0'; - from = what; - if (*what == '\0') { - el_free(what); - if (search) { - from = strdup(search); - if (from == NULL) { - el_free(tmp); - return 0; - } - } else { - from = NULL; - el_free(tmp); - return -1; - } - } - cmd++; /* shift after delim */ - if (!*cmd) - continue; - - size = 16; - with = el_realloc(to, size * sizeof(*with)); - if (with == NULL) { - el_free(to); - el_free(tmp); - return -1; - } - len = 0; - from_len = strlen(from); - for (; *cmd && *cmd != delim; cmd++) { - if (len + from_len + 1 >= size) { - char *nwith; - size += from_len + 1; - nwith = el_realloc(with, - size * sizeof(*nwith)); - if (nwith == NULL) { - el_free(with); - el_free(tmp); - return -1; - } - with = nwith; - } - if (*cmd == '&') { - /* safe */ - (void)strcpy(&with[len], from); - len += from_len; - continue; - } - if (*cmd == '\\' - && (*(cmd + 1) == delim - || *(cmd + 1) == '&')) - cmd++; - with[len++] = *cmd; - } - with[len] = '\0'; - to = with; + /*FALLTHROUGH*/ + case 's': + delim = *(++cmd), cmd++; /* XXX: check */ + if ((ev = getfrom(&cmd, &from, search, delim)) != 1) { + el_free(tmp); + return ev; + } + if ((ev = getto(&cmd, &to, from, delim)) != 1) { + el_free(tmp); + return ev; } - aptr = _rl_compat_sub(tmp, from, to, g_on); if (aptr) { el_free(tmp); tmp = aptr; } g_on = 0; + continue; } } *result = tmp; - return p_on? 2:1; + return p_on ? 2 : 1; }