You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2026/10/19 21:17:02 UTC
(tomcat) 08/46: Fix the jsp:attribute trim loop skipping nodes after removal
This is an automated email from the ASF dual-hosted git repository.
rmaucher pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 35936f7aee362625f3b0b6b4c9058654a5390129
Author: opencode <re...@apache.org>
AuthorDate: Sun Oct 18 22:16:49 2026 +0200
Fix the jsp:attribute trim loop skipping nodes after removal
When removing white-space only template text nodes from the body of a
jsp:attribute action while parsing a JSP document, the loop in
JspDocumentParser.endElement() did not re-examine the node that was
shifted into the vacated position after a removal.
Adjacent template text siblings occur in practice when the attribute
body contains CDATA sections, because the startCDATA/endCDATA handling
flushes the buffered characters into a template text node without
creating a separating node. For such bodies the skipped node could be a
second white-space only text node that then remained in the body, or the
final text node which consequently was not trimmed when trim was true.
Re-examine the shifted node after each removal so every text node
receives the treatment required by the specification. Add a regression
test using CDATA sections in jsp:attribute bodies.
Found by code review.
---
.../apache/jasper/compiler/JspDocumentParser.java | 3 ++
.../jasper/compiler/TestJspDocumentParser.java | 23 ++++++++++++++
test/webapp/jsp/document/named-attribute-trim.jspx | 37 ++++++++++++++++++++++
webapps/docs/changelog.xml | 10 ++++++
4 files changed, 73 insertions(+)
diff --git a/java/org/apache/jasper/compiler/JspDocumentParser.java b/java/org/apache/jasper/compiler/JspDocumentParser.java
index a13079a59f..8c6f91b691 100644
--- a/java/org/apache/jasper/compiler/JspDocumentParser.java
+++ b/java/org/apache/jasper/compiler/JspDocumentParser.java
@@ -548,6 +548,9 @@ class JspDocumentParser extends DefaultHandler2 implements TagConstants {
} else {
if (((Node.TemplateText) subElem).isAllSpace()) {
subElems.remove(subElem);
+ // Re-examine the element that was shifted into this
+ // position by the removal above
+ i--;
}
}
}
diff --git a/test/org/apache/jasper/compiler/TestJspDocumentParser.java b/test/org/apache/jasper/compiler/TestJspDocumentParser.java
index 8eac2bf2c3..db377dbdbe 100644
--- a/test/org/apache/jasper/compiler/TestJspDocumentParser.java
+++ b/test/org/apache/jasper/compiler/TestJspDocumentParser.java
@@ -85,6 +85,29 @@ public class TestJspDocumentParser extends TomcatBaseTest {
Assert.assertEquals(HttpServletResponse.SC_OK, rc);
}
+ @Test
+ public void testNamedAttributeTrimCdata() throws Exception {
+ getTomcatInstanceTestWebapp(false, true);
+
+ ByteChunk bc = new ByteChunk();
+ int rc = getUrl("http://localhost:" + getPort() + "/test/jsp/document/named-attribute-trim.jspx", bc, null);
+
+ Assert.assertEquals(HttpServletResponse.SC_OK, rc);
+
+ String result = bc.toString();
+
+ // White-space only text nodes between the other body elements must be
+ // removed and the final text node must be trimmed
+ Assert.assertTrue(result, result.contains("<e1 a=\"x tail\"/>"));
+ Assert.assertTrue(result, result.contains("<e2 a=\"x\"/>"));
+ Assert.assertTrue(result, result.contains("<e3 a=\"xy\"/>"));
+ Assert.assertTrue(result, result.contains("<e4 a=\"x y\"/>"));
+ // With trim set to false, leading and trailing white-space only text
+ // nodes must be kept verbatim
+ Assert.assertTrue(result, result.contains("<t5 a=\" \"/>"));
+ Assert.assertTrue(result, result.contains("<t6 a=\"x tail \"/>"));
+ }
+
@Test
public void testSchemaValidation() throws Exception {
getTomcatInstanceTestWebapp(false, true);
diff --git a/test/webapp/jsp/document/named-attribute-trim.jspx b/test/webapp/jsp/document/named-attribute-trim.jspx
new file mode 100644
index 0000000000..5422dc524e
--- /dev/null
+++ b/test/webapp/jsp/document/named-attribute-trim.jspx
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">
+ <!--
+ Regression tests for the handling of adjacent template text nodes -
+ produced by CDATA sections - in the body of a jsp:attribute action.
+ Expected results are given in comments below. Each element name encodes
+ the trim setting: e* for trim="true" (the default), t* for trim="false".
+ -->
+ <!-- Middle white-space only node removed, trailing node trimmed: "x tail" -->
+ <jsp:element name="e1"><jsp:attribute name="a"><jsp:text>x</jsp:text><![CDATA[ ]]><![CDATA[ tail ]]></jsp:attribute></jsp:element>
+ <!-- Both consecutive white-space only middle nodes removed: "x" -->
+ <jsp:element name="e2"><jsp:attribute name="a"><jsp:text>x</jsp:text><![CDATA[ ]]><![CDATA[ ]]></jsp:attribute></jsp:element>
+ <!-- Second of two consecutive white-space only middle nodes removed: "xy" -->
+ <jsp:element name="e3"><jsp:attribute name="a"><jsp:text>x</jsp:text><![CDATA[ ]]><![CDATA[ ]]><jsp:text>y</jsp:text></jsp:attribute></jsp:element>
+ <!-- Single CDATA between text nodes, trailing node trimmed: "x y" -->
+ <jsp:element name="e4"><jsp:attribute name="a">x<![CDATA[ ]]> y </jsp:attribute></jsp:element>
+ <!-- Leading and trailing white-space only nodes kept verbatim: " " -->
+ <jsp:element name="t5"><jsp:attribute name="a" trim="false"><![CDATA[ ]]><![CDATA[ ]]></jsp:attribute></jsp:element>
+ <!-- Middle node removed, trailing node kept verbatim: "x tail " -->
+ <jsp:element name="t6"><jsp:attribute name="a" trim="false">x<![CDATA[ ]]><![CDATA[ tail ]]></jsp:attribute></jsp:element>
+</jsp:root>
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index ddd33abe01..30051b6b21 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -646,6 +646,16 @@
silently omitted from processing. Option parsing now stops at the
first full stop argument wherever it appears. (remm)
</fix>
+ <fix>
+ When removing white-space only template text nodes from the body of a
+ <code>jsp:attribute</code> action while parsing a JSP document, the
+ node that was shifted into the vacated position is now re-examined.
+ Previously it was skipped, which, for bodies containing adjacent
+ template text nodes such as those produced by CDATA sections, could
+ leave a white-space only text node in the body or prevent the final
+ text node from being trimmed when <code>trim</code> was
+ <code>true</code>. (remm)
+ </fix>
</changelog>
</subsection>
<subsection name="Cluster">
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org