diff --git a/src/nnn.c b/src/nnn.c index e19b7afe..936b19f9 100644 --- a/src/nnn.c +++ b/src/nnn.c @@ -1335,21 +1335,23 @@ static char *bmtarget(const char *filepath, char *cwd, char *buf) } /* wraps the argument in single quotes so it can be safely fed to shell */ -static bool shell_escape(char *output, size_t outlen, const char *s) +static ssize_t shell_escape(char *output, size_t outlen, const char *s) { size_t n = xstrlen(s), w = 0; - if (s == output) { - DPRINTF_S("s == output"); - return FALSE; + if (s == output || outlen < 3) { + errno = EINVAL; + return -1; } output[w++] = '\''; /* begin single quote */ for (size_t r = 0; r < n; ++r) { /* potentially too big: 4 for the single quote case, 2 from * outside the loop */ - if (w + 6 >= outlen) - return FALSE; + if (w + 6 >= outlen) { + errno = ENAMETOOLONG; + return -1; + } switch (s[r]) { /* the only thing that has special meaning inside single @@ -1366,8 +1368,8 @@ static bool shell_escape(char *output, size_t outlen, const char *s) } } output[w++] = '\''; /* end single quote */ - output[w++] = '\0'; /* nul terminator */ - return TRUE; + output[w] = '\0'; /* nul terminator */ + return w; } static bool set_tilde_in_path(char *path) @@ -2841,7 +2843,7 @@ static void archive_selection(const char *cmd, const char *archive) static void write_lastdir(const char *curpath, const char *outfile) { - bool tilde = false; + bool tilde = false, ok = false; if (!outfile) xstrsncpy(cfgpath + xstrlen(cfgpath), "/.lastd", 8); else @@ -2850,15 +2852,14 @@ static void write_lastdir(const char *curpath, const char *outfile) int fd = open(outfile ? (tilde ? g_buf : outfile) : cfgpath, O_CREAT | O_WRONLY | O_TRUNC, S_IWUSR | S_IRUSR); - - if (fd != -1 && shell_escape(g_buf, sizeof(g_buf), curpath)) { - if (write(fd, "cd ", 3) == 3) { - if (write(fd, g_buf, strlen(g_buf)) != (ssize_t)strlen(g_buf)) { - DPRINTF_S("write failed!"); - } - } + if (fd >= 0) { + memcpy(g_buf, "cd ", 3); // NOLINT + ssize_t l = shell_escape(g_buf + 3, sizeof(g_buf) - 3, curpath); + ok = l >= 0 && write(fd, g_buf, l + 3) == l + 3; close(fd); } + if (!ok) + errexit(); } /*