[Vienna-pm] eval in fremden namespaces?

Peter J. Holzer hjp-vienna-pm-list at hjp.at
Wed Mar 1 07:17:41 PST 2006


On 2006-03-01 14:21:01 +0100, peter pilsl wrote:
> 
> also, das problem ist wie folgt. Ich haben einen textstring, der eine 
> formeln und variablen und operatoren enthält ala
> 
> f($a,$b)+repro($m+$n,434)-$x2-($x3+$x4)
> 
> Und ich habe einen hash, der all diese funktionen und werte enthält:
> 
> my $x={funcs=>{f=>sub{ ... },
>                 repro=>sub{....},
>                 ...
>                 },
>         vars=>{a=>4,
>                b=>5,
>                m=>11,
>                n=>989823,
>                x2=>-11,
>                x3=>2.334,
>                x4=>-343434}};
> 
> 
> Nun möchte ich es irgendwie deichseln, dass ich den Textstring mittels 
> eval von perl auswerten lassen kann, auf Basis der Funktionen und 
> Variablen in meinem Hash. Mit einem passenden Deal von Objekten und 
> Namespaces müsste das ja eigentlich irgendwie gehen, aber wenn ich 
> darüber nachdenke, ende ich immer mit Kopfweh und einer Zigarette.
> 
> Zusatzproblem ist, dass zB die Funktion repro in meinem aktuellen 
> namespace durchaus auch schon anderwertig vergeben sein kann und das 
> ganze irgendwo tief in einem namespace/objekt-Konstrukt definiert wird. 
> Die Lösung, einfach mittels eval alle funktionen und variablen in meinem 
> hash in den den aktuellen Gültigkeitsbereich zu holen und dann mit eval 
> den string zu evaluieren, ist für mich (derzeit noch) keine Lösung. Da 
> kommen dann sicher auch Garbagecollection-sorgen auf mich und meine 
> mod_perl-Applikation zu.
> 
> Die einzige Lösung, die ich derzeit habe, ist, selbst einen parser zu 
> schreiben, was aber ziemlich doof ist, weil viel arbeit, um perl 
> nochmals zu erfinden, oder aber mittels gefinkelten regexs meinen term 
> so umzuschreiben, dass $a in $x->{vars}->{a} umgewandelt wird, was 
> sicher immer wieder zu Problemen führt, weil es komische Formeln gibt, 
> mit denen meine regex nicht gerechnet hat.

Wenn die Expression aus nichtvertrauenswürdiger Quelle stammt, ist
eventuell das Safe-Modul was für Dich. Dein Beispiel würde da so
aussehen:

---8<------8<------8<------8<------8<------8<------8<------8<---
#!/usr/bin/perl 
use warnings;
use strict;
use Safe;

my $expr = 'f($a,$b)+repro($m+$n,5)-$x2';
my $x = {funcs=>{f => '$_[0] + $_[1]',
                 repro => '$_[0] * $_[1]',
                 unsafe => q{
                                $_[0] + $_[1];
                                open(F, "/etc/passwd");
                                while (<F>) {
                                    print $_;
                                }
                                close(F);
                                return 42;
                            }
                },
        vars=>{a=>4,
               b=>5,
               m=>10,
               n=>10,
               x2=>-10000,
               x3=>2.334,
               x4=>-343434}
};


my $cpt = Safe->new();

for (keys %{$x->{vars}}) {
    ${$cpt->varglob($_)} = $x->{vars}{$_};
}

for (keys %{$x->{funcs}}) {
    $cpt->reval("sub $_ { $x->{funcs}{$_} }");
}

$cpt->reval('print "$b\n"');

our $result;

$cpt->share('$result');

$cpt->reval("\$result = $expr");

print "result=$result\n";

# das sollte nicht gehen, weil open nicht erlaubt ist.
$expr = 'f($a,$b)+repro($m+$n,5)-$x2 + unsafe()';
$cpt->reval("\$result = $expr");

print "result=$result\n";
---8<------8<------8<------8<------8<------8<------8<------8<---

Ob es ein Vorteil oder Nachteil ist, dass Du in diesem Fall die
Funktionen als Strings brauchst, hängt von Deiner Anwendung ab.



-- 
   _  | Peter J. Holzer    | Ich sehe nun ein, dass Computer wenig
|_|_) | Sysadmin WSR       | geeignet sind, um sich was zu merken.
| |   | hjp at hjp.at         |
__/   | http://www.hjp.at/ |	-- Holger Lembke in dan-am
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://mail.pm.org/pipermail/vienna-pm/attachments/20060301/17e926e3/attachment.bin


More information about the Vienna-pm mailing list