Re: Match number >= 0 and <1
by blazar (Canon) on Jul 29, 2005 at 13:34 UTC
|
Personally I would:
- untaint the number using a suitable regex,
- verify that it is actually a number by any method you like most (this could be avoided depending on the regex at the previous point),
- verify that it is in the range you're interested in, e.g. $x>=0 and $x<1.
This may seem slitghtly more verbose but should also more clear top read. It all depends on the restictions you want to impose on the input. For example are users allowd to input numbers in scientific notation? | [reply] [d/l] |
|
| [reply] |
Re: Match number >= 0 and <1
by gam3 (Curate) on Jul 29, 2005 at 13:46 UTC
|
I would only point out that 0.9999999999999999999999999999 + 0 = 1 in perl. Also leading whitespace will not make it through your regular expression.
You might be better off with:
my ($untainted) = ($_num =~ /^(.*)$/);
if ($untainted >= 0 and $untainted < 1) {
$num = $untainted + 0.0;
}
And here is a small test
If you don't want strings like 'asdfads' to be equal to 0 then you do need to use a smarter regular expression.
-- gam3
A picture is worth a thousand words, but takes 200K.
| [reply] [d/l] [select] |
|
Argument "asdfads" isn't numeric in numeric ge (>=) at !.pl line 5.
Even worse, "asdfads" is falsly considered valid. (It gets converted to 0.) | [reply] [d/l] |
|
could you please give some value for $_num where my ($untainted) = ($_num =~ /^(.*)$/); has a different outcome than just my $untainted = $_num.
| [reply] |
|
It is my understandment that it will have just the same value, but it will be... ehm... untainted! Which is the point the OP was trying to make: first blindily untaint, then do your checks whatever way you like most, i.e. do not try to do it all in one regex. I second his approach, BTW!
| [reply] |
|
All of them. The regexp removes the taint flag.
| [reply] |
|
| [reply] |
|
| [reply] |
|
sysopen my $handle, "untrusted_file", O_RDONLY | O_TAINTED or die;
| [reply] [d/l] |
Re: Match number >= 0 and <1
by japhy (Canon) on Jul 29, 2005 at 13:49 UTC
|
Is "0." valid? Is "." valid? I'm assuming the first is allowed, but the second is not:
/^(?=0(?!\d)|\.\d)(0?\.?\d*)$/
I believe that works fine. The initial look-ahead ensures we're either going to see 0 that's not followed by a digit or a '.' that IS followed by a digit. The rest of the regex APPEARS to be able to match zero characters, but we know from our look-ahead we'll match AT LEAST a "0" or a ".X".
| [reply] [d/l] |
Re: Match number >= 0 and <1
by tlm (Prior) on Jul 29, 2005 at 15:33 UTC
|
if ( eval { use warnings FATAL => 'numeric'; $_num < 1 && $_num >= 0 }
+ ) {
# $_num is OK...
$_num =~ /(.*)/;
$_num = $1; # untaint $_num
# ...
}
Update: Thanks to VSarkiss for pointing out the untainting aspect of the problem. I have added untainting code to take care of this. Even with this added requirement I don't see the point of using a regexp to both untaint and check the numeric properties of the variable.
| [reply] [d/l] |
|
I don't see the point of using a regexp to solve this type of problem.
Ordinarily I'd agree with you, but the OP clearly stated:
I'm using the RE to untaint a number from a CGI form.
| [reply] |
Re: Match number >= 0 and <1
by ikegami (Patriarch) on Jul 29, 2005 at 13:34 UTC
|
my $num = ($_num =~ /^(0+(?:\.\d+)?|\.\d+)$/) ? 0+$1 : undef;
In any case, it's probably better if you first check if it's a number, then check if it's in range. It makes the code easier to read, more maintainable and less error prone.
my ($num) = $_num =~ /^(...)$/
undef $num if defined $num && ($num < 0 || $num >= 1);
Update: oops, it didn't match just plain '0'.
| [reply] [d/l] [select] |
Re: Match number >= 0 and <1
by pbeckingham (Parson) on Jul 29, 2005 at 14:27 UTC
|
It could be more concise, and you don't need the alternation:
my ($num) = $_num =~ /^0?\.\d+$/;
Interpreted as: zero or one zeroes, a period, followed by digits.
pbeckingham - typist, perishable vertebrate.
| [reply] [d/l] |
|
"0" is not legal according your regexp. I did the same mistake up above. Also, you removed the necessary capture.
| [reply] [d/l] |
Re: Match number >= 0 and <1
by davidrw (Prior) on Jul 31, 2005 at 15:29 UTC
|
If you're going to use a regex, you can use Regexp::Common::number instead of rolling your own, and then just do the numeric range check. Note that this regex will support many formats, including exponential and optionally grouping (see pod).
use Regexp::Common qw /number/;
my $ok = $num =~ /^$RE{num}{real}$/
&& 0 <= $num
&& $num < 1 ;
| [reply] [d/l] |