summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZack Weinberg <zackw@panix.com>2020-09-24 16:06:23 -0400
committerZack Weinberg <zackw@panix.com>2020-09-24 16:06:23 -0400
commit730f382a92ec897b3142fdac4dc1f3c8a9a67909 (patch)
tree83dc2ae6bd5d3cdc408886aa8d223ba4e85189f1
parentbe818a3b94a9d5ae21e649455477ecff5e465e47 (diff)
downloadautoconf-730f382a92ec897b3142fdac4dc1f3c8a9a67909.tar.gz
mktmpdir: Ensure that $tmp is always an absolute pathname.
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 <https://bugs.gentoo.org/625576>. 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.
-rw-r--r--lib/Autom4te/General.pm41
-rw-r--r--tests/tools.at32
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<END>
-Filter Perl's exit codes, delete any temporary directory (unless
-C<$debug>), and exit nonzero whenever closing C<STDOUT> fails.
+Filter Perl's exit codes and exit nonzero whenever closing C<STDOUT> 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<mktmpdir ($signature)>
Create a temporary directory which name is based on C<$signature>.
-Store its name in C<$tmp>. C<END> 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<do FILE> 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