You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2019/05/01 21:15:46 UTC

[tomcat] branch master updated: Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63359 jsp:setProperty

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

markt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/master by this push:
     new fb78a72  Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63359 jsp:setProperty
fb78a72 is described below

commit fb78a724c043953f221b7a04c492e1891ddc825e
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Wed May 1 22:14:36 2019 +0100

    Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63359 jsp:setProperty
    
    Ensure that the conversions from String are as per JSP.1.14.2.1.
    Specifically:
    - "on" is no longer converted to boolean true
    - "" is converted to 0 rather than triggering an error for numeric types
    - File is no longer a supported target type
    - If the target type is Object, a new String rather than a new String
      array is created
    - If a PropertyEditor is not available or an error occurs "" is
      converted to null rather than triggering an error
---
 .../apache/jasper/runtime/JspRuntimeLibrary.java   |  90 +++++---
 .../jasper/runtime/TestJspRuntimeLibrary.java      | 143 ++++++++++++
 test/org/apache/jasper/runtime/TesterBean.java     | 252 +++++++++++++++++++++
 test/org/apache/jasper/runtime/TesterTypeA.java    |  42 ++++
 .../apache/jasper/runtime/TesterTypeAEditor.java   |  30 +++
 test/org/apache/jasper/runtime/TesterTypeB.java    |  25 ++
 test/webapp/bug6nnnn/bug63359a.jsp                 | 202 +++++++++++++++++
 webapps/docs/changelog.xml                         |  10 +
 8 files changed, 765 insertions(+), 29 deletions(-)

diff --git a/java/org/apache/jasper/runtime/JspRuntimeLibrary.java b/java/org/apache/jasper/runtime/JspRuntimeLibrary.java
index e846229..a44c046 100644
--- a/java/org/apache/jasper/runtime/JspRuntimeLibrary.java
+++ b/java/org/apache/jasper/runtime/JspRuntimeLibrary.java
@@ -211,32 +211,54 @@ public class JspRuntimeLibrary {
             if (propertyEditorClass != null) {
                 return getValueFromBeanInfoPropertyEditor(
                                     t, propertyName, s, propertyEditorClass);
-            } else if ( t.equals(Boolean.class) || t.equals(Boolean.TYPE) ) {
-                if (s.equalsIgnoreCase("on") || s.equalsIgnoreCase("true"))
-                    s = "true";
-                else
-                    s = "false";
+            } else if (t.equals(Boolean.class) || t.equals(Boolean.TYPE)) {
                 return Boolean.valueOf(s);
-            } else if ( t.equals(Byte.class) || t.equals(Byte.TYPE) ) {
-                return Byte.valueOf(s);
+            } else if (t.equals(Byte.class) || t.equals(Byte.TYPE)) {
+                if (s.length() == 0) {
+                    return Byte.valueOf((byte)0);
+                } else {
+                    return Byte.valueOf(s);
+                }
             } else if (t.equals(Character.class) || t.equals(Character.TYPE)) {
-                return s.length() > 0 ? Character.valueOf(s.charAt(0)) : null;
-            } else if ( t.equals(Short.class) || t.equals(Short.TYPE) ) {
-                return Short.valueOf(s);
-            } else if ( t.equals(Integer.class) || t.equals(Integer.TYPE) ) {
-                return Integer.valueOf(s);
-            } else if ( t.equals(Float.class) || t.equals(Float.TYPE) ) {
-                return Float.valueOf(s);
-            } else if ( t.equals(Long.class) || t.equals(Long.TYPE) ) {
-                return Long.valueOf(s);
-            } else if ( t.equals(Double.class) || t.equals(Double.TYPE) ) {
-                return Double.valueOf(s);
+                if (s.length() == 0) {
+                    return Character.valueOf((char) 0);
+                } else {
+                    return Character.valueOf(s.charAt(0));
+                }
+            } else if (t.equals(Double.class) || t.equals(Double.TYPE)) {
+                if (s.length() == 0) {
+                    return Double.valueOf(0);
+                } else {
+                    return Double.valueOf(s);
+                }
+            } else if (t.equals(Integer.class) || t.equals(Integer.TYPE)) {
+                if (s.length() == 0) {
+                    return Integer.valueOf(0);
+                } else {
+                    return Integer.valueOf(s);
+                }
+            } else if (t.equals(Float.class) || t.equals(Float.TYPE)) {
+                if (s.length() == 0) {
+                    return Float.valueOf(0);
+                } else {
+                    return Float.valueOf(s);
+                }
+            } else if (t.equals(Long.class) || t.equals(Long.TYPE)) {
+                if (s.length() == 0) {
+                    return Long.valueOf(0);
+                } else {
+                    return Long.valueOf(s);
+                }
+            } else if (t.equals(Short.class) || t.equals(Short.TYPE)) {
+                if (s.length() == 0) {
+                    return Short.valueOf((short) 0);
+                } else {
+                    return Short.valueOf(s);
+                }
             } else if ( t.equals(String.class) ) {
                 return s;
-            } else if ( t.equals(java.io.File.class) ) {
-                return new java.io.File(s);
             } else if (t.getName().equals("java.lang.Object")) {
-                return new Object[] {s};
+                return new String(s);
             } else {
                 return getValueFromPropertyEditorManager(
                                             t, propertyName, s);
@@ -761,10 +783,14 @@ public class JspRuntimeLibrary {
             pe.setAsText(attrValue);
             return pe.getValue();
         } catch (Exception ex) {
-            throw new JasperException(
-                Localizer.getMessage("jsp.error.beans.property.conversion",
-                                     attrValue, attrClass.getName(), attrName,
-                                     ex.getMessage()));
+            if (attrValue.length() == 0) {
+                return null;
+            } else {
+                throw new JasperException(
+                    Localizer.getMessage("jsp.error.beans.property.conversion",
+                                         attrValue, attrClass.getName(), attrName,
+                                         ex.getMessage()));
+            }
         }
     }
 
@@ -778,15 +804,21 @@ public class JspRuntimeLibrary {
             if (propEditor != null) {
                 propEditor.setAsText(attrValue);
                 return propEditor.getValue();
+            } else if (attrValue.length() == 0) {
+                return null;
             } else {
                 throw new IllegalArgumentException(
                     Localizer.getMessage("jsp.error.beans.propertyeditor.notregistered"));
             }
         } catch (IllegalArgumentException ex) {
-            throw new JasperException(
-                Localizer.getMessage("jsp.error.beans.property.conversion",
-                                     attrValue, attrClass.getName(), attrName,
-                                     ex.getMessage()));
+            if (attrValue.length() == 0) {
+                return null;
+            } else {
+                throw new JasperException(
+                    Localizer.getMessage("jsp.error.beans.property.conversion",
+                                         attrValue, attrClass.getName(), attrName,
+                                         ex.getMessage()));
+            }
         }
     }
 
diff --git a/test/org/apache/jasper/runtime/TestJspRuntimeLibrary.java b/test/org/apache/jasper/runtime/TestJspRuntimeLibrary.java
new file mode 100644
index 0000000..5572df6
--- /dev/null
+++ b/test/org/apache/jasper/runtime/TestJspRuntimeLibrary.java
@@ -0,0 +1,143 @@
+/*
+* 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.
+*/
+package org.apache.jasper.runtime;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.tomcat.util.buf.ByteChunk;
+
+public class TestJspRuntimeLibrary extends TomcatBaseTest {
+
+    /*
+     * Tests successful conversions
+     */
+    @Test
+    public void testBug63359a() throws Exception {
+        getTomcatInstanceTestWebapp(false, true);
+
+        ByteChunk res = getUrl("http://localhost:" + getPort() + "/test/bug6nnnn/bug63359a.jsp");
+        String result = res.toString();
+
+        assertEcho(result, "01-false");
+        assertEcho(result, "02-false");
+        assertEcho(result, "03-true");
+        assertEcho(result, "04-true");
+        assertEcho(result, "05-false");
+
+        assertEcho(result, "11-false");
+        assertEcho(result, "12-false");
+        assertEcho(result, "13-true");
+        assertEcho(result, "14-true");
+        assertEcho(result, "15-false");
+
+        assertEcho(result, "21-0");
+        assertEcho(result, "22-42");
+        assertEcho(result, "23--42");
+        assertEcho(result, "24-42");
+
+        assertEcho(result, "31-0");
+        assertEcho(result, "32-42");
+        assertEcho(result, "33--42");
+        assertEcho(result, "34-42");
+
+        assertEcho(result, "41-\u0000");
+        assertEcho(result, "42-f");
+        assertEcho(result, "43-b");
+        assertEcho(result, "44-\n");
+
+        assertEcho(result, "51-\u0000");
+        assertEcho(result, "52-f");
+        assertEcho(result, "53-b");
+        assertEcho(result, "54-\n");
+
+        assertEcho(result, "61-0.0");
+        assertEcho(result, "62-42.0");
+        assertEcho(result, "63--42.0");
+        assertEcho(result, "64-42.0");
+
+        assertEcho(result, "71-0.0");
+        assertEcho(result, "72-42.0");
+        assertEcho(result, "73--42.0");
+        assertEcho(result, "74-42.0");
+
+        assertEcho(result, "81-0");
+        assertEcho(result, "82-42");
+        assertEcho(result, "83--42");
+        assertEcho(result, "84-42");
+
+        assertEcho(result, "91-0");
+        assertEcho(result, "92-42");
+        assertEcho(result, "93--42");
+        assertEcho(result, "94-42");
+
+        assertEcho(result, "101-0.0");
+        assertEcho(result, "102-42.0");
+        assertEcho(result, "103--42.0");
+        assertEcho(result, "104-42.0");
+
+        assertEcho(result, "111-0.0");
+        assertEcho(result, "112-42.0");
+        assertEcho(result, "113--42.0");
+        assertEcho(result, "114-42.0");
+
+        assertEcho(result, "121-0");
+        assertEcho(result, "122-42");
+        assertEcho(result, "123--42");
+        assertEcho(result, "124-42");
+
+        assertEcho(result, "131-0");
+        assertEcho(result, "132-42");
+        assertEcho(result, "133--42");
+        assertEcho(result, "134-42");
+
+        assertEcho(result, "141-0");
+        assertEcho(result, "142-42");
+        assertEcho(result, "143--42");
+        assertEcho(result, "144-42");
+
+        assertEcho(result, "151-0");
+        assertEcho(result, "152-42");
+        assertEcho(result, "153--42");
+        assertEcho(result, "154-42");
+
+        assertEcho(result, "161-");
+        assertEcho(result, "162-42");
+        assertEcho(result, "163--42");
+        assertEcho(result, "164-+42");
+
+        assertEcho(result, "171-");
+        assertEcho(result, "172-42");
+        assertEcho(result, "173--42");
+        assertEcho(result, "174-+42");
+
+        assertEcho(result, "181-");
+        assertEcho(result, "182-42");
+        assertEcho(result, "183--42");
+        assertEcho(result, "184-42");
+
+        // NB In EL null coerces to the empty String
+        assertEcho(result, "191-");
+    }
+
+
+    // Assertion for text contained with <p></p>, e.g. printed by tags:echo
+    private static void assertEcho(String result, String expected) {
+        Assert.assertTrue(result, result.indexOf("<p>" + expected + "</p>") > 0);
+    }
+}
diff --git a/test/org/apache/jasper/runtime/TesterBean.java b/test/org/apache/jasper/runtime/TesterBean.java
new file mode 100644
index 0000000..bb201c5
--- /dev/null
+++ b/test/org/apache/jasper/runtime/TesterBean.java
@@ -0,0 +1,252 @@
+/*
+* 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.
+*/
+package org.apache.jasper.runtime;
+
+public class TesterBean {
+
+    private boolean booleanPrimitive;
+    private Boolean booleanObject;
+
+    private byte bytePrimitive;
+    private Byte byteObject;
+
+    private char charPrimitive;
+    private Character charObject;
+
+    private double doublePrimitive;
+    private Double doubleObject;
+
+    private int intPrimitive;
+    private Integer intObject;
+
+    private float floatPrimitive;
+    private Float floatObject;
+
+    private long longPrimitive;
+    private Long longObject;
+
+    private short shortPrimitive;
+    private Short shortObject;
+
+    private String stringValue;
+
+    private Object objectValue;
+
+    private TesterTypeA testerTypeA;
+
+    private TesterTypeB testerTypeB;
+
+
+    public boolean getBooleanPrimitive() {
+        return booleanPrimitive;
+    }
+
+
+    public void setBooleanPrimitive(boolean booleanPrimitive) {
+        this.booleanPrimitive = booleanPrimitive;
+    }
+
+
+    public Boolean getBooleanObject() {
+        return booleanObject;
+    }
+
+
+    public void setBooleanObject(Boolean booleanObject) {
+        this.booleanObject = booleanObject;
+    }
+
+
+    public byte getBytePrimitive() {
+        return bytePrimitive;
+    }
+
+
+    public void setBytePrimitive(byte bytePrimitive) {
+        this.bytePrimitive = bytePrimitive;
+    }
+
+
+    public Byte getByteObject() {
+        return byteObject;
+    }
+
+
+    public void setByteObject(Byte byteObject) {
+        this.byteObject = byteObject;
+    }
+
+
+    public char getCharPrimitive() {
+        return charPrimitive;
+    }
+
+
+    public void setCharPrimitive(char charPrimitive) {
+        this.charPrimitive = charPrimitive;
+    }
+
+
+    public Character getCharObject() {
+        return charObject;
+    }
+
+
+    public void setCharObject(Character charObject) {
+        this.charObject = charObject;
+    }
+
+
+    public double getDoublePrimitive() {
+        return doublePrimitive;
+    }
+
+
+    public void setDoublePrimitive(double doublePrimitive) {
+        this.doublePrimitive = doublePrimitive;
+    }
+
+
+    public Double getDoubleObject() {
+        return doubleObject;
+    }
+
+
+    public void setDoubleObject(Double doubleObject) {
+        this.doubleObject = doubleObject;
+    }
+
+
+    public int getIntPrimitive() {
+        return intPrimitive;
+    }
+
+
+    public void setIntPrimitive(int intPrimitive) {
+        this.intPrimitive = intPrimitive;
+    }
+
+
+    public Integer getIntObject() {
+        return intObject;
+    }
+
+
+    public void setIntObject(Integer intObject) {
+        this.intObject = intObject;
+    }
+
+
+    public float getFloatPrimitive() {
+        return floatPrimitive;
+    }
+
+
+    public void setFloatPrimitive(float floatPrimitive) {
+        this.floatPrimitive = floatPrimitive;
+    }
+
+
+    public Float getFloatObject() {
+        return floatObject;
+    }
+
+
+    public void setFloatObject(Float floatObject) {
+        this.floatObject = floatObject;
+    }
+
+
+    public long getLongPrimitive() {
+        return longPrimitive;
+    }
+
+
+    public void setLongPrimitive(long longPrimitive) {
+        this.longPrimitive = longPrimitive;
+    }
+
+
+    public Long getLongObject() {
+        return longObject;
+    }
+
+
+    public void setLongObject(Long longObject) {
+        this.longObject = longObject;
+    }
+
+
+    public short getShortPrimitive() {
+        return shortPrimitive;
+    }
+
+
+    public void setShortPrimitive(short shortPrimitive) {
+        this.shortPrimitive = shortPrimitive;
+    }
+
+
+    public Short getShortObject() {
+        return shortObject;
+    }
+
+
+    public void setShortObject(Short shortObject) {
+        this.shortObject = shortObject;
+    }
+
+
+    public String getStringValue() {
+        return stringValue;
+    }
+
+
+    public void setStringValue(String stringValue) {
+        this.stringValue = stringValue;
+    }
+
+
+    public Object getObjectValue() {
+        return objectValue;
+    }
+
+
+    public void setObjectValue(Object objectValue) {
+        this.objectValue = objectValue;
+    }
+
+
+    public TesterTypeA getTesterTypeA() {
+        return testerTypeA;
+    }
+
+
+    public void setTesterTypeA(TesterTypeA testerTypeA) {
+        this.testerTypeA = testerTypeA;
+    }
+
+
+    public TesterTypeB getTesterTypeB() {
+        return testerTypeB;
+    }
+
+
+    public void setTesterTypeB(TesterTypeB testerTypeB) {
+        this.testerTypeB = testerTypeB;
+    }
+}
diff --git a/test/org/apache/jasper/runtime/TesterTypeA.java b/test/org/apache/jasper/runtime/TesterTypeA.java
new file mode 100644
index 0000000..1ca127f
--- /dev/null
+++ b/test/org/apache/jasper/runtime/TesterTypeA.java
@@ -0,0 +1,42 @@
+/*
+* 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.
+*/
+package org.apache.jasper.runtime;
+
+public class TesterTypeA {
+
+    private Integer data;
+
+
+    public Integer getData() {
+        return data;
+    }
+
+
+    public void setData(Integer data) {
+        this.data = data;
+    }
+
+
+    @Override
+    public String toString() {
+        if (data == null) {
+            return "";
+        } else {
+            return data.toString();
+        }
+    }
+}
diff --git a/test/org/apache/jasper/runtime/TesterTypeAEditor.java b/test/org/apache/jasper/runtime/TesterTypeAEditor.java
new file mode 100644
index 0000000..076c0f9
--- /dev/null
+++ b/test/org/apache/jasper/runtime/TesterTypeAEditor.java
@@ -0,0 +1,30 @@
+/*
+* 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.
+*/
+package org.apache.jasper.runtime;
+
+import java.beans.PropertyEditorSupport;
+
+public class TesterTypeAEditor extends PropertyEditorSupport {
+
+    @Override
+    public void setAsText(String text) throws IllegalArgumentException {
+        TesterTypeA value = new TesterTypeA();
+        // Zero length values deliberately trigger an exception
+        value.setData(Integer.valueOf(text));
+        setValue(value);
+    }
+}
diff --git a/test/org/apache/jasper/runtime/TesterTypeB.java b/test/org/apache/jasper/runtime/TesterTypeB.java
new file mode 100644
index 0000000..5e5a277
--- /dev/null
+++ b/test/org/apache/jasper/runtime/TesterTypeB.java
@@ -0,0 +1,25 @@
+/*
+* 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.
+*/
+package org.apache.jasper.runtime;
+
+public class TesterTypeB {
+
+    @Override
+    public String toString() {
+        return "TesterTypeB";
+    }
+}
diff --git a/test/webapp/bug6nnnn/bug63359a.jsp b/test/webapp/bug6nnnn/bug63359a.jsp
new file mode 100644
index 0000000..400b582
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug63359a.jsp
@@ -0,0 +1,202 @@
+<%--
+ 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:useBean id="bean" class="org.apache.jasper.runtime.TesterBean" />
+<html>
+  <head><title>Bug 63359 test cases</title></head>
+  <body>
+    <jsp:setProperty name="bean" property="booleanPrimitive" value=""/>
+    <p>01-${bean.booleanPrimitive}</p>
+    <jsp:setProperty name="bean" property="booleanPrimitive" value="foo"/>
+    <p>02-${bean.booleanPrimitive}</p>
+    <jsp:setProperty name="bean" property="booleanPrimitive" value="true"/>
+    <p>03-${bean.booleanPrimitive}</p>
+    <jsp:setProperty name="bean" property="booleanPrimitive" value="TRuE"/>
+    <p>04-${bean.booleanPrimitive}</p>
+    <jsp:setProperty name="bean" property="booleanPrimitive" value="on"/>
+    <p>05-${bean.booleanPrimitive}</p>
+
+    <jsp:setProperty name="bean" property="booleanObject" value=""/>
+    <p>11-${bean.booleanObject}</p>
+    <jsp:setProperty name="bean" property="booleanObject" value="foo"/>
+    <p>12-${bean.booleanObject}</p>
+    <jsp:setProperty name="bean" property="booleanObject" value="true"/>
+    <p>13-${bean.booleanObject}</p>
+    <jsp:setProperty name="bean" property="booleanObject" value="TRuE"/>
+    <p>14-${bean.booleanObject}</p>
+    <jsp:setProperty name="bean" property="booleanPrimitive" value="on"/>
+    <p>15-${bean.booleanPrimitive}</p>
+
+    <jsp:setProperty name="bean" property="bytePrimitive" value=""/>
+    <p>21-${bean.bytePrimitive}</p>
+    <jsp:setProperty name="bean" property="bytePrimitive" value="42"/>
+    <p>22-${bean.bytePrimitive}</p>
+    <jsp:setProperty name="bean" property="bytePrimitive" value="-42"/>
+    <p>23-${bean.bytePrimitive}</p>
+    <jsp:setProperty name="bean" property="bytePrimitive" value="+42"/>
+    <p>24-${bean.bytePrimitive}</p>
+
+    <jsp:setProperty name="bean" property="byteObject" value=""/>
+    <p>31-${bean.byteObject}</p>
+    <jsp:setProperty name="bean" property="byteObject" value="42"/>
+    <p>32-${bean.byteObject}</p>
+    <jsp:setProperty name="bean" property="byteObject" value="-42"/>
+    <p>33-${bean.byteObject}</p>
+    <jsp:setProperty name="bean" property="byteObject" value="+42"/>
+    <p>34-${bean.byteObject}</p>
+
+    <jsp:setProperty name="bean" property="charPrimitive" value=""/>
+    <p>41-${bean.charPrimitive}</p>
+    <jsp:setProperty name="bean" property="charPrimitive" value="foo"/>
+    <p>42-${bean.charPrimitive}</p>
+    <jsp:setProperty name="bean" property="charPrimitive" value="b"/>
+    <p>43-${bean.charPrimitive}</p>
+    <jsp:setProperty name="bean" property="charPrimitive" value="
+"/>
+    <p>44-${bean.charPrimitive}</p>
+
+    <jsp:setProperty name="bean" property="charObject" value=""/>
+    <p>51-${bean.charObject}</p>
+    <jsp:setProperty name="bean" property="charObject" value="foo"/>
+    <p>52-${bean.charObject}</p>
+    <jsp:setProperty name="bean" property="charObject" value="b"/>
+    <p>53-${bean.charObject}</p>
+    <jsp:setProperty name="bean" property="charObject" value="
+"/>
+    <p>54-${bean.charObject}</p>
+
+    <jsp:setProperty name="bean" property="doublePrimitive" value=""/>
+    <p>61-${bean.doublePrimitive}</p>
+    <jsp:setProperty name="bean" property="doublePrimitive" value="42"/>
+    <p>62-${bean.doublePrimitive}</p>
+    <jsp:setProperty name="bean" property="doublePrimitive" value="-42"/>
+    <p>63-${bean.doublePrimitive}</p>
+    <jsp:setProperty name="bean" property="doublePrimitive" value="+42"/>
+    <p>64-${bean.doublePrimitive}</p>
+
+    <jsp:setProperty name="bean" property="doubleObject" value=""/>
+    <p>71-${bean.doubleObject}</p>
+    <jsp:setProperty name="bean" property="doubleObject" value="42"/>
+    <p>72-${bean.doubleObject}</p>
+    <jsp:setProperty name="bean" property="doubleObject" value="-42"/>
+    <p>73-${bean.doubleObject}</p>
+    <jsp:setProperty name="bean" property="doubleObject" value="+42"/>
+    <p>74-${bean.doubleObject}</p>
+
+    <jsp:setProperty name="bean" property="intPrimitive" value=""/>
+    <p>81-${bean.intPrimitive}</p>
+    <jsp:setProperty name="bean" property="intPrimitive" value="42"/>
+    <p>82-${bean.intPrimitive}</p>
+    <jsp:setProperty name="bean" property="intPrimitive" value="-42"/>
+    <p>83-${bean.intPrimitive}</p>
+    <jsp:setProperty name="bean" property="intPrimitive" value="+42"/>
+    <p>84-${bean.intPrimitive}</p>
+
+    <jsp:setProperty name="bean" property="intObject" value=""/>
+    <p>91-${bean.intObject}</p>
+    <jsp:setProperty name="bean" property="intObject" value="42"/>
+    <p>92-${bean.intObject}</p>
+    <jsp:setProperty name="bean" property="intObject" value="-42"/>
+    <p>93-${bean.intObject}</p>
+    <jsp:setProperty name="bean" property="intObject" value="+42"/>
+    <p>94-${bean.intObject}</p>
+
+    <jsp:setProperty name="bean" property="floatPrimitive" value=""/>
+    <p>101-${bean.floatPrimitive}</p>
+    <jsp:setProperty name="bean" property="floatPrimitive" value="42"/>
+    <p>102-${bean.floatPrimitive}</p>
+    <jsp:setProperty name="bean" property="floatPrimitive" value="-42"/>
+    <p>103-${bean.floatPrimitive}</p>
+    <jsp:setProperty name="bean" property="floatPrimitive" value="+42"/>
+    <p>104-${bean.floatPrimitive}</p>
+
+    <jsp:setProperty name="bean" property="floatObject" value=""/>
+    <p>111-${bean.floatObject}</p>
+    <jsp:setProperty name="bean" property="floatObject" value="42"/>
+    <p>112-${bean.floatObject}</p>
+    <jsp:setProperty name="bean" property="floatObject" value="-42"/>
+    <p>113-${bean.floatObject}</p>
+    <jsp:setProperty name="bean" property="floatObject" value="+42"/>
+    <p>114-${bean.floatObject}</p>
+
+    <jsp:setProperty name="bean" property="longPrimitive" value=""/>
+    <p>121-${bean.longPrimitive}</p>
+    <jsp:setProperty name="bean" property="longPrimitive" value="42"/>
+    <p>122-${bean.longPrimitive}</p>
+    <jsp:setProperty name="bean" property="longPrimitive" value="-42"/>
+    <p>123-${bean.longPrimitive}</p>
+    <jsp:setProperty name="bean" property="longPrimitive" value="+42"/>
+    <p>124-${bean.longPrimitive}</p>
+
+    <jsp:setProperty name="bean" property="longObject" value=""/>
+    <p>131-${bean.longObject}</p>
+    <jsp:setProperty name="bean" property="longObject" value="42"/>
+    <p>132-${bean.longObject}</p>
+    <jsp:setProperty name="bean" property="longObject" value="-42"/>
+    <p>133-${bean.longObject}</p>
+    <jsp:setProperty name="bean" property="longObject" value="+42"/>
+    <p>134-${bean.longObject}</p>
+
+    <jsp:setProperty name="bean" property="shortPrimitive" value=""/>
+    <p>141-${bean.shortPrimitive}</p>
+    <jsp:setProperty name="bean" property="shortPrimitive" value="42"/>
+    <p>142-${bean.shortPrimitive}</p>
+    <jsp:setProperty name="bean" property="shortPrimitive" value="-42"/>
+    <p>143-${bean.shortPrimitive}</p>
+    <jsp:setProperty name="bean" property="shortPrimitive" value="+42"/>
+    <p>144-${bean.shortPrimitive}</p>
+
+    <jsp:setProperty name="bean" property="shortObject" value=""/>
+    <p>151-${bean.shortObject}</p>
+    <jsp:setProperty name="bean" property="shortObject" value="42"/>
+    <p>152-${bean.shortObject}</p>
+    <jsp:setProperty name="bean" property="shortObject" value="-42"/>
+    <p>153-${bean.shortObject}</p>
+    <jsp:setProperty name="bean" property="shortObject" value="+42"/>
+    <p>154-${bean.shortObject}</p>
+
+    <jsp:setProperty name="bean" property="stringValue" value=""/>
+    <p>161-${bean.stringValue}</p>
+    <jsp:setProperty name="bean" property="stringValue" value="42"/>
+    <p>162-${bean.stringValue}</p>
+    <jsp:setProperty name="bean" property="stringValue" value="-42"/>
+    <p>163-${bean.stringValue}</p>
+    <jsp:setProperty name="bean" property="stringValue" value="+42"/>
+    <p>164-${bean.stringValue}</p>
+
+    <jsp:setProperty name="bean" property="objectValue" value=""/>
+    <p>171-${bean.objectValue}</p>
+    <jsp:setProperty name="bean" property="objectValue" value="42"/>
+    <p>172-${bean.objectValue}</p>
+    <jsp:setProperty name="bean" property="objectValue" value="-42"/>
+    <p>173-${bean.objectValue}</p>
+    <jsp:setProperty name="bean" property="objectValue" value="+42"/>
+    <p>174-${bean.objectValue}</p>
+
+    <jsp:setProperty name="bean" property="testerTypeA" value=""/>
+    <p>181-${bean.testerTypeA}</p>
+    <jsp:setProperty name="bean" property="testerTypeA" value="42"/>
+    <p>182-${bean.testerTypeA}</p>
+    <jsp:setProperty name="bean" property="testerTypeA" value="-42"/>
+    <p>183-${bean.testerTypeA}</p>
+    <jsp:setProperty name="bean" property="testerTypeA" value="+42"/>
+    <p>184-${bean.testerTypeA}</p>
+
+    <jsp:setProperty name="bean" property="testerTypeB" value=""/>
+    <p>191-${bean.testerTypeB}</p>
+  </body>
+</html>
+
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 21d2af2..4cc2bb1 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -173,6 +173,16 @@
       </update>
     </changelog>
   </subsection>
+  <subsection name="Jasper">
+    <changelog>
+      <fix>
+        <bug>63359</bug>: Ensure that the type conversions used when converting
+        from strings for <code>jsp:setProperty</code> actions are correctly
+        implemented as per section JSP.1.14.2.1 of the JSP 2.3 specification.
+        (markt)
+      </fix>
+    </changelog>
+  </subsection>
   <subsection name="Other">
     <changelog>
       <fix>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org