From c39fe6a1cc42565fc51fdef67ee0d0008feade1a Mon Sep 17 00:00:00 2001 From: Ondrej Vasik Date: Fri, 27 Feb 2009 12:13:54 +0000 Subject: [PATCH] fix infinite loop in recursive cp (introduced by 7.1, upstream) --- coreutils-7.1-cp-recursiveinfloop.patch | 154 ++++++++++++++++++++++++ coreutils.spec | 8 +- 2 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 coreutils-7.1-cp-recursiveinfloop.patch diff --git a/coreutils-7.1-cp-recursiveinfloop.patch b/coreutils-7.1-cp-recursiveinfloop.patch new file mode 100644 index 0000000..963af0b --- /dev/null +++ b/coreutils-7.1-cp-recursiveinfloop.patch @@ -0,0 +1,154 @@ +diff -urNp coreutils-7.1-orig/src/copy.c coreutils-7.1/src/copy.c +--- coreutils-7.1-orig/src/copy.c 2009-02-27 12:07:29.000000000 +0100 ++++ coreutils-7.1/src/copy.c 2009-02-27 12:14:29.000000000 +0100 +@@ -104,6 +104,7 @@ static bool copy_internal (char const *s + struct dir_list *ancestors, + const struct cp_options *x, + bool command_line_arg, ++ bool *first_dir_created_per_command_line_arg, + bool *copy_into_self, + bool *rename_succeeded); + static bool owner_failure_ok (struct cp_options const *x); +@@ -201,13 +202,16 @@ copy_attr_by_name (char const *src_path, + DST_NAME_IN is a directory that was created previously in the + recursion. SRC_SB and ANCESTORS describe SRC_NAME_IN. + Set *COPY_INTO_SELF if SRC_NAME_IN is a parent of ++ FIRST_DIR_CREATED_PER_COMMAND_LINE_ARG FIXME + (or the same as) DST_NAME_IN; otherwise, clear it. + Return true if successful. */ + + static bool + copy_dir (char const *src_name_in, char const *dst_name_in, bool new_dst, + const struct stat *src_sb, struct dir_list *ancestors, +- const struct cp_options *x, bool *copy_into_self) ++ const struct cp_options *x, ++ bool *first_dir_created_per_command_line_arg, ++ bool *copy_into_self) + { + char *name_space; + char *namep; +@@ -237,12 +241,20 @@ copy_dir (char const *src_name_in, char + + ok &= copy_internal (src_name, dst_name, new_dst, src_sb->st_dev, + ancestors, &non_command_line_options, false, ++ first_dir_created_per_command_line_arg, + &local_copy_into_self, NULL); + *copy_into_self |= local_copy_into_self; + + free (dst_name); + free (src_name); + ++ /* If we're copying into self, there's no point in continuing, ++ and in fact, that would even infloop, now that we record only ++ the first created directory per command line argument. */ ++ if (local_copy_into_self) ++ break; ++ ++ + namep += strlen (namep) + 1; + } + free (name_space); +@@ -1125,6 +1137,7 @@ restore_default_fscreatecon_or_die (void + not known. ANCESTORS points to a linked, null terminated list of + devices and inodes of parent directories of SRC_NAME. COMMAND_LINE_ARG + is true iff SRC_NAME was specified on the command line. ++ FIRST_DIR_CREATED_PER_COMMAND_LINE_ARG is both input and output. + Set *COPY_INTO_SELF if SRC_NAME is a parent of (or the + same as) DST_NAME; otherwise, clear it. + Return true if successful. */ +@@ -1135,6 +1148,7 @@ copy_internal (char const *src_name, cha + struct dir_list *ancestors, + const struct cp_options *x, + bool command_line_arg, ++ bool *first_dir_created_per_command_line_arg, + bool *copy_into_self, + bool *rename_succeeded) + { +@@ -1815,11 +1829,15 @@ copy_internal (char const *src_name, cha + } + } + +- /* Insert the created directory's inode and device +- numbers into the search structure, so that we can +- avoid copying it again. */ +- if (!x->hard_link) +- remember_copied (dst_name, dst_sb.st_ino, dst_sb.st_dev); ++ /* Record the created directory's inode and device numbers into ++ the search structure, so that we can avoid copying it again. ++ Do this only for the first directory that is created for each ++ source command line argument. */ ++ if (!*first_dir_created_per_command_line_arg) ++ { ++ remember_copied (dst_name, dst_sb.st_ino, dst_sb.st_dev); ++ *first_dir_created_per_command_line_arg = true; ++ } + + if (x->verbose) + emit_verbose (src_name, dst_name, NULL); +@@ -1840,6 +1858,7 @@ copy_internal (char const *src_name, cha + in a source directory would cause the containing destination + directory not to have owner/perms set properly. */ + delayed_ok = copy_dir (src_name, dst_name, new_dst, &src_sb, dir, x, ++ first_dir_created_per_command_line_arg, + copy_into_self); + } + } +@@ -2187,8 +2206,11 @@ copy (char const *src_name, char const * + top_level_src_name = src_name; + top_level_dst_name = dst_name; + ++ bool first_dir_created_per_command_line_arg = false; + return copy_internal (src_name, dst_name, nonexistent_dst, 0, NULL, +- options, true, copy_into_self, rename_succeeded); ++ options, true, ++ &first_dir_created_per_command_line_arg, ++ copy_into_self, rename_succeeded); + } + + /* Set *X to the default options for a value of type struct cp_options. */ +diff -urNp coreutils-7.1-orig/tests/cp/into-self coreutils-7.1/tests/cp/into-self +--- coreutils-7.1-orig/tests/cp/into-self 2008-09-18 09:06:57.000000000 +0200 ++++ coreutils-7.1/tests/cp/into-self 2009-02-27 12:16:21.000000000 +0100 +@@ -1,7 +1,7 @@ + #!/bin/sh + # Confirm that copying a directory into itself gets a proper diagnostic. + +-# Copyright (C) 2001, 2002, 2004, 2006-2008 Free Software Foundation, Inc. ++# Copyright (C) 2001, 2002, 2004, 2006-2009 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 +@@ -28,15 +28,32 @@ fi + + . $srcdir/test-lib.sh + +-mkdir dir || framework_failure ++mkdir a dir || framework_failure + + fail=0 + + # This command should exit nonzero. + cp -R dir dir 2> out && fail=1 ++echo 1 >> out ++ ++# This should, too. However, with coreutils-7.1 it would infloop. ++cp -rl dir dir 2>> out && fail=1 ++echo 2 >> out ++ ++cp -rl a dir dir 2>> out && fail=1 ++echo 3 >> out ++cp -rl a dir dir 2>> out && fail=1 ++echo 4 >> out + + cat > exp <<\EOF + cp: cannot copy a directory, `dir', into itself, `dir/dir' ++1 ++cp: cannot copy a directory, `dir', into itself, `dir/dir' ++2 ++cp: cannot copy a directory, `dir', into itself, `dir/dir' ++3 ++cp: cannot copy a directory, `dir', into itself, `dir/dir' ++4 + EOF + #' + diff --git a/coreutils.spec b/coreutils.spec index 9025a1b..bfa4a3a 100644 --- a/coreutils.spec +++ b/coreutils.spec @@ -1,7 +1,7 @@ Summary: A set of basic GNU tools commonly used in shell scripts Name: coreutils Version: 7.1 -Release: 4%{?dist} +Release: 5%{?dist} License: GPLv3+ Group: System Environment/Base Url: http://www.gnu.org/software/coreutils/ @@ -20,6 +20,7 @@ Source203: coreutils-runuser-l.pamd # From upstream Patch1: coreutils-7.1-sort-endoffields.patch +Patch2: coreutils-7.1-cp-recursiveinfloop.patch # Our patches Patch100: coreutils-6.10-configuration.patch @@ -100,6 +101,7 @@ the old GNU fileutils, sh-utils, and textutils packages. # From upstream %patch1 -p1 -b .endfield +%patch2 -p1 -b .recinfloop # Our patches %patch100 -p1 -b .configure @@ -311,6 +313,10 @@ fi /sbin/runuser %changelog +* Fri Feb 27 2009 Ondrej Vasik 7.1-5 +- fix infinite loop in recursive cp (upstream, introduced + by 7.1) + * Thu Feb 26 2009 Ondrej Vasik 7.1-4 - fix showing ACL's for ls -Z (#487374), fix automatic column width for it as well