From 72bb9eb7b6decc34f343bdcbf0a8df0c73f9edd4 Mon Sep 17 00:00:00 2001 From: Olivier Certner Date: Mon, 7 Sep 2026 18:09:54 +0200 Subject: [PATCH] pwd(1): De-obfuscate, style(9) In getcwd_logical(), test for a '.' or '..' component in one of the most straightforward and intelligible ways possible. In particular, this removes a superfluous re-test of the the component's first character being '.' when the first one did not pass and, more importantly, prevents the second test from relying on a side-effect in the first. While here, for better clarity, replace the loop that searches for '/' with a simple call to strchrnul(). Add high-level comments about what is going on. While here, test explicitly that pointed 'char' values are not 0 ('\0') (style(9)). While here, separate the successive steps of getcwd_logical() with blank lines. No functional change (intended). Discussed with: emaste Fixes: 2df923c5d2d0 ("pwd: Clean up and adopt POSIX semantics") MFC after: 3 days Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D59709 --- bin/pwd/pwd.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/bin/pwd/pwd.c b/bin/pwd/pwd.c index 2bbf5457ec17..f619024fdcff 100644 --- a/bin/pwd/pwd.c +++ b/bin/pwd/pwd.c @@ -33,33 +33,40 @@ #include #include +#include #include #include #include #include +#include #include static char * getcwd_logical(void) { struct stat log, phy; - char *pwd, *p, *q; + char *pwd, *s, *e; /* $PWD is set and absolute */ if ((pwd = getenv("PWD")) == NULL || *pwd != '/') return (NULL); + /* $PWD does not contain /./ or /../ */ - for (p = pwd; *p; p = q) { - for (q = ++p; *q && *q != '/'; q++) - /* nothing */; - if ((*p == '.' && q == ++p) || - (*p == '.' && q == ++p)) + e = pwd; + do { + assert(*e == '/'); + s = e + 1; /* Beginning of next component (may point to NUL). */ + /* Search for the component's end. */ + e = strchrnul(s, '/'); + if (s[0] == '.' && (s + 1 == e || (s[1] == '.' && s + 2 == e))) return (NULL); - } + } while (*e != '\0'); + /* $PWD refers to the current directory */ if (stat(pwd, &log) != 0 || stat(".", &phy) != 0 || log.st_dev != phy.st_dev || log.st_ino != phy.st_ino) return (NULL); + return (pwd); }