From a59a91c312edc87f13a2e1794b4d1d8ecaf3b7e5 Mon Sep 17 00:00:00 2001 From: NRK Date: Sat, 25 Feb 2023 13:18:29 +0600 Subject: [PATCH 1/4] handle tilde more correctly closes: https://github.com/jarun/nnn/issues/1596 --- src/nnn.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/nnn.c b/src/nnn.c index 0e41cd1f..fa61f376 100644 --- a/src/nnn.c +++ b/src/nnn.c @@ -1127,6 +1127,11 @@ static inline bool getutil(char *util) return spawn("which", util, NULL, NULL, F_NORMAL | F_NOTRACE) == 0; } +static inline bool tilde_is_home(const char *s) +{ + return s[0] == '~' && (s[1] == '\0' || s[1] == '/'); +} + /* * Updates out with "dir/name or "/name" * Returns the number of bytes copied including the terminating NULL byte @@ -1137,16 +1142,10 @@ static size_t mkpath(const char *dir, const char *name, char *out) { size_t len = 0; - if (name[0] == '~') { //NOLINT + if (tilde_is_home(name)) { //NOLINT len = xstrsncpy(out, home, PATH_MAX); if (!name[1]) return len; - - if (name[1] != '/') { - out[0] = '\0'; - return 0; - } - --len; ++name; } else if (name[0] != '/') { // NOLINT @@ -1213,7 +1212,7 @@ static char *abspath(const char *filepath, char *cwd, char *buf) if (!path) return NULL; - if (path[0] == '~') { + if (tilde_is_home(path)) { cwd = home; ++path; if (*path == '/') @@ -1333,7 +1332,7 @@ static void xterm_cfg(char *path) static void convert_tilde(const char *path, char *buf) { - if (path[0] == '~') { + if (tilde_is_home(path)) { ssize_t len = xstrlen(home); ssize_t loclen = xstrlen(path); @@ -2769,7 +2768,7 @@ static void write_lastdir(const char *curpath, const char *outfile) convert_tilde(outfile, g_buf); int fd = open(outfile - ? (outfile[0] == '~' ? g_buf : outfile) + ? (tilde_is_home(outfile) ? g_buf : outfile) : cfgpath, O_CREAT | O_WRONLY | O_TRUNC, S_IWUSR | S_IRUSR); if (fd != -1) { @@ -3838,7 +3837,7 @@ static char *get_kv_val(kv *kvarr, char *buf, int key, uchar_t max, uchar_t id) val = bmstr + kvarr[r].off; convert_tilde(val, g_buf); - return abspath(((val[0] == '~') ? g_buf : val), NULL, buf); + return abspath((tilde_is_home(val) ? g_buf : val), NULL, buf); } } @@ -8297,7 +8296,7 @@ static bool setup_config(void) /* Set up configuration file paths */ if (xdgcfg && xdgcfg[0]) { DPRINTF_S(xdgcfg); - if (xdgcfg[0] == '~') { + if (tilde_is_home(xdgcfg)) { r = xstrsncpy(g_buf, home, PATH_MAX); xstrsncpy(g_buf + r - 1, xdgcfg + 1, PATH_MAX); xdgcfg = g_buf; From 8dbd9da0cc37db3bdc001c616639c50cffdf955a Mon Sep 17 00:00:00 2001 From: NRK Date: Sat, 25 Feb 2023 13:27:48 +0600 Subject: [PATCH 2/4] convert_tilde: return whether the conversion was done or not --- src/nnn.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/nnn.c b/src/nnn.c index fa61f376..5284e9ef 100644 --- a/src/nnn.c +++ b/src/nnn.c @@ -1330,7 +1330,7 @@ static void xterm_cfg(char *path) } #endif -static void convert_tilde(const char *path, char *buf) +static bool convert_tilde(const char *path, char *buf) { if (tilde_is_home(path)) { ssize_t len = xstrlen(home); @@ -1338,7 +1338,9 @@ static void convert_tilde(const char *path, char *buf) xstrsncpy(buf, home, len + 1); xstrsncpy(buf + len, path + 1, loclen); + return true; } + return false; } static int create_tmp_file(void) @@ -2762,13 +2764,14 @@ static void archive_selection(const char *cmd, const char *archive) static void write_lastdir(const char *curpath, const char *outfile) { + bool tilde = false; if (!outfile) xstrsncpy(cfgpath + xstrlen(cfgpath), "/.lastd", 8); else - convert_tilde(outfile, g_buf); + tilde = convert_tilde(outfile, g_buf); int fd = open(outfile - ? (tilde_is_home(outfile) ? g_buf : outfile) + ? (tilde ? g_buf : outfile) : cfgpath, O_CREAT | O_WRONLY | O_TRUNC, S_IWUSR | S_IRUSR); if (fd != -1) { @@ -3836,8 +3839,8 @@ static char *get_kv_val(kv *kvarr, char *buf, int key, uchar_t max, uchar_t id) return pluginstr + kvarr[r].off; val = bmstr + kvarr[r].off; - convert_tilde(val, g_buf); - return abspath((tilde_is_home(val) ? g_buf : val), NULL, buf); + bool tilde = convert_tilde(val, g_buf); + return abspath((tilde ? g_buf : val), NULL, buf); } } From 3a30211e6cbe9df59692ee4f54a5f5b10fcf5e8d Mon Sep 17 00:00:00 2001 From: NRK Date: Sun, 26 Feb 2023 18:11:43 +0600 Subject: [PATCH 3/4] handle tilde more strictly in mkpath and abspath otherwise, if a file is named "~" it will get incorrectly expanded into $HOME and disaster can happen. --- src/nnn.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/nnn.c b/src/nnn.c index 5284e9ef..75ab5a06 100644 --- a/src/nnn.c +++ b/src/nnn.c @@ -1132,6 +1132,11 @@ static inline bool tilde_is_home(const char *s) return s[0] == '~' && (s[1] == '\0' || s[1] == '/'); } +static inline bool tilde_is_home_strict(const char *s) +{ + return s[0] == '~' && s[1] == '/'; +} + /* * Updates out with "dir/name or "/name" * Returns the number of bytes copied including the terminating NULL byte @@ -1142,10 +1147,8 @@ static size_t mkpath(const char *dir, const char *name, char *out) { size_t len = 0; - if (tilde_is_home(name)) { //NOLINT + if (tilde_is_home_strict(name)) { //NOLINT len = xstrsncpy(out, home, PATH_MAX); - if (!name[1]) - return len; --len; ++name; } else if (name[0] != '/') { // NOLINT @@ -1212,11 +1215,9 @@ static char *abspath(const char *filepath, char *cwd, char *buf) if (!path) return NULL; - if (tilde_is_home(path)) { + if (tilde_is_home_strict(path)) { cwd = home; - ++path; - if (*path == '/') - ++path; + path += 2; /* advance 2 bytes past the "~/" */ } else if ((path[0] != '/') && !cwd) { cwd = getcwd(NULL, 0); if (!cwd) From 003228afbae1586c3765824bcfe102f621be9fa8 Mon Sep 17 00:00:00 2001 From: NRK Date: Sun, 5 Mar 2023 18:43:08 +0600 Subject: [PATCH 4/4] add some critical comments --- src/nnn.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/nnn.c b/src/nnn.c index 75ab5a06..491749ab 100644 --- a/src/nnn.c +++ b/src/nnn.c @@ -1147,6 +1147,7 @@ static size_t mkpath(const char *dir, const char *name, char *out) { size_t len = 0; + /* same rational for being strict as abspath() */ if (tilde_is_home_strict(name)) { //NOLINT len = xstrsncpy(out, home, PATH_MAX); --len; @@ -1215,6 +1216,9 @@ static char *abspath(const char *filepath, char *cwd, char *buf) if (!path) return NULL; + /* when dealing with tilde, we need to be strict. + * otherwise a file named "~" can end up expanding to + * $HOME and causing disaster */ if (tilde_is_home_strict(path)) { cwd = home; path += 2; /* advance 2 bytes past the "~/" */