aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2015-09-12 15:46:46 -0500
committerRob Landley <rob@landley.net>2015-09-12 15:46:46 -0500
commitedae0b07db841e3bf8449d591971f04c9957ecbc (patch)
tree186c7e6504e3217ba630714b4577c23f4ac3ec94
parente5354ca12a232b3f97726214254a868771cb70d1 (diff)
downloadtoybox-edae0b07db841e3bf8449d591971f04c9957ecbc.tar.gz
Fix a find segfault.
Elliott Hughes found a bug https://android-review.googlesource.com/#/c/170020/ and Daniel K. Levy worked out the problem: the user/group/newer arguments to find weren't consuming their arguments when not checking the results of their comparison (because an earlier test had already caused their parenthetical group to fail). This confused the argument parsing logic and could lead to segfaults. I applied a different fix that reorganized the existing tests instead of adding a new test. (Looks like a big commit but it's mostly whitespace due to extra curly brackets changing indendentation levels.)
-rwxr-xr-xtests/find.test4
-rw-r--r--toys/posix/find.c36
2 files changed, 24 insertions, 16 deletions
diff --git a/tests/find.test b/tests/find.test
index cbbce5fd..65bbb501 100755
--- a/tests/find.test
+++ b/tests/find.test
@@ -39,4 +39,8 @@ testing "find -type f -a -print" \
testing "find -print -o -print" \
"find dir -type f -a \( -print -o -print \)" "dir/file\n" "" ""
+# these were erroring or segfaulting:
+# find -type f -user nobody -exec : \;
+# find -type f -user nobody -exec : -exec : \;
+
rm -rf dir
diff --git a/toys/posix/find.c b/toys/posix/find.c
index 10585294..aca19845 100644
--- a/toys/posix/find.c
+++ b/toys/posix/find.c
@@ -336,26 +336,30 @@ static int do_find(struct dirtree *new)
} u;
} *udl;
- if (!new && ss[1]) {
- udl = xmalloc(sizeof(*udl));
- dlist_add_nomalloc(&TT.argdata, (void *)udl);
+ if (!new) {
+ if (ss[1]) {
+ udl = xmalloc(sizeof(*udl));
+ dlist_add_nomalloc(&TT.argdata, (void *)udl);
- if (*s == 'u') udl->u.uid = xgetpwnamid(ss[1])->pw_uid;
- else if (*s == 'g') udl->u.gid = xgetgrnamid(ss[1])->gr_gid;
- else {
- struct stat st;
+ if (*s == 'u') udl->u.uid = xgetpwnamid(ss[1])->pw_uid;
+ else if (*s == 'g') udl->u.gid = xgetgrnamid(ss[1])->gr_gid;
+ else {
+ struct stat st;
- xstat(ss[1], &st);
- udl->u.tm = st.st_mtim;
+ xstat(ss[1], &st);
+ udl->u.tm = st.st_mtim;
+ }
}
- } else if (check) {
+ } else {
udl = (void *)llist_pop(&argdata);
- if (*s == 'u') test = new->st.st_uid == udl->u.uid;
- else if (*s == 'g') test = new->st.st_gid == udl->u.gid;
- else {
- test = new->st.st_mtim.tv_sec > udl->u.tm.tv_sec;
- if (new->st.st_mtim.tv_sec == udl->u.tm.tv_sec)
- test = new->st.st_mtim.tv_nsec > udl->u.tm.tv_nsec;
+ if (check) {
+ if (*s == 'u') test = new->st.st_uid == udl->u.uid;
+ else if (*s == 'g') test = new->st.st_gid == udl->u.gid;
+ else {
+ test = new->st.st_mtim.tv_sec > udl->u.tm.tv_sec;
+ if (new->st.st_mtim.tv_sec == udl->u.tm.tv_sec)
+ test = new->st.st_mtim.tv_nsec > udl->u.tm.tv_nsec;
+ }
}
}
} else if (!strcmp(s, "exec") || !strcmp("ok", s)