diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2024-04-24 11:07:33 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2024-04-24 11:08:10 -0400 |
commit | d597be5bc1ee0e76117037b7d9a52c52fd4531ad (patch) | |
tree | a8384fcb4cabde1da989b8c3e3b114b8114dfcc0 | |
parent | 30e309de41aaca259c4d0a200daa42ba74cbc5a5 (diff) | |
download | bfs-d597be5bc1ee0e76117037b7d9a52c52fd4531ad.tar.xz |
eval: Plug memory leak if bfs_opendir() fails
-rw-r--r-- | src/eval.c | 40 | ||||
-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.out | 3 | ||||
-rw-r--r-- | tests/common/empty_error.sh | 7 | ||||
-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
@@ -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 |