summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2024-04-24 11:07:33 -0400
committerTavian Barnes <tavianator@tavianator.com>2024-04-24 11:08:10 -0400
commitd597be5bc1ee0e76117037b7d9a52c52fd4531ad (patch)
treea8384fcb4cabde1da989b8c3e3b114b8114dfcc0
parent30e309de41aaca259c4d0a200daa42ba74cbc5a5 (diff)
downloadbfs-d597be5bc1ee0e76117037b7d9a52c52fd4531ad.tar.xz
eval: Plug memory leak if bfs_opendir() fails
-rw-r--r--src/eval.c40
-rw-r--r--tests/common/empty.out (renamed from tests/gnu/empty.out)0
-rw-r--r--tests/common/empty.sh (renamed from tests/gnu/empty.sh)0
-rw-r--r--tests/common/empty_error.out3
-rw-r--r--tests/common/empty_error.sh7
-rw-r--r--tests/common/empty_special.out (renamed from tests/gnu/empty_special.out)0
-rw-r--r--tests/common/empty_special.sh (renamed from tests/gnu/empty_special.sh)0
7 files changed, 32 insertions, 18 deletions
diff --git a/src/eval.c b/src/eval.c
index b103912..49028b7 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -445,38 +445,42 @@ bool eval_depth(const struct bfs_expr *expr, struct bfs_eval *state) {
* -empty test.
*/
bool eval_empty(const struct bfs_expr *expr, struct bfs_eval *state) {
- bool ret = false;
const struct BFTW *ftwbuf = state->ftwbuf;
+ const struct bfs_stat *statbuf;
+ struct bfs_dir *dir;
+
+ switch (ftwbuf->type) {
+ case BFS_REG:
+ statbuf = eval_stat(state);
+ return statbuf && statbuf->size == 0;
- if (ftwbuf->type == BFS_DIR) {
- struct bfs_dir *dir = bfs_allocdir();
+ case BFS_DIR:
+ dir = bfs_allocdir();
if (!dir) {
- eval_report_error(state);
- return ret;
+ goto error;
}
if (bfs_opendir(dir, ftwbuf->at_fd, ftwbuf->at_path, 0) != 0) {
- eval_report_error(state);
- return ret;
+ goto error;
}
int did_read = bfs_readdir(dir, NULL);
+ bfs_closedir(dir);
+
if (did_read < 0) {
- eval_report_error(state);
- } else {
- ret = !did_read;
+ goto error;
}
- bfs_closedir(dir);
free(dir);
- } else if (ftwbuf->type == BFS_REG) {
- const struct bfs_stat *statbuf = eval_stat(state);
- if (statbuf) {
- ret = statbuf->size == 0;
- }
- }
+ return did_read == 0;
+ error:
+ eval_report_error(state);
+ free(dir);
+ return false;
- return ret;
+ default:
+ return false;
+ }
}
/**
diff --git a/tests/gnu/empty.out b/tests/common/empty.out
index a0f4b76..a0f4b76 100644
--- a/tests/gnu/empty.out
+++ b/tests/common/empty.out
diff --git a/tests/gnu/empty.sh b/tests/common/empty.sh
index 95ee988..95ee988 100644
--- a/tests/gnu/empty.sh
+++ b/tests/common/empty.sh
diff --git a/tests/common/empty_error.out b/tests/common/empty_error.out
new file mode 100644
index 0000000..da45e23
--- /dev/null
+++ b/tests/common/empty_error.out
@@ -0,0 +1,3 @@
+./bar
+./baz
+./qux
diff --git a/tests/common/empty_error.sh b/tests/common/empty_error.sh
new file mode 100644
index 0000000..7c8049c
--- /dev/null
+++ b/tests/common/empty_error.sh
@@ -0,0 +1,7 @@
+cd "$TEST"
+
+"$XTOUCH" -p foo/ bar/ baz qux
+chmod -r foo baz
+defer chmod +r foo baz
+
+! bfs_diff . -empty
diff --git a/tests/gnu/empty_special.out b/tests/common/empty_special.out
index fa35478..fa35478 100644
--- a/tests/gnu/empty_special.out
+++ b/tests/common/empty_special.out
diff --git a/tests/gnu/empty_special.sh b/tests/common/empty_special.sh
index 31e9d2e..31e9d2e 100644
--- a/tests/gnu/empty_special.sh
+++ b/tests/common/empty_special.sh