From 730f382a92ec897b3142fdac4dc1f3c8a9a67909 Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Thu, 24 Sep 2020 16:06:23 -0400 Subject: mktmpdir: Ensure that $tmp is always an absolute pathname. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Several autotools programs use ‘do’ to evaluate Perl code generated into a file in the temporary directory created by Autom4te::General::mktmpdir. If the environment variable TMPDIR is a relative path, mktmpdir will set $tmp to a relative path and we’ll end up trying to ‘do’ a relative path, which searches for the file in @INC. This doesn’t work under perl 5.26 or later, because ‘.’ was removed from @INC in that version (for security reasons). Ensure that mktmpdir sets $tmp to an absolute pathname. Also use File::Temp::tempdir to create the temporary directory, instead of shelling out to ‘mktemp -d’; this eliminates a subprocess and means we don’t have to worry about cleaning up the directory on exit. Problem found by Kent Fredric and reported as . Supersedes Gentoo’s autoconf-2.69-perl-5.26-2.patch. * lib/Autom4te/General.pm (mktmpdir): Use File::Temp to create temporary directory. Ensure that $tmp is an absolute path. (END): No need to clean up $tmp. * tests/tools.at (autotools and relative TMPDIR): New test. --- lib/Autom4te/General.pm | 41 +++++++++++++++++------------------------ tests/tools.at | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/lib/Autom4te/General.pm b/lib/Autom4te/General.pm index 01004575..e07e7e0f 100644 --- a/lib/Autom4te/General.pm +++ b/lib/Autom4te/General.pm @@ -39,8 +39,9 @@ use warnings FATAL => 'all'; use Carp; use Exporter; use File::Basename; -use File::Path (); +use File::Spec (); use File::stat; +use File::Temp (); use IO::File; use Autom4te::ChannelDefs; @@ -152,8 +153,7 @@ our $version = undef; =item C -Filter Perl's exit codes, delete any temporary directory (unless -C<$debug>), and exit nonzero whenever closing C fails. +Filter Perl's exit codes and exit nonzero whenever closing C fails. =cut @@ -184,12 +184,6 @@ sub END # from calls to die when `$! = n'. It's not big deal because # we only call `exit (0)' or `exit (1)'.) - if (!$debug && defined $tmp && -d $tmp) - { - local $SIG{__WARN__} = sub { $status = 1; warn $_[0] }; - File::Path::rmtree $tmp; - } - # This is required if the code might send any output to stdout # E.g., even --version or --help. So it's best to do it unconditionally. if (! close STDOUT) @@ -284,8 +278,8 @@ sub shell_quote($) =item C Create a temporary directory which name is based on C<$signature>. -Store its name in C<$tmp>. C is in charge of removing it, unless -C<$debug>. +Store its name in C<$tmp>. It will be removed at program exit, +unless C<$debug> is true. =cut @@ -294,23 +288,22 @@ C<$debug>. sub mktmpdir ($) { my ($signature) = @_; - my $TMPDIR = $ENV{'TMPDIR'} || '/tmp'; - my $quoted_tmpdir = shell_quote ($TMPDIR); - # If mktemp supports dirs, use it. - $tmp = `(umask 077 && - mktemp -d $quoted_tmpdir/"${signature}XXXXXX") 2>/dev/null`; - chomp $tmp; - - if (!$tmp || ! -d $tmp) - { - $tmp = "$TMPDIR/$signature" . int (rand 10000) . ".$$"; - mkdir $tmp, 0700 - or croak "$me: cannot create $tmp: $!\n"; - } + # Ensure that we refer to the temporary directory by absolute + # pathname; most importantly, this ensures that C will + # work whenever FILE is in $tmp, even when '.' is not in @INC + # (perl 5.26 and later). + my $TMPDIR = File::Spec->rel2abs (File::Spec->tmpdir ()); + $tmp = File::Temp::tempdir ( + $signature . "XXXXXX", + DIR => $TMPDIR, + CLEANUP => !$debug + ); print STDERR "$me:$$: working in $tmp\n" if $debug; + + return $tmp; } diff --git a/tests/tools.at b/tests/tools.at index 2ad46ca1..6288de00 100644 --- a/tests/tools.at +++ b/tests/tools.at @@ -1621,3 +1621,35 @@ END done AT_CLEANUP + +# autotools and file names containing whitespace +# ---------------------------------------------- + +AT_SETUP([autotools and relative TMPDIR]) + +# We use aclocal. +AT_CHECK([aclocal --version || exit 77], [], [ignore], [ignore]) + +mkdir _tmp +TMPDIR=_tmp +export TMPDIR + +AT_DATA([configure.ac], +[[AC_INIT(x,0) +AC_CONFIG_HEADERS([config.h:config.hin]) +AC_MACRO +AC_OUTPUT +]]) + +mkdir m4 +AT_DATA([m4/foo.m4], +[[AC_DEFUN([AC_MACRO], +[AC_DEFINE([HAVE_MACROS], 1, [Define if you have macros.])]) +]]) + +AT_CHECK([aclocal -I m4]) +AT_CHECK_AUTOHEADER([], [HAVE_MACROS]) +AT_CHECK_AUTOCONF +AT_CHECK_CONFIGURE + +AT_CLEANUP -- cgit v1.2.1