]> git.ipfire.org Git - thirdparty/autoconf.git/commitdiff
mktmpdir: Ensure that $tmp is always an absolute pathname.
authorZack Weinberg <zackw@panix.com>
Thu, 24 Sep 2020 20:06:23 +0000 (16:06 -0400)
committerZack Weinberg <zackw@panix.com>
Thu, 24 Sep 2020 20:06:23 +0000 (16:06 -0400)
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.

lib/Autom4te/General.pm
tests/tools.at

index 010045754d0bf078df7de390936a73bd8d10da9e..e07e7e0f2f4253b04b61ae7e9084b9de797e4a8b 100644 (file)
@@ -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;
 }
 
 
index 2ad46ca11daa6e6492923d7b031fc86b68fe39e1..6288de00b5ec0a7137fbcbbd48d631ce2cfb1ac2 100644 (file)
@@ -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