Skip to content

Commit b89f22c

Browse files
committed
color: Fix an infinite loop colorizing some invalid paths
Previously, given $ touch file $ ln -s file/file notdir $ bfs notdir/file bfs would loop forever when printing the error message, since it expected stripping the trailing slash from "notdir/" to fix the ENOTDIR error, but the broken symlink still gave the same error. Fixes: b4c3201 ("color: Only highlight the trailing slash on ENOTDIR")
1 parent 295ae76 commit b89f22c

File tree

3 files changed

+13
-8
lines changed

3 files changed

+13
-8
lines changed

src/color.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -998,22 +998,25 @@ static ssize_t first_broken_offset(const char *path, const struct BFTW *ftwbuf,
998998
goto out;
999999
}
10001000

1001+
size_t len = dstrlen(at_path);
10011002
while (ret > 0) {
1003+
dstresize(&at_path, len);
10021004
if (xfaccessat(at_fd, at_path, F_OK) == 0) {
10031005
break;
10041006
}
10051007

1006-
size_t len = dstrlen(at_path);
1007-
while (ret && at_path[len - 1] == '/') {
1008-
--len, --ret;
1009-
}
1010-
if (errno != ENOTDIR) {
1011-
while (ret && at_path[len - 1] != '/') {
1008+
// Try without trailing slashes, to distinguish "notdir/" from "notdir"
1009+
if (at_path[len - 1] == '/') {
1010+
do {
10121011
--len, --ret;
1013-
}
1012+
} while (ret > 0 && at_path[len - 1] == '/');
1013+
continue;
10141014
}
10151015

1016-
dstresize(&at_path, len);
1016+
// Remove the last component and try again
1017+
do {
1018+
--len, --ret;
1019+
} while (ret > 0 && at_path[len - 1] != '/');
10171020
}
10181021

10191022
out_path:

tests/bfs/color_notdir_slash_error.out

Whitespace-only changes.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Regression test: infinite loop printing the error message for .../notdir/nowhere
2+
! bfs_diff -color links/notdir/nowhere

0 commit comments

Comments
 (0)