From 13661b46f900b0ef7dcca6404c9b9fd276624f40 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Sun, 30 Mar 2025 13:51:14 +0200 Subject: [PATCH] Validate: Normalize num/int/uint to Perl numeric types + add 64bit limit to int/uint Normalization may be undone by later validations, but this should work in most cases. --- FU/Validate.pm | 15 ++++++++------- t/validate.t | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/FU/Validate.pm b/FU/Validate.pm index da29a2e..7352053 100644 --- a/FU/Validate.pm +++ b/FU/Validate.pm @@ -81,9 +81,9 @@ our %default_validations = ( bool => { type => 'any', func => sub { my $r = to_bool $_[0]; return {} if !defined $r; $_[0] = $r; 1 } }, anybool => { type => 'any', default => false, func => sub { $_[0] = $_[0] ? true : false; 1 } }, - num => { _reg $re_num }, - int => { _reg $re_int }, # implies num - uint => { _reg $re_uint }, # implies num + num => [ _reg($re_num), func => sub { $_[0] = $_[0]*1; 1 } ], + int => [ _reg($re_int), func => sub { return { message => 'integer out of range' } if $_[0] < -9223372036854775808 || $_[0] > 9223372036854775807; $_[0] = int $_[0]; 1 } ], + uint => [ _reg($re_uint), func => sub { return { message => 'integer out of range' } if $_[0] > 18446744073709551615; $_[0] = int $_[0]; 1 } ], min => sub($min) { +{ num => 1, func => sub { $_[0] >= $min ? 1 : { expected => $min, got => $_[0] } } } }, max => sub($max) { +{ num => 1, func => sub { $_[0] <= $max ? 1 : { expected => $max, got => $_[0] } } } }, range => sub { [ min => $_[0][0], max => $_[0][1] ] }, @@ -780,17 +780,18 @@ Require the input to be a boolean type as per C in L. Implies C<< type => 'scalar' >>. Require the input to be a number formatted using the format permitted by JSON. Note that this is slightly more restrictive from Perl's number formatting, in that 'NaN', 'Inf' and thousand separators are -not permitted. +not permitted. The value is normalized to a Perl integer or floating point +value, which means precision for large numbers may be lost. =item int => 1 -Implies C<< type => 'scalar' >>. Require the input to be an (arbitrarily large) +Implies C<< type => 'scalar' >>. Require the input to be an (at most) 64-bit integer. =item uint => 1 -Implies C<< type => 'scalar' >>. Require the input to be an (arbitrarily large) -positive integer. +Implies C<< type => 'scalar' >>. Require the input to be an (at most) 64-bit +unsigned integer. =item min => $num diff --git a/t/validate.t b/t/validate.t index 626dbbd..a29dc4c 100644 --- a/t/validate.t +++ b/t/validate.t @@ -209,8 +209,8 @@ t { num => 1 }, '1', '1'; f { num => 1 }, '1.1.', nerr '1.1.'; f { num => 1 }, '1.-1', nerr '1.-1'; f { num => 1 }, '.1', nerr '.1'; -t { num => 1 }, '0.1e5', '0.1e5'; -t { num => 1 }, '0.1e+5', '0.1e+5'; +t { num => 1 }, '0.1e5', 10000; +t { num => 1 }, '0.1e+5', 10000; f { num => 1 }, '0.1e5.1', nerr '0.1e5.1'; t { int => 1 }, 0, 0; t { int => 1 }, -123, -123;