summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2007-08-05 12:22:14 +0000
committerEric Blake <ebb9@byu.net>2007-08-05 12:22:14 +0000
commit4859cfca404f2e51b53f5696b70f7b845a69af69 (patch)
tree4bb3b69c0371902f66fb0fbdf89f631a8276caf4
parent756cecd45b0545ad52345507592cfa3c9f97a0ad (diff)
downloadfindutils-4859cfca404f2e51b53f5696b70f7b845a69af69.tar.gz
Fix Savannah bugs #20662, 20688.
* find/find.c (at_top): Avoid memory leak. * find/pred.c (do_fprintf, pred_iname, pred_name): Likewise. (pred_name_common): New function, factored from pred_iname and pred_name. * find/parser.c (check_name_arg): Let -nowarn silence -name /. * locate/locate.c (visit_basename): Avoid memory leak. * NEWS: Document the changes. * doc/find.texi (Warning Messages): Document -nowarn's effect on -name and -iname. * find/testsuite/find.gnu/name-slash.exp: New test, to ensure 20662 doesn't regress on '-name /', and that 20688 silences the warning. * find/testsuite/find.gnu/printf-slash.exp: Likewise. * find/testsuite/find.gnu/name-slash.xo: Expected results. * find/testsuite/find.gnu/printf-slash.xo: Likewise. * find/testsuite/Makefile.am (EXTRA_DIST_XO, EXTRA_DIST_EXP): Distribute new tests.
-rw-r--r--ChangeLog21
-rw-r--r--NEWS7
-rw-r--r--doc/find.texi9
-rw-r--r--find/find.c10
-rw-r--r--find/parser.c4
-rw-r--r--find/pred.c53
-rw-r--r--find/testsuite/Makefile.am4
-rw-r--r--find/testsuite/find.gnu/name-slash.exp2
-rw-r--r--find/testsuite/find.gnu/name-slash.xo2
-rw-r--r--find/testsuite/find.gnu/printf-slash.exp1
-rw-r--r--find/testsuite/find.gnu/printf-slash.xo2
-rw-r--r--locate/locate.c5
12 files changed, 88 insertions, 32 deletions
diff --git a/ChangeLog b/ChangeLog
index a1031de8..cf9c67e2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2007-08-05 Eric Blake <ebb9@byu.net>
+
+ Fix Savannah bugs #20662, #20688.
+ * find/find.c (at_top): Avoid memory leak.
+ * find/pred.c (do_fprintf, pred_iname, pred_name): Likewise.
+ (pred_name_common): New function, factored from pred_iname and
+ pred_name.
+ * find/parser.c (check_name_arg): Let -nowarn silence -name /.
+ * locate/locate.c (visit_basename): Avoid memory leak.
+ * NEWS: Document the changes.
+ * doc/find.texi (Warning Messages): Document -nowarn's effect on
+ -name and -iname.
+ * find/testsuite/find.gnu/name-slash.exp: New test, to ensure
+ 20662 doesn't regress on '-name /', and that 20688 silences the
+ warning.
+ * find/testsuite/find.gnu/printf-slash.exp: Likewise.
+ * find/testsuite/find.gnu/name-slash.xo: Expected results.
+ * find/testsuite/find.gnu/printf-slash.xo: Likewise.
+ * find/testsuite/Makefile.am (EXTRA_DIST_XO, EXTRA_DIST_EXP):
+ Distribute new tests.
+
2007-07-31 Eric Blake <ebb9@byu.net>
Allow choice of default arg size, Savannah bug #20594.
diff --git a/NEWS b/NEWS
index e8526484..29372008 100644
--- a/NEWS
+++ b/NEWS
@@ -27,11 +27,18 @@ does not follow the POSIX rules of doing likewise.
updatedb, frcode and code now complies with the GNU Project's coding
standards.
+#20662: Avoid memory leak in find -name and other places affected by
+gnulib dirname module. The leak had been present since 4.3.1.
+
** Enhancements
#20594: Allow fine-tuning of the default argument size used by xargs
and find at ./configure time.
+#20688: The warning printed by -name or -iname when the pattern to
+ match contains a slash can now be silenced by -nowarn. This warning
+ was originally introduced unconditionally in 4.2.21.
+
** Documentation Fixes
Point out more explicitly that the subsecond timestamp support
diff --git a/doc/find.texi b/doc/find.texi
index d6e9c64b..3c3e11b9 100644
--- a/doc/find.texi
+++ b/doc/find.texi
@@ -31,8 +31,8 @@
This file documents the GNU utilities for finding files that match
certain criteria and performing various operations on them.
-Copyright (C) 1994, 1996, 1998, 2000, 2001, 2003, 2004, 2005 Free
-Software Foundation, Inc.
+Copyright (C) 1994, 1996, 1998, 2000, 2001, 2003, 2004, 2005, 2006,
+2007 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -2972,6 +2972,11 @@ Use of the @samp{-ipath} option which is deprecated; please use
@item
Specifying an option (for example @samp{-mindepth}) after a non-option
(for example @samp{-type} or @samp{-print}) on the command line.
+@item
+Use of the @samp{-name} or @samp{-iname} option with a slash character
+in the pattern. Since the name predicates only compare against the
+basename of the visited files, the only file that can match a slash is
+the root directory itself.
@end itemize
The default behaviour above is designed to work in that way so that
diff --git a/find/find.c b/find/find.c
index 8dcf0012..72f555ae 100644
--- a/find/find.c
+++ b/find/find.c
@@ -1,6 +1,6 @@
/* find -- search for files in a directory hierarchy
Copyright (C) 1990, 91, 92, 93, 94, 2000,
- 2003, 2004, 2005 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -947,13 +947,13 @@ at_top (char *pathname,
struct stat *pstat))
{
int dirchange;
- char *parent_dir = dir_name(pathname);
- char *base = base_name(pathname);
-
+ char *parent_dir = dir_name (pathname);
+ char *base = last_component (pathname);
+
state.curdepth = 0;
state.starting_path_length = strlen (pathname);
- if (0 == strcmp(pathname, parent_dir)
+ if (0 == *base
|| 0 == strcmp(parent_dir, "."))
{
dirchange = 0;
diff --git a/find/parser.c b/find/parser.c
index 6c078aa1..2a5b19e2 100644
--- a/find/parser.c
+++ b/find/parser.c
@@ -1124,10 +1124,10 @@ fnmatch_sanitycheck(void)
}
-static boolean
+static boolean
check_name_arg(const char *pred, const char *arg)
{
- if (strchr(arg, '/'))
+ if (options.warnings && strchr(arg, '/'))
{
error(0, 0,_("warning: Unix filenames usually don't contain slashes (though pathnames do). That means that '%s %s' will probably evaluate to false all the time on this system. You might find the '-wholename' test more useful, or perhaps '-samefile'. Alternatively, if you are using GNU grep, you could use 'find ... -print0 | grep -FzZ %s'."),
pred,
diff --git a/find/pred.c b/find/pred.c
index 5e3adb70..730a8765 100644
--- a/find/pred.c
+++ b/find/pred.c
@@ -741,7 +741,11 @@ do_fprintf(struct format_val *dest,
break;
case 'f': /* base name of path */
/* sanitised */
- checked_print_quoted (dest, segment->text, base_name (pathname));
+ {
+ char *base = base_name (pathname);
+ checked_print_quoted (dest, segment->text, base);
+ free (base);
+ }
break;
case 'F': /* file system type */
/* trusted */
@@ -1150,20 +1154,38 @@ pred_ilname (const char *pathname, struct stat *stat_buf, struct predicate *pred
return match_lname (pathname, stat_buf, pred_ptr, true);
}
-boolean
-pred_iname (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
+/* Common code between -name, -iname. PATHNAME is being visited, STR
+ is name to compare basename against, and FLAGS are passed to
+ fnmatch. */
+static boolean
+pred_name_common (const char *pathname, const char *str, int flags)
{
- const char *base;
-
- (void) stat_buf;
+ /* Prefer last_component over base_name, to avoid malloc when
+ possible. */
+ char *base = last_component (pathname);
+ /* base is empty only if pathname is a file system root. But recall
+ that 'find / -name /' is one of the few times where a '/' in the
+ -name must actually find something. */
+ if (!*base)
+ {
+ boolean b;
+ base = base_name (pathname);
+ b = fnmatch (str, base, flags) == 0;
+ free (base);
+ return b;
+ }
/* FNM_PERIOD is not used here because POSIX requires that it not be.
* See http://standards.ieee.org/reading/ieee/interp/1003-2-92_int/pasc-1003.2-126.html
*/
- base = base_name (pathname);
- if (fnmatch (pred_ptr->args.str, base, FNM_CASEFOLD) == 0)
- return (true);
- return (false);
+ return fnmatch (str, base, flags) == 0;
+}
+
+boolean
+pred_iname (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
+{
+ (void) stat_buf;
+ return pred_name_common (pathname, pred_ptr->args.str, FNM_CASEFOLD);
}
boolean
@@ -1271,17 +1293,8 @@ pred_mtime (const char *pathname, struct stat *stat_buf, struct predicate *pred_
boolean
pred_name (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
{
- const char *base;
-
(void) stat_buf;
- base = base_name (pathname);
-
- /* FNM_PERIOD is not used here because POSIX requires that it not be.
- * See http://standards.ieee.org/reading/ieee/interp/1003-2-92_int/pasc-1003.2-126.html
- */
- if (fnmatch (pred_ptr->args.str, base, 0) == 0)
- return (true);
- return (false);
+ return pred_name_common (pathname, pred_ptr->args.str, 0);
}
boolean
diff --git a/find/testsuite/Makefile.am b/find/testsuite/Makefile.am
index 02d4c751..c1033d43 100644
--- a/find/testsuite/Makefile.am
+++ b/find/testsuite/Makefile.am
@@ -37,6 +37,7 @@ find.gnu/lname.xo \
find.gnu/mindepth-arg.xo \
find.gnu/name-opt.xo \
find.gnu/name-period.xo \
+find.gnu/name-slash.xo \
find.gnu/path.xo \
find.gnu/print_stdout.xo \
find.gnu/perm.xo \
@@ -46,6 +47,7 @@ find.gnu/posix-dflt.xo \
find.gnu/posix-h.xo \
find.gnu/posix-l.xo \
find.gnu/printfHdfl.xo \
+find.gnu/printf-slash.xo \
find.gnu/printf-symlink.xo \
find.gnu/printf-h.xo \
find.gnu/printf.xo \
@@ -133,6 +135,7 @@ find.gnu/mindepth-arg.exp \
find.gnu/mindepth-badarg.exp \
find.gnu/name-opt.exp \
find.gnu/name-period.exp \
+find.gnu/name-slash.exp \
find.gnu/path.exp \
find.gnu/print_stdout.exp \
find.gnu/print0.exp \
@@ -145,6 +148,7 @@ find.gnu/posix-l.exp \
find.gnu/printfHdfl.exp \
find.gnu/printf.exp \
find.gnu/printf.exp \
+find.gnu/printf-slash.exp \
find.gnu/printf-symlink.exp \
find.gnu/printf-h.exp \
find.gnu/prune-default-print.exp \
diff --git a/find/testsuite/find.gnu/name-slash.exp b/find/testsuite/find.gnu/name-slash.exp
new file mode 100644
index 00000000..bd9a187b
--- /dev/null
+++ b/find/testsuite/find.gnu/name-slash.exp
@@ -0,0 +1,2 @@
+# tests for '-name /'
+find_start p {/ /// -maxdepth 0 -name /}
diff --git a/find/testsuite/find.gnu/name-slash.xo b/find/testsuite/find.gnu/name-slash.xo
new file mode 100644
index 00000000..6c241446
--- /dev/null
+++ b/find/testsuite/find.gnu/name-slash.xo
@@ -0,0 +1,2 @@
+/
+///
diff --git a/find/testsuite/find.gnu/printf-slash.exp b/find/testsuite/find.gnu/printf-slash.exp
new file mode 100644
index 00000000..3f460238
--- /dev/null
+++ b/find/testsuite/find.gnu/printf-slash.exp
@@ -0,0 +1 @@
+find_start p {/ /// -maxdepth 0 -printf "%p %f\\n"}
diff --git a/find/testsuite/find.gnu/printf-slash.xo b/find/testsuite/find.gnu/printf-slash.xo
new file mode 100644
index 00000000..50f8192f
--- /dev/null
+++ b/find/testsuite/find.gnu/printf-slash.xo
@@ -0,0 +1,2 @@
+/ /
+/// /
diff --git a/locate/locate.c b/locate/locate.c
index b02f227d..1595075a 100644
--- a/locate/locate.c
+++ b/locate/locate.c
@@ -337,7 +337,7 @@ struct process_data
int len;
char *original_filename; /* The current input database entry. */
size_t pathsize; /* Amount allocated for it. */
- char *munged_filename; /* path or base_name(path) */
+ char *munged_filename; /* path or basename(path) */
FILE *fp; /* The pathname database. */
const char *dbfile; /* Its name, or "<stdin>" */
int slocatedb_format; /* Allows us to cope with slocate's format variant */
@@ -641,7 +641,7 @@ static int
visit_basename(struct process_data *procdata, void *context)
{
(void) context;
- procdata->munged_filename = base_name(procdata->original_filename);
+ procdata->munged_filename = last_component (procdata->original_filename);
return VISIT_CONTINUE;
}
@@ -1929,4 +1929,3 @@ main (int argc, char **argv)
return dolocate(argc, argv, dbfd);
}
-