You don't know where it's being changed, but you need to find out. Change the variable so that it tells you where it's being changed.

package TattletaleScalar;

useCarpqw(cluck);

requireTie::Scalar;

our@ISA = qw(Tie::StdScalar);

sub STORE{

warn"TATTLETALE variable set to {$_[1]}";

cluck();

${$_[0]} = $_[1];

}

package main;

useData::Dumper;

sub some_long_faraway_function{

my$href = shift;

# Pretend there's a lot of code here I don't want to sift through

$href->{bananas} = 'some bad value';

}

my$shopping_list = {

apples=>1,

pears=>3,

bananas=>5,

};

my$tmp = $shopping_list->{bananas};# Save current value

tie$shopping_list->{bananas},'TattletaleScalar';

$shopping_list->{bananas} = $tmp;# Restore saved value

some_long_faraway_function($shopping_list);

warnDumper(\$shopping_list);

Now we can see the stack every time the variable is changed:

TATTLETALE variable set to {5} at example.pl line 7.
at example.pl line 8.
TattletaleScalar::STORE(TattletaleScalar=SCALAR(0x7fac290d3260), 5) called at example.pl line 29
TATTLETALE variable set to {some bad value} at example.pl line 7.
at example.pl line 8.
TattletaleScalar::STORE(TattletaleScalar=SCALAR(0x7fac290d3260), "some bad value") called at example.pl line 19
main::some_long_faraway_function(HASH(0x7fac29026508)) called at example.pl line 30
$VAR1 = \{
'apples' => 1,
'pears' => 3,
'bananas' => 'some bad value'
};

Wednesday, August 26, 2015

Update: I have changed the title to "Using Dispatch Tables To Improve Application Security" for clarity.

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:

usestrict;

usewarnings;

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{

nostrict'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:

usestrict;

usewarnings;

my%dispatch = (

greet=> \&greet,

inquire=> \&inquire,

bye=> \&bye,

);

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 secure_call{

my$call = shift;

if(ref$dispatch{$call} eq'CODE'){

$dispatch{$call}->();

}

else{

warn"Invalid call $call";

}

}

secure_call('greet');

secure_call('inquire');

secure_call('bye');

secure_call('delete_all_files');

Output:

Hello!
How are you?
Farewell!
Invalid call delete_all_files at example_2a line 22.

The thing that bugs me about this particular solution (and I'll admit it's minor) is the repetition:

my%dispatch = (

greet=> \&greet,

inquire=> \&inquire,

bye=> \&bye,

);

To me, this reads like:

To go to greet, type 'greet'.
To go to inquire, type 'inquire'.
To go to bye, type 'bye'.

When it could just be asking "Which function do you wish to use?"

So, we could build the dispatch table dynamically from a list of acceptable calls:

usestrict;

usewarnings;

my%dispatch;

my@valid_calls = qw( greet inquire bye );

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 build_dispatch_table{

nostrict'refs';

%dispatch = map{$_=>*{$_} }@valid_calls;

}

sub secure_call{

my$call = shift;

if($dispatch{$call} ){

$dispatch{$call}->();

}

else{

warn"Invalid call $call\n";

}

}

build_dispatch_table();

secure_call('greet');

secure_call('inquire');

secure_call('bye');

secure_call('delete_all_files');

print"\nBut, now this works because of the typeglob *{}\n";

our@greet = qw( This is an array );

print"@{$dispatch{greet}}\n";

print"which annoys me even though it's probably inconsequential\n";

Output:

Hello!
How are you?
Farewell!
Invalid call delete_all_files
But, now this works because of the typeglob *{}
This is an array
which annoys me even though it's probably inconsequential

In addition to the typeglob annoyance, there is still a little repetition there: greet, inquire and bye still appear more than once in the code. I don't actually find this to be a huge deal, but how might we solve those issues? One way is including the code itself in the dispatch table:

One argument against this is it adds visual complexity to the code: it's one more layer that a new developer on the project would need to mentally parse before coming up-to-speed on the code. But, that may be minor, and I think these formatting choices are developer-friendly.

Friday, August 07, 2015

One of the corners I often paint myself into when developing a tool is only accepting one type of input, usually STDIN, the standard input stream, like a pipeline (ex: cat fruit.txt | grep apple) or a redirect (ex: grep apple < fruit.txt)

What inevitably happens is I end up wanting the tool to work like any Unix tool and accept different kinds of input (filenames or arguments on the command line, for example.)

Finally I got fed up with it and added a function called multi_input() to my library. Here is how it works:

Sunday, April 26, 2015

Some people still don't read a blog's comments. I encourage you to do so if the topic interests you. The original post is not complete without the comments, because in them you will often find corrections to the original post or suggestions that improve upon it. Sometimes you will read comments that you feel add little, or, if it's especially popular (not mine), flame wars and maybe some spam. But it's better to have the conversation than a lone blog post with a single person's opinions and experiences.

I have been tempted in the past to update my own posts with valuable input from the comment section, but I think it's better to encourage folks to read them. What's useful to me might not be useful to you.

There's no single person that knows everything I know, but for any given topic, there's someone who knows more about it than I do. That's why the comments are important.

Sunday, April 05, 2015

I was reviewing some code I had written for a simple RPG dice algorithm (although there's already a good module for this, Game::Dice) and I realized again that I have a prefererence for functions that can fit on one screen. One strategy is breaking up the code into smaller routines but I sometimes like to compact it vertically as much as possible first.

This function roll, given a string of "dice language," should return the results of such a dice roll. An example of this would be "3d10+1" to roll three 10-sided dice and then add 1, or "4d6b3" which says to roll four 6-sided dice and take the best three.

Now you can make things a lot smaller (see Perl Golf examples) but readability is important to me, and I think this is arguably as readable as the original. I was actually a little surprised that perltidy barely touched the if/elsif structure, just screwing up the alignment a little on the first line:

The code doesn't strictly adhere to Perl Best Practices, which is something I like to use as a guide for the most part, but perlcritic (which is based on Perl Best Practices) doesn't start to complain until the cruel setting, then bringing up things like postfix if, postfix for, and unless.

Sunday, March 15, 2015

A couple weeks ago I asked how you "join the conversation" but based on feedback I got, I don't think I communicated well. I think people thought I meant "which blogs do you read?" What I really meant was: when you write a blog entry, where do you post the link so that it's seen by people who are interested in that subject?

So for example, when I write about Perl, I post to blogs.perl.org. I want to blog about other topics too, like web development (JavaScript, CSS, etc); lifehacks; Unix, Linux, shell scripting; general tech / tech business; and database stuff. But when I blog I'd like it to have a chance of being seen. Please let me know your thoughts!