stephenpry has asked for the wisdom of the Perl Monks concerning the following question:

I have a problem trying to evaluate variables coming back from Mysql. Basically I read a table of commands so that in the debugger I can 'p $cmd' and see "/usr/sbin/ping $this->{config}->{server}" The problem is that when I backtick $cmd it still has the literal $this->{config}->{server} in the string. In other words I can't get it to evaluate. I've tried setting it into a new variable in double-quotes and passing it to a sub etc. but still the same. Is it possible that the data is tainted and if so how can I get it to evaluate ?

Replies are listed 'Best First'.
Re: Variable expansion
by strat (Canon) on Apr 17, 2002 at 14:01 UTC
    You save perl-code to a database as string, and then read it from the database und want to evaluate it? Then eval might give you a helping hand...

    I can't give you a code-example because I am not sure what your string retrieved from the databases is like and how the rest of the script looks like...

    Best regards,
    perl -le "s==*F=e=>y~\*martinF~stronat~=>s~[^\w]~~g=>chop,print"

Re: Variable expansion
by perlplexer (Hermit) on Apr 17, 2002 at 13:27 UTC
    Are you sure you are using `` and not '' ?
    To avoid confusion, use qx// instead; e.g.,
    my $cmd = 'ls -la'; my @out = qx/$cmd/;

    --perlplexer
Re: Variable expansion
by broquaint (Abbot) on Apr 17, 2002 at 13:31 UTC
    Are you sure you're not literal quoting $cmd before putting it in the backticks?
    my $hr = {foo => { bar => '/dev/null' } }; # will not work my $cmd = 'ls $hr->{foo}->{bar}'; print `$cmd`; # works a treat my $cmd = "ls $hr->{foo}->{bar}"; print `$cmd`; __output__ ls: -: No such file or directory /dev/null

    HTH

    broquaint

      I think the strings coming back are literals so what I must have is your case 1 which as you say doesn't work ! The literals contain strings that do map to local variables so somehow I've got to translate the part that is the variable to its value ? (I tried splitting it up where the '$' starts but when I set a new variable to: $newcmd=$cmd1.$cmd2; It seems to do the same thing.)
        If you do have the unfortunate case of having the string not being interpolated then you could use the string version of eval() to get the desired result.
        my $hr = { foo => { bar => '/dev/null' } }; my $cmd_literal = 'ls $hr->{foo}->{bar}'; my $cmd = eval qq(return "$cmd_literal";); print `$cmd`; __output__ /dev/null
        But the best option would be to have $cmd be interpolated rather than resorting to eval().
        HTH

        broquaint

Re: Variable expansion
by stephen (Priest) on Apr 17, 2002 at 13:38 UTC

    Hard to say without seeing a little more code... if the problem were tainting, you would get an error message something like:

    Insecure dependency in `` while running with -T switch at ping_thingy. +pl line 10, <STDIN> line 1.

    Backticks interpolate their contents like a double-quoted string... but if you used single-quotes for $cmd, i.e.:

    my $cmd = '/usr/sbin/ping $this->{config}->{server}' my $output = `$cmd`;
    then you're going to get '/usr/sbin/ping $this->{config}->{server}' in the backticks. Switch those to double-quotes and you'll be OK.

    Or better yet, perhaps you can use Net::Ping...

    stephen

Re: Variable expansion
by Fletch (Bishop) on Apr 17, 2002 at 15:09 UTC

    Be aware that if you're not very sure of the source of the values comming back from your database you're treading in dangerous waters. If a malicious entity can get their own values in there somehow, th3y wI11 0wN J00 (especially since it looks like you're subsequently planning on passing values to system()).

    It's better practice to keep your code and data seperate (c.f. use strict "refs" :). Perhaps create different modules implementing an interface, and then use data from your database to select from that (limited, controlled) set of modules.