Re: Calling subroutines.
Andy Williams (IMAP HILLWAY) wrote: Great thanks. I had thought of doing that but it needs to know about subroutines that another programmer may put in an entirely different package. (Basically I will be the only one to have access to this code). Er... you seem confused. If you're the only one with access to this code, who's the "another programmer"? (: I suspect "can" is probably the tidiest way of doing what you want (it'll work with inheritance & everything, if that matters) I guess I can just leave the hash off. but that just doesn't feel very secure maybe it's just me :) I agree. This is only partly about security, though. _If_ you are dealing with dubious data which might say "store", or alternatively "`rm -rf /`", you'd better not say eval $dubious_data or you'd be in trouble. It's more particularly a matter of knowing what your interfaces are up to, and not having unexpected methods/functions ("DESTROY"?) called without realising what's going on. (This is more of a problem where other programmers are involved - to parapharse Satre, "hell is [what] other people [do to your interfaces]" - but it's fairly easy to pervert one's own interfaces by mistake). HTH, -- Ti'
RE: Calling subroutines.
> -Original Message- > From: [EMAIL PROTECTED] > [mailto:[EMAIL PROTECTED] On Behalf Of Matt Lawrence > Sent: 01 August 2003 16:20 > To: [EMAIL PROTECTED] > Subject: Re: Calling subroutines. > A nice simple way of doing that would be to have a hash of > valid values > for $method. > > my %valid = ( > 'METH1' => 1, > 'MyPkg::METH2' => 1 > ); > > if ($method and $valid{$method}) { > { > no strict 'refs'; > eval { &$method(@args) }; > } > if ($@) { > my $args = join(', ', map {"'$_'"} @args); > warn "Error doing $method($args):[EMAIL PROTECTED]"; > } > } > else { > die "Invalid method $method\n"; > } > > That way you know that only "approved" subroutines can be called. > Great thanks. I had thought of doing that but it needs to know about subroutines that another programmer may put in an entirely different package. (Basically I will be the only one to have access to this code). I guess I can just leave the hash off. but that just doesn't feel very secure maybe it's just me :) Andy
Re: Calling subroutines.
> I realise that what is passed could be tainted and need to check for > that, I was just wondering if there was a "nice" way of doing this or > whether I should do it at all? Maybe not a 'nice' approach, but definitely effective in this case, would walking the main stash. So something like this would do it sub find_sub { my($pkg, $method) = @_; my $ret; return $ret if $ret = $pkg->can($method); for(keys %{"$pkg\::"}) { next if $_ eq "$pkg\::"; $ret = find_sub($1 => $method) if /(.*)\b::$/ and defined %{"$1\::"}; } return $ret; } die "Usage: $0 METHOD [ARGS]\n" unless @ARGV; my($method, @vars) = @ARGV; die "$0: couldn't find subroutine '$method'\n" unless my $sub = find_sub main => $method; $sub->( @vars ); exit(0); sub METH1 { my @passed_vars = @_; print "Welcome to method 1\n"; } package MyPgk; sub METH2 { my @passed_vars = @_; print "Welcome to method 2\n"; } Now if you run it at the command-line shell> perl find_sub.pl METH1 Welcome to method 1 shell> perl find_sub.pl METH2 Welcome to method 2 shell> perl find_sub.pl NOFUNC do_method.pl: couldn't find subroutine 'NOFUNC' Hope that helps. Dan
Re: Calling subroutines.
Andy Williams (IMAP HILLWAY) wrote: Hi, I want to be able to do something like the following: my $method = shift(@ARGV); my @vars = @ARGV; eval { &$method(@vars); }; if ($@) { die "Method doesn't exist"; } sub METH1 { my @passed_vars = @_; print "Welcome to method 1"; } package MyPgk; sub METH2 { my @passed_vars = @_; print "Welcome to method 1"; } So the above code would work for methods called METH1 and MyPgk::METH2 but no other. A nice simple way of doing that would be to have a hash of valid values for $method. my %valid = ( 'METH1' => 1, 'MyPkg::METH2' => 1 ); if ($method and $valid{$method}) { { no strict 'refs'; eval { &$method(@args) }; } if ($@) { my $args = join(', ', map {"'$_'"} @args); warn "Error doing $method($args):[EMAIL PROTECTED]"; } } else { die "Invalid method $method\n"; } That way you know that only "approved" subroutines can be called. I realise that what is passed could be tainted and need to check for that, I was just wondering if there was a "nice" way of doing this or whether I should do it at all. Tainted data is only a problem when you interact with the shell, AFAIK. If this program is supposed to interact with the shell, I'd say find another way of doing it, cause it's probably going to end up being a total hornet's nest. HTH, Matt
Re: Calling subroutines.
"Andy Williams (IMAP HILLWAY)" wrote: > > Hi, > > I want to be able to do something like the following: > > my $method = shift(@ARGV); > my @vars = @ARGV; > > eval { > &$method(@vars); > }; > > if ($@) { > die "Method doesn't exist"; > } > > sub METH1 { > my @passed_vars = @_; > print "Welcome to method 1"; > } > package MyPgk; > > sub METH2 { > my @passed_vars = @_; > print "Welcome to method 1"; > } > > > So the above code would work for methods called METH1 and MyPgk::METH2 > but no other. > > I realise that what is passed could be tainted and need to check for > that, I was just wondering if there was a "nice" way of doing this or > whether I should do it at all? 'can' does this? package Monster; sub method_monster { print 'monster' }; package main; for ('Monster::method_monster', 'arse', 'main_method') { print main->can ($_); } sub main_method { print 'method main' } [EMAIL PROTECTED] jmccrea]$ perl -l testy CODE(0x8104124) CODE(0x81041d8) [EMAIL PROTECTED] jmccrea]$ Unless I'm totally misunderstanding what the problem is? Jasper
Calling subroutines.
Hi, I want to be able to do something like the following: my $method = shift(@ARGV); my @vars = @ARGV; eval { &$method(@vars); }; if ($@) { die "Method doesn't exist"; } sub METH1 { my @passed_vars = @_; print "Welcome to method 1"; } package MyPgk; sub METH2 { my @passed_vars = @_; print "Welcome to method 1"; } So the above code would work for methods called METH1 and MyPgk::METH2 but no other. I realise that what is passed could be tainted and need to check for that, I was just wondering if there was a "nice" way of doing this or whether I should do it at all? TIA Andy