The original problem that led me to find this bug was reported here:

  https://bugs.launchpad.net/ubuntu/+source/findutils/+bug/373214

... and amounts to "/usr/include/asm/ contents missing from Linux kernel
package when built with findutils 4.4.1".


The -prune action needs stat information when -depth is not given, but
find's parser fails to declare this. It is therefore possible for -prune
to use undefined stat data.

I've attached a patch (against the rel-4-4-fixes branch, I'm afraid; I
have spent the whole afternoon trying to track this down in the face of
half our developers complaining because all their builds are breaking,
so I'd rather do something else right now, but I wanted to get this
patch sent; if you need it reconstructed against master then I can do
that tomorrow), including a test that you may be able to get to
demonstrate the problem. Whether the test actually fails for you is
unfortunately not certain, since it's an undefined-data problem; you
should at least be able to see the bug manually by breaking on
pred_prune.

Thanks,

-- 
Colin Watson                                       [[email protected]]
>From f16477379378235642e139effc9fbb2a74d7e90c Mon Sep 17 00:00:00 2001
From: Colin Watson <[email protected]>
Date: Thu, 7 May 2009 22:11:09 +0100
Subject: [PATCH] find -prune now makes sure it has valid stat() information

* find/parser.c (parse_prune): -prune needs stat information if
-depth is not in use.
* find/pred.c (pred_prune): Assert that stat information is
available if needed.
* find/testsuite/find.posix/prune-stat.exp: New test.
* find/testsuite/find.posix/prune-stat.xo: New test.
* find/testsuite/Makefile.am (EXTRA_DIST_EXP, EXTRA_DIST_XO): Added
prune-stat.exp, prune-stat.xo.
* NEWS: Mention this bugfix.

Signed-off-by: Colin Watson <[email protected]>
---
 ChangeLog                                |   12 ++++++++++++
 NEWS                                     |    4 ++++
 find/parser.c                            |    3 ++-
 find/pred.c                              |   10 ++++++----
 find/testsuite/Makefile.am               |    2 ++
 find/testsuite/find.posix/prune-stat.exp |    7 +++++++
 find/testsuite/find.posix/prune-stat.xo  |    3 +++
 7 files changed, 36 insertions(+), 5 deletions(-)
 create mode 100644 find/testsuite/find.posix/prune-stat.exp
 create mode 100644 find/testsuite/find.posix/prune-stat.xo

diff --git a/ChangeLog b/ChangeLog
index 640a704..41c878a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2009-05-07  Colin Watson  <[email protected]>
+
+	* find/parser.c (parse_prune): -prune needs stat information if
+	-depth is not in use.
+	* find/pred.c (pred_prune): Assert that stat information is
+	available if needed.
+	* find/testsuite/find.posix/prune-stat.exp: New test.
+	* find/testsuite/find.posix/prune-stat.xo: New test.
+	* find/testsuite/Makefile.am (EXTRA_DIST_EXP, EXTRA_DIST_XO): Added
+	prune-stat.exp, prune-stat.xo.
+	* NEWS: Mention this bugfix.
+
 2009-04-25  James Youngman  <[email protected]>
 
 	* AUTHORS: Add Andreas Metzler.
diff --git a/NEWS b/NEWS
index 49659cb..90e9c17 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,10 @@ GNU findutils NEWS - User visible changes.	-*- outline -*- (allout)
 
 * Major changes in release 4.4.2-git, YYYY-MM-DD
 
+** Bug Fixes
+
+find -prune now makes sure it has valid stat() information.
+
 * Major changes in release 4.4.1, 2009-04-21
 
 ** Bug Fixes
diff --git a/find/parser.c b/find/parser.c
index de4ef24..534b670 100644
--- a/find/parser.c
+++ b/find/parser.c
@@ -1982,7 +1982,8 @@ parse_prune (const struct parser_table* entry, char **argv, int *arg_ptr)
   (void) arg_ptr;
 
   our_pred = insert_primary (entry);
-  our_pred->need_stat = our_pred->need_type = false;
+  if (options.do_dir_first == false)
+    our_pred->need_stat = our_pred->need_type = false;
   /* -prune has a side effect that it does not descend into
      the current directory. */
   our_pred->side_effects = true;
diff --git a/find/pred.c b/find/pred.c
index d7253e4..b1f48a0 100644
--- a/find/pred.c
+++ b/find/pred.c
@@ -1605,10 +1605,12 @@ pred_prune (const char *pathname, struct stat *stat_buf, struct predicate *pred_
   (void) pathname;
   (void) pred_ptr;
 
-  if (options.do_dir_first == true && /* no effect with -depth */
-      stat_buf != NULL &&
-      S_ISDIR(stat_buf->st_mode))
-    state.stop_at_current_level = true;
+  if (options.do_dir_first == true) { /* no effect with -depth */
+    assert (state.have_stat);
+    if (stat_buf != NULL &&
+	S_ISDIR(stat_buf->st_mode))
+      state.stop_at_current_level = true;
+  }
 
   /* findutils used to return options.do_dir_first here, so that -prune
    * returns true only if -depth is not in effect.   But POSIX requires
diff --git a/find/testsuite/Makefile.am b/find/testsuite/Makefile.am
index 1b68b0d..dca30e6 100644
--- a/find/testsuite/Makefile.am
+++ b/find/testsuite/Makefile.am
@@ -88,6 +88,7 @@ find.posix/perm-vanilla.xo \
 find.posix/posixnot.xo \
 find.posix/prune.xo \
 find.posix/prune-result.xo \
+find.posix/prune-stat.xo \
 find.posix/sizes.xo \
 find.posix/sizetype.xo \
 find.posix/sv-bug-11175.xo \
@@ -205,6 +206,7 @@ find.posix/perm-vanilla.exp \
 find.posix/posixnot.exp \
 find.posix/prune.exp \
 find.posix/prune-result.exp \
+find.posix/prune-stat.exp \
 find.posix/size-invalid.exp \
 find.posix/size-missing.exp \
 find.posix/sizes.exp \
diff --git a/find/testsuite/find.posix/prune-stat.exp b/find/testsuite/find.posix/prune-stat.exp
new file mode 100644
index 0000000..b418d78
--- /dev/null
+++ b/find/testsuite/find.posix/prune-stat.exp
@@ -0,0 +1,7 @@
+# tests that -prune gets stat information
+exec rm -rf tmp
+exec mkdir tmp tmp/a
+exec touch tmp/b
+exec mkdir tmp/c
+find_start p {tmp -name b -prune -o -print }
+exec rm -rf tmp
diff --git a/find/testsuite/find.posix/prune-stat.xo b/find/testsuite/find.posix/prune-stat.xo
new file mode 100644
index 0000000..471c9c4
--- /dev/null
+++ b/find/testsuite/find.posix/prune-stat.xo
@@ -0,0 +1,3 @@
+tmp
+tmp/a
+tmp/c
-- 
1.6.0.4

Reply via email to