Dispatch Tables

At a previous job, I saw some code that asked the user which function they wanted to run and then executed a subroutine with that name. This code demonstrates why such a practice is bad:


use strict;
use warnings;

sub greet { print "Hello!\n" }
sub inquire { print "How are you?\n" }
sub bye { print "Farewell!\n" }
sub delete_all_files { print "*KABOOM*\n" }

sub insecure_call {
no strict 'refs';
shift->();
}

insecure_call('greet');
insecure_call('inquire');
insecure_call('bye');
insecure_call('delete_all_files');



Output:


Hello!
How are you?
Farewell!
*KABOOM*


One solution to this is the dispatch table. With a dispatch table, you define up front which calls are legal for an outsider to make:


more

2 Comments

I cover dispatch tables in Mastering Perl along with other such subroutine tricks. :)

Just put a prefix on the names of functions.

sub cmd_greet   { print "Hello!\n" }
sub cmd_inquire { print "How are you?\n" }
sub cmd_bye     { print "Farewell!\n" }
 
sub secure_enough_call {
    my ($cmd) = @_;
    my $sub = __PACKAGE__->can("cmd_$cmd")
        or do { warn "No such command $cmd\n"; return };
    $sub->();
}

Now if you have a sub delete_all_files there is no way to call it through secure_enough_call.

Leave a comment

About tinypig

user-pic I blog about Perl.