util1: fix clean_fname ".." collapse off-by-one

After the backward walk, s points at the first char of the prior component and
s[-1] is its leading '/', so the boundary test must read s[-1] (not *s) and t
must reset to s (not s+1).  The old off-by-one left CFN_COLLAPSE_DOT_DOT_DIRS
dead for all multi-component and absolute paths.  The peer-traversal guard
CFN_REFUSE_DOT_DOT_DIRS is checked first and is unaffected, so this is a
normalization-correctness fix, not a traversal hole.

Reported-by: Leonid Bugaev
This commit is contained in:
Andrew Tridgell committed 2026-07-20 14:05:32 +10:00
1 parent 07bf9af5b5
commit fbeb553b73
1 file changed
+8 -3
+8 -3
View File
@@ -1085,9 +1085,14 @@ int clean_fname(char *name, int flags)
while (s > limit && s[-1] != '/')
s--;
/* If found prior '/', or we reached the start, adjust t. */
if (s != t - 1 && (s <= name || *s == '/')) {
t = (s == name) ? name : s + 1;
/* If found prior '/', or we reached the start, adjust t.
* After the backward walk, s points at the first char of the
* prior component and s[-1] is its leading '/' -- so test
* s[-1] (not *s) and reset t to s (not s+1) to actually drop
* the component; the old off-by-one left CFN_COLLAPSE_DOT_DOT_DIRS
* dead for multi-component and absolute paths. */
if (s != t - 1 && (s <= name || s[-1] == '/')) {
t = (s == name) ? name : s;
f += 2;
continue;
}