[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