>From fbdadfe9226b3de9712cafcbb0734131e0a73f4f Mon Sep 17 00:00:00 2001 From: Pavel Raiskup
Date: Sun, 15 Nov 2015 12:54:19 +0100 Subject: [PATCH 3/3] incremen: don't indefinitely recurse into symlink loop This complements previous commit. * src/common.h (nl_dir_loop_point): New prototype. * src/incremen.c (nl_dir_loop_point): New function. * src/names.c (add_hierarchy_to_namelist): Don't recurse down to the directory if the directory is already in namelist. Use nl_dir_loop_point for detection. * tests/deref02.at: New testcase. * tests/testsuite.at: Mention new testcase. * tests/Makefile.am (TESTSUITE_AT): Likewise. --- src/common.h | 1 + src/incremen.c | 19 +++++++++++++++++++ src/names.c | 8 ++++++++ tests/Makefile.am | 1 + tests/deref02.at | 40 ++++++++++++++++++++++++++++++++++++++++ tests/testsuite.at | 1 + 6 files changed, 70 insertions(+) create mode 100644 tests/deref02.at diff --git a/src/common.h b/src/common.h index 7f4103a..49e1973 100644 --- a/src/common.h +++ b/src/common.h @@ -566,6 +566,7 @@ void update_parent_directory (struct tar_stat_info *st); size_t dumpdir_size (const char *p); bool is_dumpdir (struct tar_stat_info *stat_info); void clear_directory_table (void); +bool nl_dir_loop_point (struct name *name); /* Module list.c. */ diff --git a/src/incremen.c b/src/incremen.c index 19d0b9b..932882c 100644 --- a/src/incremen.c +++ b/src/incremen.c @@ -1758,6 +1758,25 @@ try_purge_directory (char const *directory_name) return true; } +bool +nl_dir_loop_point (struct name *name) +{ + const struct name *ptr = name; + + if (!dereference_option) + return false; + + while (ptr->parent) + { + ptr = ptr->parent; + if (ptr->directory->device_number == name->directory->device_number + && ptr->directory->inode_number == name->directory->inode_number) + return true; + } + + return false; +} + void purge_directory (char const *directory_name) { diff --git a/src/names.c b/src/names.c index 219aa77..02f757c 100644 --- a/src/names.c +++ b/src/names.c @@ -1543,6 +1543,14 @@ add_hierarchy_to_namelist (struct tar_stat_info *st, struct name *name) const char *buffer; name->directory = scan_directory (st); + + if (nl_dir_loop_point (name)) + { + WARN ((0, 0, _("%s: stopping recursion due to directory loop"), + name->name)); + return; + } + buffer = directory_contents (name->directory); if (buffer) { diff --git a/tests/Makefile.am b/tests/Makefile.am index aa7d49b..439ca6c 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -71,6 +71,7 @@ TESTSUITE_AT = \ delete04.at\ delete05.at\ deref01.at\ + deref02.at\ exclude.at\ exclude01.at\ exclude02.at\ diff --git a/tests/deref02.at b/tests/deref02.at new file mode 100644 index 0000000..0c20c08 --- /dev/null +++ b/tests/deref02.at @@ -0,0 +1,40 @@ +# Process this file with autom4te to create testsuite. -*- Autotest -*- +# +# Test suite for GNU tar. +# Copyright 2015 Free Software Foundation, Inc. + +# This file is part of GNU tar. + +# GNU tar is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# GNU tar is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see