Reject non-integer strings in integer locale converters#411
Conversation
The integer locale converters parsed a value like 5.5 with a DecimalFormat that allows decimals, then narrowed it, silently truncating to 5. Reject a non-integer parse result before narrowing; BigIntegerLocaleConverter uses toBigIntegerExact.
|
Hi @rootvector2 Hm, my initial reaction was: This might break a bunch of existing call sites that rely on mapping a Then looking at the Javadoc of, for example, /**
* Standard {@link org.apache.commons.beanutils2.locale.LocaleConverter} implementation that converts an incoming locale-sensitive String into a {@link Integer}
* object, optionally using a default value or throwing a {@link org.apache.commons.beanutils2.ConversionException} if a conversion error occurs.
*/
public class IntegerLocaleConverter extends DecimalLocaleConverter<Integer> {Specifically: "optionally using a default value or throwing a ConversionException if a conversion error occurs." Which begs the question, when do you map a conversion error to the default value and when do you map it to throwing a ConversionException? Do you have any thoughts here? We have some leeway for changing behavior and APIs in master since 2.0 isn't out yet but a 1.X version of this PR would need to be least surprising. So focusing on master, and looking at WDYT? |
|
The split is decided at construction time, not per error. Every builder sets That's also why this patch doesn't introduce a new policy. It reclassifies a fractional result as a parse failure and lets the existing dispatch decide. A converter built with a default keeps returning the default (the On 1.X I agree least surprise wins. #407 landed the out-of-range rejection there, but truncating fractions is much older behavior, so I'd hold off on a 1.X port unless you want one. |
|
Thanks @rootvector2 , merged 🚀 It seems reasonable to port to 1.X since check for out-of-range in master, I'm not sure how far the code's drifted since the 1.x vs. master split though. |
|
thanks for merging. the 1.x side hasn't drifted much, its |
The integer locale converters
IntegerLocaleConverter,LongLocaleConverter,ShortLocaleConverter,ByteLocaleConverterandBigIntegerLocaleConverterparse with aDecimalFormatthat accepts a fractional part, then narrow the result withintValue()/longValue()/byteValue()/toBigInteger(). Their only guard checks that the value fits the target range, so5.5slips through and is silently truncated to5instead of rejected. Found by diffing them against the non-localeIntegerConverter, which rejects5.5throughInteger.valueOf.Each
parsenow rejects a non-integer result before narrowing, andBigIntegerLocaleConverterusestoBigIntegerExact. Grouping separators and large in-range integers still convert. The stale(B)assertions that pinned the old truncated values now expect the default.mvn; that'smvnon the command line by itself.