ok, so, I need to read in some numbers from a file.
Numbers need to allow integer, float, signed/unsigned,
as well as supporting decimal, hex, binary, octal.
Extra level of annoyance: using modules from cpan is difficult.
So, if it can be pure perl, all the better.
What I came up with was this:
our $TEMPVAL;
sub convert_thing_to_numeric{
my ($orig_val)=@_;
if($orig_val =~ m{[\'\"]}){ # " '
confess "Error: to_numeric cannot handle input strings with quotes
";
}
$TEMPVAL = undef;
my $evalstring = "use warnings FATAL => 'all'; \$TEMPVAL = $orig_val ;
\$TEMPVAL = \$TEMPVAL + 0;";
print ":DEBUG: to_numeric($orig_val) evalstring is '$evalstring' \n"
if($DEBUG);
eval($evalstring);
if($@){
confess "Error: to_numeric() could not convert input string
'$orig_val' ";
}
unless(defined($TEMPVAL)){
confess "Error: to_numeric() ended up with undefined value? ";
}
return $retval;
}
so the idea is use perl string eval to read the numerical thing as a
perl numeric literal.
This will allow every format I need to support.
if $orig_val is any of these:
534
-234
4345.652
-256.234
0xbeef
0b1010101
then the eval string turns into
$TEMPVAL = 534;
$TEMPVAL = -234;
$TEMPVAL = 4345.625;
$TEMPVAL = -256.234;
$TEMPVAL = 0xbeef;
$TEMPVAL = 0b1010101;
And eval() will correctly convert the thing into a number and store it
in TEMPVAL.
The last part of eval string adds zero to TEMPVAL
$TEMPVAL = $TEMPVAL + 0;
This will force perl to numify TEMPVAL.
If the user had a bad number in the original file, such as '0xdeadybeef'
then TEMPVAL will start out a string, and then adding zero will force
perl to try to convert it into a number.
Normally, if perl can't turn the thing into a number to add zero,
it only throws a WARNING, which doesn't show up in $@ after an eval
block.
so, the first part of the eval string is to force all warnings into
fatals.
use warnings FATAL => 'all';
The only thing that concerns me a bit is that using string eval() means
the file could contain code I don't want to execute. and I can't figure
out
an easy way to prevent that.
I have a check for quotation marks in the argument.
I could add a check for parens, but that would only catch some function
calls,
not all, and would prevent legitimate users from using mathematical
parens.
and a bad string might have a function call with no parens.
Any suggestions on how to put some checks in here to keep things
safe-ish?
The file being read is local, mostly under our control, so its not like
I have to worry about reading strings passed in by random users from a
website.
Its more a matter of catching mistakes and typos that end up doing weird
things
without emitting any warning.
_______________________________________________
Boston-pm mailing list
Boston-pm@pm.org
https://mail.pm.org/mailman/listinfo/boston-pm