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
