diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c
index bf0f233118b1..156599f6f9d4 100644
--- a/sapi/cgi/cgi_main.c
+++ b/sapi/cgi/cgi_main.c
@@ -2372,6 +2372,7 @@ consult the installation file that came with this distribution, or visit \n\
}
}
+do_repeat:
if (script_file) {
/* override path_translated if -f on command line */
if (SG(request_info).path_translated) efree(SG(request_info).path_translated);
@@ -2512,7 +2513,6 @@ consult the installation file that came with this distribution, or visit \n\
PG(during_request_startup) = 0;
if (php_lint_script(&file_handle) == SUCCESS) {
zend_printf("No syntax errors detected in %s\n", ZSTR_VAL(file_handle.filename));
- exit_status = 0;
} else {
zend_printf("Errors parsing %s\n", ZSTR_VAL(file_handle.filename));
exit_status = -1;
@@ -2581,6 +2581,11 @@ consult the installation file that came with this distribution, or visit \n\
}
}
}
+ if (behavior == PHP_MODE_LINT && argc - 1 > php_optind) {
+ php_optind++;
+ script_file = NULL;
+ goto do_repeat;
+ }
break;
}
diff --git a/sapi/cgi/tests/012.phpt b/sapi/cgi/tests/012.phpt
new file mode 100644
index 000000000000..7f981b7da8d0
--- /dev/null
+++ b/sapi/cgi/tests/012.phpt
@@ -0,0 +1,117 @@
+--TEST--
+multiple files syntax check
+--SKIPIF--
+
+--INI--
+display_errors=stdout
+--FILE--
+/dev/null";
+ }
+ exec($cmd, $output, $exit_code);
+ print_r($output);
+ // Normalize Windows vs Linux exit codes. On Windows exit code -1 is actually -1 instead of 255.
+ if ($exit_code < 0) {
+ $exit_code += 256;
+ }
+ var_dump($exit_code);
+}
+
+$php = get_cgi_path();
+reset_env_vars();
+
+$filename_good = __DIR__."/012_good.test.php";
+$filename_good_escaped = escapeshellarg($filename_good);
+$filename_bad = __DIR__."/012_bad.test.php";
+$filename_bad_escaped = escapeshellarg($filename_bad);
+
+$code = '
+
+';
+
+file_put_contents($filename_bad, $code);
+
+run_and_output("$php -n -l $filename_good_escaped $filename_good_escaped");
+run_and_output("$php -n -l $filename_good_escaped some.unknown $filename_good_escaped");
+run_and_output("$php -n -l $filename_good_escaped $filename_bad_escaped $filename_good_escaped");
+run_and_output("$php -n -l $filename_bad_escaped $filename_bad_escaped");
+run_and_output("$php -n -l $filename_bad_escaped some.unknown $filename_bad_escaped");
+run_and_output("$php -n -l $filename_bad_escaped $filename_bad_escaped some.unknown");
+
+echo "Done\n";
+?>
+--CLEAN--
+
+--EXPECTF--
+Array
+(
+ [0] => No syntax errors detected in %s012_good.test.php
+ [1] => No syntax errors detected in %s012_good.test.php
+)
+int(0)
+Array
+(
+ [0] => No syntax errors detected in %s012_good.test.php
+ [1] => No input file specified.
+)
+int(255)
+Array
+(
+ [0] => No syntax errors detected in %s012_good.test.php
+ [1] =>
+ [2] => Parse error: syntax error, unexpected token "private", expecting "{" in %s012_bad.test.php on line 5
+ [3] => Errors parsing %s012_bad.test.php
+ [4] => No syntax errors detected in %s012_good.test.php
+)
+int(255)
+Array
+(
+ [0] =>
+ [1] => Parse error: syntax error, unexpected token "private", expecting "{" in %s012_bad.test.php on line 5
+ [2] => Errors parsing %s012_bad.test.php
+ [3] =>
+ [4] => Parse error: syntax error, unexpected token "private", expecting "{" in %s012_bad.test.php on line 5
+ [5] => Errors parsing %s012_bad.test.php
+)
+int(255)
+Array
+(
+ [0] =>
+ [1] => Parse error: syntax error, unexpected token "private", expecting "{" in %s012_bad.test.php on line 5
+ [2] => Errors parsing %s012_bad.test.php
+ [3] => No input file specified.
+)
+int(255)
+Array
+(
+ [0] =>
+ [1] => Parse error: syntax error, unexpected token "private", expecting "{" in %s012_bad.test.php on line 5
+ [2] => Errors parsing %s012_bad.test.php
+ [3] =>
+ [4] => Parse error: syntax error, unexpected token "private", expecting "{" in %s012_bad.test.php on line 5
+ [5] => Errors parsing %s012_bad.test.php
+ [6] => No input file specified.
+)
+int(255)
+Done
diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c
index c35980030585..546c4ba997dc 100644
--- a/sapi/cli/php_cli.c
+++ b/sapi/cli/php_cli.c
@@ -734,6 +734,10 @@ static int do_cli(int argc, char **argv) /* {{{ */
break;
}
behavior=PHP_MODE_LINT;
+ /* We want to set the error exit status if at least one lint failed.
+ * If all were successful we set the exit status to 0.
+ * We already set EG(exit_status) here such that only failures set the exit status. */
+ EG(exit_status) = 0;
break;
case 'q': /* do not generate HTTP headers */
@@ -962,7 +966,6 @@ static int do_cli(int argc, char **argv) /* {{{ */
case PHP_MODE_LINT:
if (php_lint_script(&file_handle) == SUCCESS) {
zend_printf("No syntax errors detected in %s\n", php_self);
- EG(exit_status) = 0;
} else {
zend_printf("Errors parsing %s\n", php_self);
EG(exit_status) = 255;
@@ -1128,9 +1131,15 @@ static int do_cli(int argc, char **argv) /* {{{ */
}
if (request_started) {
php_request_shutdown((void *) 0);
+ request_started = 0;
}
if (translated_path) {
free(translated_path);
+ translated_path = NULL;
+ }
+ if (behavior == PHP_MODE_LINT && argc > php_optind && strcmp(argv[php_optind],"--")) {
+ script_file = NULL;
+ goto do_repeat;
}
/* Don't repeat fork()ed processes. */
if (--num_repeats && pid == getpid()) {
diff --git a/sapi/cli/tests/024.phpt b/sapi/cli/tests/024.phpt
new file mode 100644
index 000000000000..bfd24679fd3c
--- /dev/null
+++ b/sapi/cli/tests/024.phpt
@@ -0,0 +1,110 @@
+--TEST--
+multiple files syntax check
+--SKIPIF--
+
+--FILE--
+
+';
+
+file_put_contents($filename_bad, $code);
+
+run_and_output("$php -n -l $filename_good_escaped $filename_good_escaped 2>&1");
+run_and_output("$php -n -l $filename_good_escaped some.unknown $filename_good_escaped 2>&1");
+run_and_output("$php -n -l $filename_good_escaped $filename_bad_escaped $filename_good_escaped 2>&1");
+run_and_output("$php -n -l $filename_bad_escaped $filename_bad_escaped 2>&1");
+run_and_output("$php -n -l $filename_bad_escaped some.unknown $filename_bad_escaped 2>&1");
+run_and_output("$php -n -l $filename_bad_escaped $filename_bad_escaped some.unknown 2>&1");
+
+echo "Done\n";
+?>
+--CLEAN--
+
+--EXPECTF--
+Array
+(
+ [0] => No syntax errors detected in %s024_good.test.php
+ [1] => No syntax errors detected in %s024_good.test.php
+)
+int(0)
+Array
+(
+ [0] => No syntax errors detected in %s024_good.test.php
+ [1] => Could not open input file: some.unknown
+ [2] => No syntax errors detected in %s024_good.test.php
+)
+int(1)
+Array
+(
+ [0] => No syntax errors detected in %s024_good.test.php
+ [1] =>
+ [2] => Parse error: syntax error, unexpected token "private", expecting "{" in %s on line %d
+ [3] => Errors parsing %s024_bad.test.php
+ [4] => No syntax errors detected in %s024_good.test.php
+)
+int(255)
+Array
+(
+ [0] =>
+ [1] => Parse error: syntax error, unexpected token "private", expecting "{" in %s on line %d
+ [2] => Errors parsing %s024_bad.test.php
+ [3] =>
+ [4] => Parse error: syntax error, unexpected token "private", expecting "{" in %s on line %d
+ [5] => Errors parsing %s024_bad.test.php
+)
+int(255)
+Array
+(
+ [0] =>
+ [1] => Parse error: syntax error, unexpected token "private", expecting "{" in %s on line %d
+ [2] => Errors parsing %s024_bad.test.php
+ [3] => Could not open input file: some.unknown
+ [4] =>
+ [5] => Parse error: syntax error, unexpected token "private", expecting "{" in %s on line %d
+ [6] => Errors parsing %s024_bad.test.php
+)
+int(255)
+Array
+(
+ [0] =>
+ [1] => Parse error: syntax error, unexpected token "private", expecting "{" in %s on line %d
+ [2] => Errors parsing %s024_bad.test.php
+ [3] =>
+ [4] => Parse error: syntax error, unexpected token "private", expecting "{" in %s on line %d
+ [5] => Errors parsing %s024_bad.test.php
+ [6] => Could not open input file: some.unknown
+)
+int(1)
+Done