[SV 27374] Fatal immediately on unrecoverable fopen() errors.

This commit is contained in:
Paul Smith 2013-09-15 16:41:42 -04:00
parent a4d8444b59
commit 1b90248893
6 changed files with 74 additions and 29 deletions

View File

@ -1,5 +1,9 @@
2013-09-15 Paul Smith <psmith@gnu.org> 2013-09-15 Paul Smith <psmith@gnu.org>
* read.c (eval_makefile): If the file open fails with an
unrecoverable error, stop now rather than trying to make it.
Fixes Savannah bug #27374.
* main.c (main): Perform the validation of the jobserver FDs * main.c (main): Perform the validation of the jobserver FDs
early, before we read makefiles, to ensure that something hasn't early, before we read makefiles, to ensure that something hasn't
opened and used those FDs for some other reason. opened and used those FDs for some other reason.

16
read.c
View File

@ -353,10 +353,24 @@ eval_makefile (const char *filename, int flags)
filename = expanded; filename = expanded;
} }
ebuf.fp = fopen (filename, "r"); ENULLLOOP (ebuf.fp, fopen (filename, "r"));
/* Save the error code so we print the right message later. */ /* Save the error code so we print the right message later. */
makefile_errno = errno; makefile_errno = errno;
/* Check for unrecoverable errors: out of mem or FILE slots. */
switch (makefile_errno)
{
#ifdef EMFILE
case EMFILE:
#endif
#ifdef ENFILE
case ENFILE:
#endif
case ENOMEM:
fatal (reading_file, "%s", strerror (makefile_errno));
}
/* If the makefile wasn't found and it's either a makefile from /* If the makefile wasn't found and it's either a makefile from
the 'MAKEFILES' variable or an included makefile, the 'MAKEFILES' variable or an included makefile,
search the included makefile search path for this makefile. */ search the included makefile search path for this makefile. */

View File

@ -1,5 +1,12 @@
2013-09-15 Paul Smith <psmith@gnu.org> 2013-09-15 Paul Smith <psmith@gnu.org>
* scripts/misc/fopen-fail: Check for failure on infinite recursion.
* run_make_tests.pl (run_make_test): Allow the answer string to be
undef, which means that we shouldn't compare it at all. Only the
exit code matters in this case.
* test_driver.pl (compare_output): Ditto.
Test for Savannah bug #27374.
* scripts/features/parallelism: Test broken jobserver on recursion. * scripts/features/parallelism: Test broken jobserver on recursion.
Test for Savannah bug #39934. Test for Savannah bug #39934.

View File

@ -148,8 +148,10 @@ sub run_make_test
} }
# Do the same processing on $answer as we did on $makestring. # Do the same processing on $answer as we did on $makestring.
$answer && $answer !~ /\n$/s and $answer .= "\n"; if (defined $answer) {
$answer = subst_make_string($answer); $answer && $answer !~ /\n$/s and $answer .= "\n";
$answer = subst_make_string($answer);
}
run_make_with_options($makefile, $options, &get_logfile(0), run_make_with_options($makefile, $options, &get_logfile(0),
$err_code, $timeout); $err_code, $timeout);

View File

@ -0,0 +1,15 @@
# -*-perl-*-
$description = "Make sure make exits with an error if fopen fails.";
# Recurse infinitely until we run out of open files, and ensure we
# fail with a non-zero exit code. Don't bother to test the output
# since it's hard to know what it will be, exactly.
# See Savannah bug #27374.
run_make_test(q!
include $(lastword $(MAKEFILE_LIST))
!,
'', undef, 512);
1;

View File

@ -653,38 +653,43 @@ sub compare_output
local($answer,$logfile) = @_; local($answer,$logfile) = @_;
local($slurp, $answer_matched) = ('', 0); local($slurp, $answer_matched) = ('', 0);
print "Comparing Output ........ " if $debug;
$slurp = &read_file_into_string ($logfile);
# For make, get rid of any time skew error before comparing--too bad this
# has to go into the "generic" driver code :-/
$slurp =~ s/^.*modification time .*in the future.*\n//gm;
$slurp =~ s/^.*Clock skew detected.*\n//gm;
++$tests_run; ++$tests_run;
if ($slurp eq $answer) { if (! defined $answer) {
$answer_matched = 1; print "Ignoring output ........ " if $debug;
$answer_matched = 1;
} else { } else {
# See if it is a slash or CRLF problem print "Comparing Output ........ " if $debug;
local ($answer_mod, $slurp_mod) = ($answer, $slurp);
$answer_mod =~ tr,\\,/,; $slurp = &read_file_into_string ($logfile);
$answer_mod =~ s,\r\n,\n,gs;
$slurp_mod =~ tr,\\,/,; # For make, get rid of any time skew error before comparing--too bad this
$slurp_mod =~ s,\r\n,\n,gs; # has to go into the "generic" driver code :-/
$slurp =~ s/^.*modification time .*in the future.*\n//gm;
$slurp =~ s/^.*Clock skew detected.*\n//gm;
$answer_matched = ($slurp_mod eq $answer_mod); if ($slurp eq $answer) {
$answer_matched = 1;
} else {
# See if it is a slash or CRLF problem
local ($answer_mod, $slurp_mod) = ($answer, $slurp);
# If it still doesn't match, see if the answer might be a regex. $answer_mod =~ tr,\\,/,;
if (!$answer_matched && $answer =~ m,^/(.+)/$,) { $answer_mod =~ s,\r\n,\n,gs;
$answer_matched = ($slurp =~ /$1/);
if (!$answer_matched && $answer_mod =~ m,^/(.+)/$,) { $slurp_mod =~ tr,\\,/,;
$answer_matched = ($slurp_mod =~ /$1/); $slurp_mod =~ s,\r\n,\n,gs;
$answer_matched = ($slurp_mod eq $answer_mod);
# If it still doesn't match, see if the answer might be a regex.
if (!$answer_matched && $answer =~ m,^/(.+)/$,) {
$answer_matched = ($slurp =~ /$1/);
if (!$answer_matched && $answer_mod =~ m,^/(.+)/$,) {
$answer_matched = ($slurp_mod =~ /$1/);
}
}
} }
}
} }
if ($answer_matched && $test_passed) if ($answer_matched && $test_passed)
@ -706,8 +711,6 @@ sub compare_output
local($command) = "diff -c " . &get_basefile . " " . $logfile; local($command) = "diff -c " . &get_basefile . " " . $logfile;
&run_command_with_output(&get_difffile,$command); &run_command_with_output(&get_difffile,$command);
} else {
&rmfiles ();
} }
$suite_passed = 0; $suite_passed = 0;