If ELSupport.coerceToType is called with an BigDecimal instance as the first Parameter 'obj' and
BigDecimal.class as type it should return the inputted value.
Instead the BigDecimal is converted into a double and back into a BigDecimal which leads to a diffenent
value. This happens in Line 228:
if (BigInteger.class.equals(type)) {
if (number instanceof BigDecimal) {
return ((BigDecimal) number).toBigInteger();
}
return BigInteger.valueOf(number.longValue()); // This leads to a different value.
}
Example: Run the Method with new BigDecimal("0.19"), BigDecimal.class as parameters.
This should result in a BigDecimal with value 0.19. Instead i got
0.190000000000000002220446049250313080847263336181640625.
The easiest solution is to compare the class of the object to coerce with the target class and return the
inputted value if the are equal in ELSupport.coerceToType Method:
public final static Object coerceToType(final Object obj, final Class type) throws
IllegalArgumentException {
if (type == null || Object.class.equals(type) || type.equals(obj.getClass())) {
return obj;
}
...

Well, the patch (as proposed in rev. 649639) fixes ELSupport.coerceToType(Object, Class), but the bug itself is in ELSupport.coerceToNumber(Number, Class).
There do exist other ways how coerceToNumber() is called from public methods of ELSupport.
For example, ELSupport.compare(Object, Object) calls it. I suppose, that those methods may suffer until coerceToNumber() itself is fixed.
The fix is OK for coerceToType() though.

I think that this fix may have introduced a regression error, since after upgrading from 6.0.16 to 6.0.18 I am getting this error:
Cannot convert 4,390,241 of type class java.lang.Integer to class java.lang.Number
java.lang.IllegalArgumentException
org.apache.el.lang.ELSupport.coerceToNumber(ELSupport.java:252)
org.apache.el.lang.ELSupport.coerceToNumber(ELSupport.java:265)
org.apache.el.lang.ELSupport.coerceToType(ELSupport.java:353)
org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:188)
org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate(PageContextImpl.java:925)
org.deltava.jsp.main.home_jsp._jspx_meth_fmt_005fint_005f0(home_jsp.java)

Created attachment 22355[details]
Removed unnecessary Object-creation in coerceToNumber()
The method protected final static Number coerceToNumber(final Number number, final Class type) created new BigInteger or BigDecimal Objects if the input-value was of the given type. As far as BigInteger and BigDecimal are immutable we can return the input value.
Another possible risk is the number.doubleValue() in the BigDecimal if clause. This behaves different to the coerceToType Method and was replaced with number.toString().

(In reply to comment #8)
> Another possible risk is the number.doubleValue() in the BigDecimal if clause.
> This behaves different to the coerceToType Method and was replaced with
> number.toString().
This breaks the spec. I have reverted this part of the patch.

This does not appear to be fixed, but I'm not sure if the problem rests with the code here or JSPC. I get the following error when executing a JSP:
Cannot convert 0 of type class java.lang.Long to class java.lang.Number
java.lang.IllegalArgumentException
org.apache.el.lang.ELSupport.coerceToNumber(ELSupport.java:250)
org.apache.el.lang.ELSupport.coerceToNumber(ELSupport.java:257)
org.apache.el.lang.ELSupport.coerceToType(ELSupport.java:351)
org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:188)
org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate(PageContextImpl.java:935)
org.deltava.jsp.admin.diagnostics_jsp._jspx_meth_fmt_005fint_005f8(diagnostics_jsp.java)
org.deltava.jsp.admin.diagnostics_jsp._jspx_meth_el_005ftable_005f0(diagnostics_jsp.java)
Looking at the the method call, I see this in the JSP source:
_jspx_th_fmt_005fint_005f8.setValue((java.lang.Number) org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${mapsAPIUsage}", java.lang.Number.class, (PageContext)_jspx_page_context, null, false));
The ELSupport.coerceToNumber(Number, Class) method appears to fail if the Class specified is java.lang.Number; there's no way it can execute without throwing an exception.

I don't think I can do this with just a JSP.
My best guess is that it gets triggered when JSP includes a tag that has a parameter which is defined in the TLD as being of type java.lang.Number; then when JSPC compiles the page it takes the type defined in the TLD and passes it to coerceToNumber.
Can I send you a JSP, TLD and a JAR with the tag?

This is a simple JSP I have created that should exhibit the behavior, along with a stripped-down TLD and tag sources.
The key I believe is to look at the compiled JSP's source and see what is getting passed in the setValue() method call.

The test case isn't clean (it references a class that doe snot exist) but once I clean it up this works for me with 6.0.20, 6.0.x and trunk.
If you still see this issue with the 6.0.x or later, please provide a working test case that demonstrates the issue.

Created attachment 24692[details]
zip containing JSP, TLD and java file
I came across this bug today - at least it looks a lot like it.
If I try to pass in a null to the function, it falls over giving me the following:
java.lang.IllegalArgumentException: Cannot convert 0 of type class java.lang.Long to class java.lang.Number
org.apache.el.lang.ELSupport.coerceToNumber(ELSupport.java:250)
Which is at best misleading and at worst, just the wrong way to handle nulls. Hopefully this is reproducible everywhere.

This is ASF Bugzilla: the Apache Software Foundation bug system. In case
of problems with the functioning of ASF Bugzilla, please contact
bugzilla-admin@apache.org.
Please Note: this e-mail address is only for reporting problems
with ASF Bugzilla. Mail about any other subject will be silently
ignored.