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.