[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 1/10] Proper file name escaping in Autoconf programs and Perl mod
From: |
Ralf Wildenhues |
Subject: |
[PATCH 1/10] Proper file name escaping in Autoconf programs and Perl modules. |
Date: |
Tue, 4 Dec 2007 22:45:09 +0100 |
User-agent: |
Mutt/1.5.13 (2006-08-11) |
This includes escaping of characters special to the shell
as well as special to Perl, e.g., leading `<' or `>'.
For example, when $file starts with `>', `open ">$file"'
wrongly tries to append to a different file.
* bin/autoconf.as: Fix quoting for autom4te options.
* lib/Autom4te/General.pm (shell_quote): New function, taken
from coreutils, written by Jim Meyering.
(mktmpdir): Use it.
* lib/Autom4te/FileUtils.pm (update_file): IO::File usage
fix.
* bin/autom4te.in (files_to_options, handle_m4): Use quote_file.
* bin/autoreconf.in (parse_args): Likewise.
* bin/autoscan.in (main): Likewise.
* bin/autoupdate.in (main): Likewise.
* bin/autoheader.in: Likewise, fixing old insufficient escaping.
* bin/ifnames.in: Likewise, XFile usage fixes.
* tests/tools.at (autom4te and whitespace in file names): Extend
test.
(autotools and whitespace in file names): New test.
Reported by Paul Eggert and Benoit Sigoure.
---
This changes FileUtils.pm whose master source is Automake.
I think the changes are not problematic for Automake, but
have not tested yet.
FWIW, I checked the Autoconf code to the end that the new tests
exercise each change, except for a couple, which I am still
investigating.
bin/autoconf.as | 17 ++++++--
bin/autoheader.in | 21 +++++-----
bin/autom4te.in | 40 +++++++++-----------
bin/autoreconf.in | 10 ++--
bin/autoscan.in | 18 ++++----
bin/autoupdate.in | 34 ++++++++--------
bin/ifnames.in | 2 +-
lib/Autom4te/FileUtils.pm | 4 +-
lib/Autom4te/General.pm | 33 +++++++++++++++-
tests/tools.at | 91 ++++++++++++++++++++++++++++++++++++++++----
10 files changed, 187 insertions(+), 83 deletions(-)
diff --git a/bin/autoconf.as b/bin/autoconf.as
index b68d4ef..dbabc30 100644
--- a/bin/autoconf.as
+++ b/bin/autoconf.as
@@ -107,14 +107,21 @@ while test $# -gt 0 ; do
--include=* | -I?* | \
--prepend-include=* | -B?* | \
--warnings=* | -W?* )
- autom4te_options="$autom4te_options '$1'"; shift ;;
-
+ case $1 in
+ *\'*) arg=`AS_ECHO(["$1"]) | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) arg=$1 ;;
+ esac
+ autom4te_options="$autom4te_options '$arg'"; shift ;;
# Options with separated arg passed as is to autom4te.
--include | -I | \
--prepend-include | -B | \
--warnings | -W )
test $# = 1 && eval "$exit_missing_arg"
- autom4te_options="$autom4te_options $option '$2'"
+ case $2 in
+ *\'*) arg=`AS_ECHO(["$2"]) | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) arg=$2 ;;
+ esac
+ autom4te_options="$autom4te_options $option '$arg'"
shift; shift ;;
--trace=* | -t?* )
@@ -178,8 +185,8 @@ esac
test -z "$outfile" && outfile=-
# Run autom4te with expansion.
-eval set x $autom4te_options \
- --language=autoconf --output=\$outfile "$traces" \$infile
+eval set x "$autom4te_options" \
+ --language=autoconf --output=\"\$outfile\" "$traces" \"\$infile\"
shift
$verbose && AS_ECHO(["$as_me: running $AUTOM4TE $*"]) >&2
exec "$AUTOM4TE" "$@"
diff --git a/bin/autoheader.in b/bin/autoheader.in
index 9c19ea3..ed88556 100644
--- a/bin/autoheader.in
+++ b/bin/autoheader.in
@@ -157,8 +157,8 @@ END
# Set up autoconf.
my $autoconf = "'$autom4te' --language=autoconf ";
-$autoconf .= join (' ', map { "--include='$_'" } @include);
-$autoconf .= join (' ', map { "--prepend-include='$_'" } @prepend_include);
+$autoconf .= join (' --include=', '', map { shell_quote ($_) } @include);
+$autoconf .= join (' --prepend-include=', '', map { shell_quote ($_) }
@prepend_include);
$autoconf .= ' --debug' if $debug;
$autoconf .= ' --force' if $force;
$autoconf .= ' --verbose' if $verbose;
@@ -169,16 +169,17 @@ $autoconf .= ' --verbose' if $verbose;
# Source what the traces are trying to tell us.
verb "$me: running $autoconf to trace from $ARGV[0]";
+my $quoted_tmp = shell_quote ($tmp);
xsystem ("$autoconf"
# If you change this list, update the
# `Autoheader-preselections' section of autom4te.in.
. ' --trace AC_CONFIG_HEADERS:\'$$config_h ||= \'"\'"\'$1\'"\'"\';\''
. ' --trace AH_OUTPUT:\'$$verbatim{\'"\'"\'$1\'"\'"\'} =
\'"\'"\'$2\'"\'"\';\''
. ' --trace AC_DEFINE_TRACE_LITERAL:\'$$symbol{\'"\'"\'$1\'"\'"\'} =
1;\''
- . " $ARGV[0] >$tmp/traces.pl");
+ . " " . shell_quote ($ARGV[0]) . " >$quoted_tmp/traces.pl");
local (%verbatim, %symbol);
-debug "$me: \`do'ing $tmp/traces.pl:\n" . `sed 's/^/| /' $tmp/traces.pl`;
+debug "$me: \`do'ing $tmp/traces.pl:\n" . `sed 's/^/| /'
$quoted_tmp/traces.pl`;
do "$tmp/traces.pl";
warn "couldn't parse $tmp/traces.pl: $@" if $@;
unless ($config_h)
@@ -197,7 +198,7 @@ $config_h_in ||= "$config_h.in";
# only the name of the macro.
%symbol = map { s/\(.*//; $_ => 1 } keys %symbol;
-my $out = new Autom4te::XFile (">$tmp/config.hin");
+my $out = new Autom4te::XFile ("> $tmp/config.hin");
# Don't write "do not edit" -- it will get copied into the
# config.h, which it's ok to edit.
@@ -206,7 +207,7 @@ print $out "/* $config_h_in. Generated from $ARGV[0] by
autoheader. */\n";
# Dump the top.
if ($config_h_top)
{
- my $in = new Autom4te::XFile ($config_h_top);
+ my $in = new Autom4te::XFile ("< $config_h_top");
while ($_ = $in->getline)
{
print $out $_;
@@ -216,7 +217,7 @@ if ($config_h_top)
# Dump `acconfig.h', except for its bottom portion.
if ($acconfig_h)
{
- my $in = new Autom4te::XFile ($acconfig_h);
+ my $in = new Autom4te::XFile ("< $acconfig_h");
while ($_ = $in->getline)
{
last if /address@hidden@/;
@@ -234,7 +235,7 @@ foreach (sort keys %verbatim)
# Dump bottom portion of `acconfig.h'.
if ($acconfig_h)
{
- my $in = new Autom4te::XFile ($acconfig_h);
+ my $in = new Autom4te::XFile ("< $acconfig_h");
my $dump = 0;
while ($_ = $in->getline)
{
@@ -246,7 +247,7 @@ if ($acconfig_h)
# Dump the bottom.
if ($config_h_bot)
{
- my $in = new Autom4te::XFile ($config_h_bot);
+ my $in = new Autom4te::XFile ("< $config_h_bot");
while ($_ = $in->getline)
{
print $out $_;
@@ -257,7 +258,7 @@ $out->close;
# Check that all the symbols have a template.
{
- my $in = new Autom4te::XFile ("$tmp/config.hin");
+ my $in = new Autom4te::XFile ("< $tmp/config.hin");
my $suggest_ac_define = 1;
while ($_ = $in->getline)
{
diff --git a/bin/autom4te.in b/bin/autom4te.in
index b273b9a..832a6e1 100644
--- a/bin/autom4te.in
+++ b/bin/autom4te.in
@@ -235,14 +235,10 @@ sub files_to_options (@)
my @res;
foreach my $file (@file)
{
- (my $arg = $file) =~ s/'/'\\''/g;
+ my $arg = shell_quote ($file);
if ($file =~ /\.m4f$/)
{
- $arg = "--reload-state=$file";
- }
- if ($file =~ /[\t "'\\\$()]/)
- {
- $arg = "'$arg'";
+ $arg = "--reload-state=$arg";
}
push @res, $arg;
}
@@ -258,7 +254,7 @@ sub load_configuration ($)
my ($file) = @_;
use Text::ParseWords;
- my $cfg = new Autom4te::XFile ($file);
+ my $cfg = new Autom4te::XFile ("< $file");
my $lang;
while ($_ = $cfg->getline)
{
@@ -462,13 +458,13 @@ sub handle_m4 ($@)
# We don't output directly to the cache files, to avoid problems
# when we are interrupted (that leaves corrupted files).
xsystem ("$m4"
- . join (' --include=', '', @include)
+ . join (' --include=', '', map { shell_quote ($_) } @include)
. ' --debug=aflq'
. (!exists $ENV{'AUTOM4TE_NO_FATAL'} ? ' --fatal-warning' : '')
- . " @address@hidden" . $req->id . "t"
+ . " @address@hidden" . shell_quote ("$tcache" . $req->id . "t")
. join (' --trace=', '', sort @macro)
. " " . files_to_options (@ARGV)
- . " >$ocache" . $req->id . "t");
+ . " > " . shell_quote ("$ocache" . $req->id . "t"));
# Everything went ok: preserve the outputs.
foreach my $file (map { $_ . $req->id } ($tcache, $ocache))
@@ -526,7 +522,7 @@ sub handle_output ($$)
handle_traces ($req, "$tmp/patterns",
('m4_pattern_forbid' => 'forbid:$1:$2',
'm4_pattern_allow' => 'allow:$1'));
- my @patterns = new Autom4te::XFile ("$tmp/patterns")->getlines;
+ my @patterns = new Autom4te::XFile ("< $tmp/patterns")->getlines;
chomp @patterns;
my %forbidden =
map { /^forbid:([^:]+):.+$/ => /^forbid:[^:]+:(.+)$/ } @patterns;
@@ -545,7 +541,7 @@ sub handle_output ($$)
my $out = new Autom4te::XFile;
if ($output eq '-')
{
- $out->open (">$output");
+ $out->open ("> $output");
}
else
{
@@ -553,7 +549,7 @@ sub handle_output ($$)
}
fatal "cannot create $output: $!"
unless $out;
- my $in = new Autom4te::XFile ($ocache . $req->id);
+ my $in = new Autom4te::XFile ("< " . $ocache . $req->id);
my %prohibited;
my $res;
@@ -594,7 +590,7 @@ sub handle_output ($$)
if ($ARGV[$#ARGV] ne '-')
{
my $prohibited = '\b(' . join ('|', keys %prohibited) . ')\b';
- my $file = new Autom4te::XFile ($ARGV[$#ARGV]);
+ my $file = new Autom4te::XFile ("< " . $ARGV[$#ARGV]);
while ($_ = $file->getline)
{
@@ -712,7 +708,7 @@ sub handle_traces ($$%)
verb "formatting traces for `$output': " . join (', ', sort keys %trace);
# Processing the traces.
- my $trace_m4 = new Autom4te::XFile (">$tmp/traces.m4");
+ my $trace_m4 = new Autom4te::XFile ("> $tmp/traces.m4");
$_ = <<'EOF';
divert(-1)
@@ -816,7 +812,7 @@ EOF
#
# Pay attention that the file name might include colons, if under DOS
# for instance, so we don't use `[^:]+'.
- my $traces = new Autom4te::XFile ($tcache . $req->id);
+ my $traces = new Autom4te::XFile ("< " . $tcache . $req->id);
while ($_ = $traces->getline)
{
# Trace with arguments, as the example above. We don't try
@@ -831,8 +827,8 @@ EOF
}
$trace_m4->close;
- my $in = new Autom4te::XFile ("$m4 $tmp/traces.m4 |");
- my $out = new Autom4te::XFile (">$output");
+ my $in = new Autom4te::XFile ("$m4 " . shell_quote ("$tmp/traces.m4") . "
|");
+ my $out = new Autom4te::XFile ("> $output");
# This is dubious: should we really transform the quadrigraphs in
# traces? It might break balanced [ ] etc. in the output. The
@@ -892,7 +888,7 @@ sub up_to_date ($)
handle_traces ($req, "$tmp/dependencies",
('include' => '$1',
'm4_include' => '$1'));
- my $deps = new Autom4te::XFile ("$tmp/dependencies");
+ my $deps = new Autom4te::XFile ("< $tmp/dependencies");
while ($_ = $deps->getline)
{
chomp;
@@ -925,7 +921,7 @@ sub freeze ($)
# output but comments and empty lines.
my $result = xqx ("$m4"
. ' --fatal-warning'
- . join (' --include=', '', @include)
+ . join (' --include=', '', map { shell_quote ($_) }
@include)
. ' --define=divert'
. " " . files_to_options (@ARGV)
. ' </dev/null');
@@ -939,8 +935,8 @@ sub freeze ($)
# or an improper paren etc.
xsystem ("$m4"
. ' --fatal-warning'
- . join (' --include=', '', @include)
- . " --freeze-state=$output"
+ . join (' --include=', '', map { shell_quote ($_) } @include)
+ . " --freeze-state=" . shell_quote ($output)
. " " . files_to_options (@ARGV)
. ' </dev/null');
}
diff --git a/bin/autoreconf.in b/bin/autoreconf.in
index c964b03..e707446 100644
--- a/bin/autoreconf.in
+++ b/bin/autoreconf.in
@@ -182,10 +182,10 @@ sub parse_args ()
# Dispatch autoreconf's option to the tools.
# --include;
- $autoconf .= join (' --include=', '', @include);
- $autoconf .= join (' --prepend-include=', '', @prepend_include);
- $autoheader .= join (' --include=', '', @include);
- $autoheader .= join (' --prepend-include=', '', @prepend_include);
+ $autoconf .= join (' --include=', '', map { shell_quote ($_) } @include);
+ $autoconf .= join (' --prepend-include=', '', map { shell_quote ($_) }
@prepend_include);
+ $autoheader .= join (' --include=', '', map { shell_quote ($_) } @include);
+ $autoheader .= join (' --prepend-include=', '', map { shell_quote ($_) }
@prepend_include);
# --install and --symlink;
if ($install)
@@ -316,7 +316,7 @@ sub autoreconf_current_directory ()
my $uses_gettext;
if (-f $configure_ac)
{
- my $configure_ac_file = new Autom4te::XFile $configure_ac;
+ my $configure_ac_file = new Autom4te::XFile "< $configure_ac";
while ($_ = $configure_ac_file->getline)
{
s/#.*//;
diff --git a/bin/autoscan.in b/bin/autoscan.in
index 372a878..6165afe 100644
--- a/bin/autoscan.in
+++ b/bin/autoscan.in
@@ -166,7 +166,7 @@ sub init_tables ()
# instead of duplicating the code in lots of configure.ac files.
my $file = find_file ("autoscan/autoscan.list",
reverse (@prepend_include), @include);
- my $table = new Autom4te::XFile $file;
+ my $table = new Autom4te::XFile "< $file";
my $tables_are_consistent = 1;
while ($_ = $table->getline)
@@ -241,7 +241,7 @@ sub scan_c_file ($)
# Nonzero if in a multiline comment.
my $in_comment = 0;
- my $file = new Autom4te::XFile "<$file_name";
+ my $file = new Autom4te::XFile "< $file_name";
while ($_ = $file->getline)
{
@@ -307,7 +307,7 @@ sub scan_makefile ($)
my ($file_name) = @_;
push @makefiles, $File::Find::name;
- my $file = new Autom4te::XFile "<$file_name";
+ my $file = new Autom4te::XFile "< $file_name";
while ($_ = $file->getline)
{
@@ -349,7 +349,7 @@ sub scan_sh_file ($)
my ($file_name) = @_;
push @shfiles, $File::Find::name;
- my $file = new Autom4te::XFile "<$file_name";
+ my $file = new Autom4te::XFile "< $file_name";
while ($_ = $file->getline)
{
@@ -518,7 +518,7 @@ sub output ($)
my $configure_scan = shift;
my %unique_makefiles;
- my $file = new Autom4te::XFile ">$configure_scan";
+ my $file = new Autom4te::XFile "> $configure_scan";
print $file
("# -*- Autoconf -*-\n" .
@@ -587,7 +587,7 @@ sub check_configure_ac ($)
verb "running: $autoconf $trace_option $configure_ac";
my $traces =
- new Autom4te::XFile "$autoconf $trace_option $configure_ac|";
+ new Autom4te::XFile "$autoconf $trace_option $configure_ac |";
while ($_ = $traces->getline)
{
@@ -636,12 +636,12 @@ sub check_configure_ac ($)
## -------------- ##
parse_args;
-$log = new Autom4te::XFile ">$me.log";
+$log = new Autom4te::XFile "> $me.log";
$autoconf .= " --debug" if $debug;
$autoconf .= " --verbose" if $verbose;
-$autoconf .= join (' --include=', '', @include);
-$autoconf .= join (' --prepend-include=', '', @prepend_include);
+$autoconf .= join (' --include=', '', map { shell_quote ($_) } @include);
+$autoconf .= join (' --prepend-include=', '', map { shell_quote ($_) }
@prepend_include);
my $configure_ac = find_configure_ac;
init_tables;
diff --git a/bin/autoupdate.in b/bin/autoupdate.in
index d69211d..1aba71d 100644
--- a/bin/autoupdate.in
+++ b/bin/autoupdate.in
@@ -127,8 +127,8 @@ my (%ac_macros, %au_macros, %m4_builtins);
sub handle_autoconf_macros ()
{
# Get the builtins.
- xsystem ("echo dumpdef | $m4 2>$tmp/m4.defs >/dev/null");
- my $m4_defs = new Autom4te::XFile "$tmp/m4.defs";
+ xsystem ("echo dumpdef | $m4 2>" . shell_quote ("$tmp/m4.defs") . "
>/dev/null");
+ my $m4_defs = new Autom4te::XFile "< $tmp/m4.defs";
while ($_ = $m4_defs->getline)
{
$m4_builtins{$1} = 1
@@ -184,9 +184,9 @@ sub handle_autoconf_macros ()
# ac.m4 -- autoquoting definitions of the AC macros (M4sugar excluded).
# unac.m4 -- undefine the AC macros.
- my $ac_m4 = new Autom4te::XFile ">$tmp/ac.m4";
+ my $ac_m4 = new Autom4te::XFile "> $tmp/ac.m4";
print $ac_m4 "# ac.m4 -- autoquoting definitions of the AC macros.\n";
- my $unac_m4 = new Autom4te::XFile ">$tmp/unac.m4";
+ my $unac_m4 = new Autom4te::XFile "> $tmp/unac.m4";
print $unac_m4 "# unac.m4 -- undefine the AC macros.\n";
foreach (sort keys %ac_macros)
{
@@ -197,11 +197,11 @@ sub handle_autoconf_macros ()
# m4save.m4 -- save the m4 builtins.
# unm4.m4 -- disable the m4 builtins.
# m4.m4 -- enable the m4 builtins.
- my $m4save_m4 = new Autom4te::XFile ">$tmp/m4save.m4";
+ my $m4save_m4 = new Autom4te::XFile "> $tmp/m4save.m4";
print $m4save_m4 "# m4save.m4 -- save the m4 builtins.\n";
- my $unm4_m4 = new Autom4te::XFile ">$tmp/unm4.m4";
+ my $unm4_m4 = new Autom4te::XFile "> $tmp/unm4.m4";
print $unm4_m4 "# unm4.m4 -- disable the m4 builtins.\n";
- my $m4_m4 = new Autom4te::XFile ">$tmp/m4.m4";
+ my $m4_m4 = new Autom4te::XFile "> $tmp/m4.m4";
print $m4_m4 "# m4.m4 -- enable the m4 builtins.\n";
foreach (sort keys %m4_builtins)
{
@@ -220,8 +220,8 @@ parse_args;
$autoconf .= " --debug" if $debug;
$autoconf .= " --force" if $force;
$autoconf .= " --verbose" if $verbose;
-$autoconf .= join (' --include=', '', @include);
-$autoconf .= join (' --prepend-include=', '', @prepend_include);
+$autoconf .= join (' --include=', '', map { shell_quote ($_) } @include);
+$autoconf .= join (' --prepend-include=', '', map { shell_quote ($_) }
@prepend_include);
mktmpdir ('au');
handle_autoconf_macros;
@@ -233,7 +233,7 @@ my $au_changequote =
# au.m4 -- definitions the AU macros.
xsystem ("$autoconf --trace AU_DEFINE:'_au_defun(\@<:address@hidden@:>\@,
\@<:address@hidden@:>\@)' --melt /dev/null "
- . ">$tmp/au.m4");
+ . ">" . shell_quote ("$tmp/au.m4"));
@@ -247,7 +247,7 @@ foreach my $file (@ARGV)
if ($file eq '-')
{
$file = "$tmp/stdin";
- system "cat >$file";
+ system "cat >" . shell_quote ($file);
}
elsif (! -r "$file")
{
@@ -376,9 +376,9 @@ EOF
$input_m4 =~ s/\$file/$file/g;
# prepared input -- input, but reenables the quote before each AU macro.
- open INPUT_M4, ">$tmp/input.m4"
+ open INPUT_M4, "> $tmp/input.m4"
or error "cannot open: $!";
- open FILE, "<$file"
+ open FILE, "< $file"
or error "cannot open: $!";
print INPUT_M4 "$input_m4";
while (<FILE>)
@@ -392,10 +392,10 @@ EOF
or error "cannot close $tmp/input.m4: $!";
# Now ask m4 to perform the update.
- xsystem ("$m4 --include=$tmp"
- . join (' --include=', '', reverse (@prepend_include))
- . join (' --include=', '', @include)
- . " $tmp/input.m4 >$tmp/updated");
+ xsystem ("$m4 --include=" . shell_quote ($tmp)
+ . join (' --include=', '', map { shell_quote ($_) } reverse
(@prepend_include))
+ . join (' --include=', '', map { shell_quote ($_) } @include)
+ . " " . shell_quote ("$tmp/input.m4") . " > " . shell_quote
("$tmp/updated"));
update_file ("$tmp/updated",
"$file" eq "$tmp/stdin" ? '-' : "$file");
}
diff --git a/bin/ifnames.in b/bin/ifnames.in
index d7c36ba..9d937be 100644
--- a/bin/ifnames.in
+++ b/bin/ifnames.in
@@ -92,7 +92,7 @@ my %occurrence;
sub scan_file ($)
{
my ($file_name) = @_;
- my $file = new Autom4te::XFile ($file_name);
+ my $file = new Autom4te::XFile ("< $file_name");
while ($_ = $file->getline)
{
# Continuation lines.
diff --git a/lib/Autom4te/FileUtils.pm b/lib/Autom4te/FileUtils.pm
index 3c9c1ba..26ec04b 100644
--- a/lib/Autom4te/FileUtils.pm
+++ b/lib/Autom4te/FileUtils.pm
@@ -1,4 +1,4 @@
-# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# Copyright (C) 2003, 2004, 2005, 2006, 2007 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
@@ -139,7 +139,7 @@ sub update_file ($$;$)
if ($to eq '-')
{
- my $in = new IO::File ("$from");
+ my $in = new IO::File ("< $from");
my $out = new IO::File (">-");
while ($_ = $in->getline)
{
diff --git a/lib/Autom4te/General.pm b/lib/Autom4te/General.pm
index b79467f..5639e4c 100644
--- a/lib/Autom4te/General.pm
+++ b/lib/Autom4te/General.pm
@@ -1,5 +1,6 @@
# autoconf -- create `configure' using m4 macros
-# Copyright (C) 2001, 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2002, 2003, 2004, 2006, 2007 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
@@ -53,7 +54,7 @@ my @export_vars =
# Functions we define and export.
my @export_subs =
qw (&debug
- &getopt &mktmpdir
+ &getopt &shell_quote &mktmpdir
&uniq);
# Functions we forward (coming from modules we use).
@@ -281,6 +282,31 @@ sub getopt (%)
}
+=item C<shell_quote ($file_name)>
+
+Quote C<$file_name> for the shell.
+
+=cut
+
+# $FILE_NAME
+# shell_quote ($FILE_NAME)
+# ------------------------
+# If the string $S is a well-behaved file name, simply return it.
+# If it contains white space, quotes, etc., quote it, and return
+# the new string.
+sub shell_quote($)
+{
+ my ($s) = @_;
+ if ($s =~ m![^\w+/.,-]!)
+ {
+ # Convert each single quote to '\''
+ $s =~ s/\'/\'\\\'\'/g;
+ # Then single quote the string.
+ $s = "'$s'";
+ }
+ return $s;
+}
+
=item C<mktmpdir ($signature)>
Create a temporary directory which name is based on C<$signature>.
@@ -295,10 +321,11 @@ 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 "$TMPDIR/${signature}XXXXXX") 2>/dev/null`;
+ mktemp -d $quoted_tmpdir/"${signature}XXXXXX") 2>/dev/null`;
chomp $tmp;
if (!$tmp || ! -d $tmp)
diff --git a/tests/tools.at b/tests/tools.at
index 4096d9e..e06ee82 100644
--- a/tests/tools.at
+++ b/tests/tools.at
@@ -138,23 +138,46 @@ AT_CHECK([cat file], 0,
AT_CLEANUP
-# autom4te and file names containing white space
-# ----------------------------------------------
+# autom4te and file names containing whitespace
+# ---------------------------------------------
-AT_SETUP([autom4te and white space in file names])
+AT_SETUP([autom4te and whitespace in file names])
+
+file='>file with funny \ '\'' \'\'' $ & #!*? name'
+dir='>dir with funny \ '\'' \'\'' $ & #!*? name'
+cachedir=">cache$dir"
+TMPDIR=">tmp$dir"
+export TMPDIR
-file='file with funny \ '\'' \'\'' $ & #!*? name'
cat >"$file.m4" <<'END'
-right
+[m4@&address@hidden(foo.m4)
+m4@&address@hidden(0)d@&address@hidden
+FOO]
+END
+# skip if we cannot create such a file or directory
+AT_CHECK([mkdir "$dir" "$cachedir" "$TMPDIR" && test -f "$file.m4" || exit 77])
+cat >"$dir"/foo.m4 <<'END'
+[m4@&address@hidden([FOO], [bar])]
END
-# skip if we cannot create such a file
-AT_CHECK([test -f "$file.m4" || exit 77])
-AT_CHECK_AUTOM4TE([-o "$file" "$file.m4"])
+AT_CHECK_AUTOM4TE([-C "$cachedir" -B "$dir" --language=m4sugar -o "$file"
"$file.m4"])
AT_CHECK([cat "$file"], [],
-[[right
+[[bar
+]])
+AT_CHECK_AUTOM4TE([-C "$cachedir" -I "$dir" --language=m4sugar -o "$file"
"$file.m4"])
+AT_CHECK([cat "$file"], [],
+[[bar
]])
+cat >"$file.m4" <<'END'
+[m4@&address@hidden(foo.m4)
+m4@&address@hidden(0)d@&address@hidden
+END
+AT_CHECK_AUTOM4TE([-C "$cachedir" -I "$dir" --language=m4sugar --freeze -o
"$file.m4f" "$file.m4"])
+AT_CHECK([test -s "$file.m4f"])
+
+# Check --reload-state
+AT_CHECK_AUTOM4TE([-C "$cachedir" --language=m4sugar -o "$file" "$file.m4f"
/dev/null])
AT_CLEANUP
@@ -925,3 +948,53 @@ AT_CHECK([test "`find configure -newer newer`" = "" ||
{ diff old-requests autom4te.cache/requests; exit 1; }])
AT_CLEANUP
+
+
+# autotools and file names containing whitespace
+# ---------------------------------------------
+
+AT_SETUP([autotools and whitespace in file names])
+
+file='>configure with funny \ '\'' \'\'' $ & #!*? name'
+dir='>dir with funny \ '\'' \'\'' $ & #!*? name'
+TMPDIR=">tmp$dir"
+export TMPDIR
+
+cat >"$file.in" <<'END'
+[AC_INIT(x,0)
+m4@&address@hidden([foo.m4])
+AC_CONFIG_HEADERS([config.h:config.hin])
+AC_MACRO
+AC_OUTPUT]
+END
+# skip if we cannot create such a file or directory
+AT_CHECK([mkdir "$dir" "$TMPDIR" && test -f "$file.in" || exit 77])
+cat >"$dir"/foo.m4 <<'END'
+[AC_DEFUN([AC_MACRO], [echo hi])]
+END
+
+AT_CHECK_AUTOHEADER([-B "$dir" "$file.in"])
+AT_CHECK_AUTOHEADER([-I "$dir" "$file.in"])
+AT_CHECK_AUTOUPDATE([-B "$dir" "$file.in"])
+AT_CHECK_AUTOUPDATE([-I "$dir" "$file.in"])
+AT_CHECK_AUTOUPDATE([-B "$dir" - < "$file.in"], [], [ignore])
+AT_CHECK_AUTOCONF([-B "$dir" -o "$file" "$file.in"])
+AT_CHECK_AUTOCONF([-I "$dir" -o "$file" "$file.in"])
+# In autoconf, these exercise a slightly different code path:
+AT_CHECK_AUTOCONF([--prepend-include="$dir" -o "$file" "$file.in"])
+AT_CHECK_AUTOCONF([--include="$dir" -o "$file" "$file.in"])
+AT_CHECK([autoscan -B "$dir"])
+AT_CHECK([autoscan -I "$dir"])
+# autoreconf requires a sane input file name. Also, disable aclocal.
+mv -f "$file.in" configure.in
+AT_DATA([aclocal.m4])
+AT_CHECK([autoreconf -B "$dir"])
+AT_CHECK([autoreconf -I "$dir"])
+
+cat >"$file.c" <<'END'
+#if FOO
+#endif
+END
+AT_CHECK([ifnames "$file.c"], [], [ignore])
+
+AT_CLEANUP
--
1.5.3.6.950.g92b7b
- [PATCH 0/10] Whitespace robustness patch series, Ralf Wildenhues, 2007/12/04
- [PATCH 1/10] Proper file name escaping in Autoconf programs and Perl modules.,
Ralf Wildenhues <=
- Re: [PATCH 1/10] Proper file name escaping in Autoconf programs and Perl modules., Russ Allbery, 2007/12/04
- Re: [PATCH 1/10] Proper file name escaping in Autoconf programs and Perl modules., Paul Eggert, 2007/12/04
- Re: [PATCH 1/10] Proper file name escaping in Autoconf programs and Perl modules., Eric Blake, 2007/12/05
- Re: [PATCH 1/10] Proper file name escaping in Autoconf programs and Perl modules., Ralf Wildenhues, 2007/12/06
- Re: [PATCH 1/10] Proper file name escaping in Autoconf programs and Perl modules., Eric Blake, 2007/12/12
- Re: [PATCH 1/10] Proper file name escaping in Autoconf programs and Perl modules., Ralf Wildenhues, 2007/12/13
[PATCH 2/10] * lib/autom4te.in: Quote @address@hidden, Ralf Wildenhues, 2007/12/04