Perl CGI::param Overloaded Method?

Posted in: Technical Track

This is a little story of a little bug. This gremlin suddenly appeared in a CGI.PM web-based application I work with. To make a long story short, an email was coming out something like this . . .

389939
Subject:Update to Report #389939 by B. bloggins Description:389939 #389939: TPDD Now Deploying to monitoring for the MySQL servers.

. . . when it should have been some thing like this:

Subject: TPDD Update to Report #389939 by B. bloggins

TPDD Now Deploying to monitoring for the MySQL servers.

After about an hour tracking things back, my team and I narrowed it down to this line of code:

$self->send_TXT_email(CGI::param("rep_no"),$rep_object,
                     $subject,$user_ref);

We scratched our respective heads on this for a while, because for user type ‘A’, it worked fine; but for user type ‘B’, it did not. And they were both using the same web page to send the email.

But before we went and reinstalled our mail server, I remembered that this is how CGI::param is intended to work:

@values = $query->param('foo');
# or
$value = $query->param('foo');

Arghhh! A wretched, two-faced overloaded method! So, depending on how you call the method, the returned results may differ.

Looking deeper, I discovered that the page was in fact receiving three values for CGT::param(“rep_no”) when user was of type ‘B’, and thus sending that as an array to the send_TXT_email method, and as a result, buggering up the email content.

Even more digging I found out the root cause was a web page that was three pages back from the one that was sending the email. Seems some-one made a change to fix one bug and as a result caused this one.

This quick fix for this (as we could not change the root page) was

my $rep_no=CGT::param("rep_no");
$self->send_TXT_email($rep_no,$rep_object,$subject,$user_ref);

Lesson learned: never trust a wretched, two-faced overloaded method.

Interested in working with John? Schedule a tech call.

3 Comments. Leave new

Richard Quintin
December 1, 2009 7:44 am

Perl – a million solutions for every problem.

Would this also do it?
$self->send_TXT_email(scalar($rep_no=CGT::param(“rep_no”)),$rep_object,$subject,$user_ref);

Reply
Yanick Champoux
December 1, 2009 6:34 pm

$self->send_TXT_email(scalar($rep_no=CGT::param(”rep_no”)),$rep_object,$subject,$user_ref);

Actually, the scalar( $x = param() ) is overkill. Assigning ‘param()’ to a scalar already forces a scalar context. So

$self->send_TXT_email(scalar(CGI::param(”rep_no”)),$rep_object,$subject,$user_ref);

or

$self->send_TXT_email(($rep_no=CGI::param(”rep_no”)),$rep_object,$subject,$user_ref);

or even

$self->send_TXT_email(''.CGI::param(”rep_no”),$rep_object,$subject,$user_ref);

would work just fine. Although splitting it in two statements, like John did, is a more readable way of doing it.

Reply

I could be wrong here, but you could also embrace the overloading:

($value) = $query->param(‘foo’);

You’ll get the param output as an array, where it will put the first value in the list into $value.

Reply

Leave a Reply

Your email address will not be published. Required fields are marked *