This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 17234c387e398c05cbb5158475e2ef9d4258e380 Author: opencode <[email protected]> AuthorDate: Sun Oct 18 20:47:18 2026 +0200 Fix jspc handling of the full stop (--) argument The full stop argument was never advanced past by nextArg(), while nextFile() incremented the argument position on every call when the full stop had been seen. The net result was that every second file argument after '--' was silently skipped, e.g. 'jspc -- a.jsp b.jsp c.jsp' only processed a.jsp and c.jsp. nextArg() now consumes the full stop argument exactly once and nextFile() no longer manipulates the argument position, so all remaining arguments are collected as files. In addition, the rewind for the first non-option argument is now unconditional, and option parsing stops whenever the full stop argument is consumed, including when it appears in an option value position, so that option-like arguments after '--' are treated as files. As a side effect, the previously possible infinite loop caused by a full stop argument directly after -trimSpaces no longer occurs. Add regression tests for the full stop argument handling to TestJspC. --- java/org/apache/jasper/JspC.java | 39 +++++++++++++++++++++------------- test/org/apache/jasper/TestJspC.java | 41 ++++++++++++++++++++++++++++++++++++ webapps/docs/changelog.xml | 12 +++++++++++ 3 files changed, 77 insertions(+), 15 deletions(-) diff --git a/java/org/apache/jasper/JspC.java b/java/org/apache/jasper/JspC.java index f467db4294..babd616246 100644 --- a/java/org/apache/jasper/JspC.java +++ b/java/org/apache/jasper/JspC.java @@ -502,12 +502,16 @@ public class JspC extends Task implements Options { if (tok.startsWith("-")) { throw new JasperException(Localizer.getMessage("jspc.error.unknownOption", tok)); } - if (!fullstop) { - argPos--; - } + // Re-process this argument as a JSP page + argPos--; // Start treating the rest as JSP Pages break; } + if (fullstop) { + // A full stop argument encountered while reading an option + // value also stops option parsing + break; + } } // Add all extra arguments to the list of files @@ -1642,32 +1646,37 @@ public class JspC extends Task implements Options { // ==================== protected utility methods ==================== /** - * Returns the next command-line argument. + * Returns the next command-line argument. Option parsing stops when the + * full stop argument {@code --} is encountered. The full stop argument is + * consumed and is never returned. * - * @return the next argument, or {@code null} if no more arguments + * @return the next argument, or {@code null} if no more arguments are + * available or the full stop argument was reached */ protected String nextArg() { - if ((argPos >= args.length) || (fullstop = SWITCH_FULL_STOP.equals(args[argPos]))) { + if (argPos >= args.length) { return null; - } else { - return args[argPos++]; } + if (SWITCH_FULL_STOP.equals(args[argPos])) { + fullstop = true; + argPos++; + return null; + } + return args[argPos++]; } /** - * Returns the next file argument from the command-line. + * Returns the next file argument from the command-line. All remaining + * arguments are treated as files once option parsing has stopped. * - * @return the next file argument, or {@code null} if no more arguments + * @return the next file argument, or {@code null} if no more arguments are + * available */ protected String nextFile() { - if (fullstop) { - argPos++; - } if (argPos >= args.length) { return null; - } else { - return args[argPos++]; } + return args[argPos++]; } /** diff --git a/test/org/apache/jasper/TestJspC.java b/test/org/apache/jasper/TestJspC.java index da1f96fdee..a2577c1284 100644 --- a/test/org/apache/jasper/TestJspC.java +++ b/test/org/apache/jasper/TestJspC.java @@ -125,6 +125,47 @@ public class TestJspC { verify(webappOut); } + @Test + public void argsNoFullStop() throws Exception { + jspc.setArgs(new String[] {"a.jsp", "b.jsp"}); + Assert.assertEquals(List.of("a.jsp", "b.jsp"), jspc.pages); + } + + @Test + public void argsFullStop() throws Exception { + jspc.setArgs(new String[] {"--", "a.jsp", "b.jsp", "c.jsp"}); + Assert.assertEquals(List.of("a.jsp", "b.jsp", "c.jsp"), jspc.pages); + } + + @Test + public void argsFullStopAfterOptions() throws Exception { + jspc.setArgs(new String[] {"-compile", "--", "a.jsp", "b.jsp"}); + Assert.assertTrue(jspc.compile); + Assert.assertEquals(List.of("a.jsp", "b.jsp"), jspc.pages); + } + + @Test + public void argsFullStopFileStartingWithDash() throws Exception { + jspc.setArgs(new String[] {"--", "-a.jsp", "b.jsp"}); + Assert.assertEquals(List.of("-a.jsp", "b.jsp"), jspc.pages); + } + + @Test + public void argsFullStopAsOptionValue() throws Exception { + // The full stop argument takes the place of the missing option value + // and must not cause the first file argument to be dropped + jspc.setArgs(new String[] {"-d", "--", "a.jsp", "b.jsp"}); + Assert.assertEquals(List.of("a.jsp", "b.jsp"), jspc.pages); + } + + @Test + public void argsFullStopInOptionValuePositionStopsOptionParsing() + throws Exception { + jspc.setArgs(new String[] {"-cache", "--", "-compile", "a.jsp"}); + Assert.assertFalse(jspc.compile); + Assert.assertEquals(List.of("-compile", "a.jsp"), jspc.pages); + } + @Test public void servletContextUsesAntLog() throws Exception { List<String> messages = new ArrayList<>(); diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 618b8a2ac0..4575af986d 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -401,6 +401,18 @@ </fix> </changelog> </subsection> + <subsection name="Jasper"> + <changelog> + <fix> + Correct the handling of the <code>--</code> argument by + <code>jspc</code>. The argument position was advanced past the full + stop argument on each iteration while collecting the JSP file + arguments, so every second file argument after <code>--</code> was + silently omitted from processing. Option parsing now stops at the + first full stop argument wherever it appears. (remm) + </fix> + </changelog> + </subsection> <subsection name="WebSocket"> <changelog> <fix> --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
