Calling subroutines.

2003-08-01 Thread Andy Williams \(IMAP HILLWAY\)
Hi,

I want to be able to do something like the following:
perl
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;
}

/perl
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




Re: Calling subroutines.

2003-08-01 Thread Jasper McCrea
Andy Williams (IMAP HILLWAY) wrote:
 
 Hi,
 
 I want to be able to do something like the following:
 perl
 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;
 }
 
 /perl
 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



Re: Calling subroutines.

2003-08-01 Thread Matt Lawrence
Andy Williams (IMAP HILLWAY) wrote:

Hi,

I want to be able to do something like the following:
perl
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;
}
/perl
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.

2003-08-01 Thread Dan Brook
 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.

2003-08-01 Thread Andy Williams \(IMAP HILLWAY\)


 -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.

2003-08-01 Thread Tim Sweetman
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'