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

Reply via email to