Handle huge numbers better

A sufficiently big number, i.e. longer than a long long, had interesting
effects. Perl would promote it to a float, and format it as -1 in
sprintf, which RevBank::Amount didn't handle correctly. In extreme cases
the number got rounded to Inf and would no longer round-trip.

As a result, numbers returned by RevBank::Amount are now Math::BigInt
and Math::BigFloat objects. Those should be transparent to all existing
code. It's amazing to see the unit tests pass.

I don't think there is any actual use case in RevBank for numbers this
large and I don't think anyone will have actually encountered the
aforementioned weird effects. Mostly, the input would be parsed with
parse_amount which refuses any number greater than 99900 anyway. Only
where parse_string was used directly, such large numbers could actually
have been used, but in stock RevBank that is only done when reading the
accounts file.

This change also introduces a new global function parse_any_amount that
is like parse_amount but doesn't complain about negative or large
numbers, to further improve the adduser plugin (see previous commit) in
insane edge cases. It differs from RevBank::Amount->parse_string in that
it does support addition and subtraction operators.
This commit is contained in:
Juerd Waalboer 2024-08-28 05:08:20 +02:00
parent f6f5d66bdc
commit ef0039bc33
5 changed files with 54 additions and 40 deletions

View file

@ -21,8 +21,9 @@ sub username($self, $cart, $name, @) {
return REJECT, "Sorry, - + / ^ * are not allowed as the first character."
if $name =~ /^[-+*\/\^]/;
return REJECT, "Sorry, that's too numeric to be a user name."
if defined RevBank::Amount->parse_string($name);
my $num;
return REJECT, "Sorry, that evaluates to the amount $num and can't be an account name."
if defined($num = parse_any_amount($name));
return REJECT, "That name is not available."
if defined parse_user($name, 1);