This is an automated email from the ASF dual-hosted git repository.

rmaucher pushed a commit to branch 11.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 79e8d06f4c6abfa787c823e3fa968c93cab2ed40
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 | 49 ++++++++++++++++++++++++++++++++++++
 webapps/docs/changelog.xml           | 12 +++++++++
 3 files changed, 85 insertions(+), 15 deletions(-)

diff --git a/java/org/apache/jasper/JspC.java b/java/org/apache/jasper/JspC.java
index 0740215348..028a3acd71 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 3c595ffce1..611cf11b55 100644
--- a/test/org/apache/jasper/TestJspC.java
+++ b/test/org/apache/jasper/TestJspC.java
@@ -133,6 +133,55 @@ public class TestJspC {
         verify(webappOut);
     }
 
+    @Test
+    public void precompileWebapp_6_2() throws IOException {
+        File appDir = new File("test/webapp-6.2");
+        File webappOut = new File(outputDir, appDir.getName());
+        precompile(appDir, webappOut);
+        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 657c876c16..f5056106ad 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]

Reply via email to