shell_escape: return strlen or -1 on failure

also check for `outlen < 3` since the function
unconditionally writes at least 3 bytes.
This commit is contained in:
NRK 2025-01-05 19:40:33 +00:00
parent 1cf9654368
commit 94bac4ef98

View file

@ -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 */ /* 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; size_t n = xstrlen(s), w = 0;
if (s == output) { if (s == output || outlen < 3) {
DPRINTF_S("s == output"); errno = EINVAL;
return FALSE; return -1;
} }
output[w++] = '\''; /* begin single quote */ output[w++] = '\''; /* begin single quote */
for (size_t r = 0; r < n; ++r) { for (size_t r = 0; r < n; ++r) {
/* potentially too big: 4 for the single quote case, 2 from /* potentially too big: 4 for the single quote case, 2 from
* outside the loop */ * outside the loop */
if (w + 6 >= outlen) if (w + 6 >= outlen) {
return FALSE; errno = ENAMETOOLONG;
return -1;
}
switch (s[r]) { switch (s[r]) {
/* the only thing that has special meaning inside single /* 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++] = '\''; /* end single quote */
output[w++] = '\0'; /* nul terminator */ output[w] = '\0'; /* nul terminator */
return TRUE; return w;
} }
static bool set_tilde_in_path(char *path) 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) static void write_lastdir(const char *curpath, const char *outfile)
{ {
bool tilde = false; bool tilde = false, ok = false;
if (!outfile) if (!outfile)
xstrsncpy(cfgpath + xstrlen(cfgpath), "/.lastd", 8); xstrsncpy(cfgpath + xstrlen(cfgpath), "/.lastd", 8);
else else
@ -2850,15 +2852,14 @@ static void write_lastdir(const char *curpath, const char *outfile)
int fd = open(outfile int fd = open(outfile
? (tilde ? g_buf : outfile) ? (tilde ? g_buf : outfile)
: cfgpath, O_CREAT | O_WRONLY | O_TRUNC, S_IWUSR | S_IRUSR); : cfgpath, O_CREAT | O_WRONLY | O_TRUNC, S_IWUSR | S_IRUSR);
if (fd >= 0) {
if (fd != -1 && shell_escape(g_buf, sizeof(g_buf), curpath)) { memcpy(g_buf, "cd ", 3); // NOLINT
if (write(fd, "cd ", 3) == 3) { ssize_t l = shell_escape(g_buf + 3, sizeof(g_buf) - 3, curpath);
if (write(fd, g_buf, strlen(g_buf)) != (ssize_t)strlen(g_buf)) { ok = l >= 0 && write(fd, g_buf, l + 3) == l + 3;
DPRINTF_S("write failed!");
}
}
close(fd); close(fd);
} }
if (!ok)
errexit();
} }
/* /*