OSDN Git Service

Fix a find segfault.
authorRob Landley <rob@landley.net>
Sat, 12 Sep 2015 20:46:46 +0000 (15:46 -0500)
committerRob Landley <rob@landley.net>
Sat, 12 Sep 2015 20:46:46 +0000 (15:46 -0500)
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.)

tests/find.test
toys/posix/find.c

index cbbce5f..65bbb50 100755 (executable)
@@ -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
index 1058529..aca1984 100644 (file)
@@ -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)