Eval, the $ string, backslash escaping, and the adventures thereof

144 views
Skip to first unread message

dave

unread,
Jun 7, 2001, 8:59:13 AM6/7/01
to
$translate_dollar_sign = "\$$key =~ s/\$/(dollar-sign)/g";
eval "$translate_dollar_sign";
if ($@) {bail ("Error stripping \$$key $@");}

This code replaces the end of line with "(dollar-sign)" when I want it
to replace the character '$'. Backslashing doesn't help, it is still
a $ EOL to the regexp. I thought that maybe the eval was affecting
it, but the eval doesn't have any variables to interpret. Any ideas?

Thanks,

dave

Bernard El-Hagin

unread,
Jun 7, 2001, 9:10:25 AM6/7/01
to

Try:

$translate_dollar_sign = "\$$key =~ s/\\\$/(dollar-sign)/g";

Cheers,
Bernard
--
perl -l54e's yyw q q tvmrx "h\ywx ersxliv zivp legoiv"qiy;y #a-zA-Z#d-gu-z#
chefghijklmnopqrstuvwxyzcJab-def-uPwxyzc;s j j s u u s t t s r r s
ppevalpereeteueje'

Tad McClellan

unread,
Jun 7, 2001, 8:27:13 AM6/7/01
to
dave <us...@cyberspace.org> wrote:
>$translate_dollar_sign = "\$$key =~ s/\$/(dollar-sign)/g";
>eval "$translate_dollar_sign";
>if ($@) {bail ("Error stripping \$$key $@");}
>
>This code replaces the end of line with "(dollar-sign)"


It does?

I don't see how it does that. Looks like a syntax error when I try it...


>when I want it
>to replace the character '$'. Backslashing doesn't help


Yes it does, but the regex engine is not seeing a backslash in
front of the dollar sign.


>I thought that maybe the eval was affecting
>it,


I think it is the double quotes affecting it :-)


>Any ideas?


print "$translate_dollar_sign\n"; # see what perl sees

You appear to be using Symbolic References.

DON'T!

http://www.plover.com/~mjd/perl/varvarname.html
http://www.plover.com/~mjd/perl/varvarname2.html
http://www.plover.com/~mjd/perl/varvarname3.html


--
Tad McClellan SGML consulting
ta...@augustmail.com Perl programming
Fort Worth, Texas

Mark Jason Dominus

unread,
Jun 7, 2001, 2:45:40 PM6/7/01
to
In article <e2c00ae.01060...@posting.google.com>,

dave <us...@cyberspace.org> wrote:
>$translate_dollar_sign = "\$$key =~ s/\$/(dollar-sign)/g";
>eval "$translate_dollar_sign";
>if ($@) {bail ("Error stripping \$$key $@");}

Why don't you just use

$$key =~ s/\$/(dollar-sign)/g;

and dispense with the 'eval'? $$key will operate on the variable
whose name is stored in $key.

--
@P=split//,".URRUU\c8R";@d=split//,"\nrekcah xinU / lreP rehtona tsuJ";sub p{
@p{"r$p","u$p"}=(P,P);pipe"r$p","u$p";++$p;($q*=2)+=$f=!fork;map{$P=$P[$f^ord
($p{$_})&6];$p{$_}=/ ^$P/ix?$P:close$_}keys%p}p;p;p;p;p;map{$p{$_}=~/^[P.]/&&
close$_}%p;wait until$?;map{/^r/&&<$_>}%p;$_=$d[$q];sleep rand(2)if/\S/;print

Mark Jason Dominus

unread,
Jun 7, 2001, 2:52:49 PM6/7/01
to
In article <slrn9husp1...@tadmc26.august.net>,

Tad McClellan <ta...@augustmail.com> wrote:
>dave <us...@cyberspace.org> wrote:
>>$translate_dollar_sign = "\$$key =~ s/\$/(dollar-sign)/g";
>>eval "$translate_dollar_sign";
>>if ($@) {bail ("Error stripping \$$key $@");}
>>
>You appear to be using Symbolic References.

It may appear so, but you are mistaken.
('strict refs' agrees with me on this.)

I nominate this code as a #1 example of why the dictum "Always use
strict, even if you don't understand it" is bad advice.

dave

unread,
Jun 8, 2001, 8:46:28 AM6/8/01
to
m...@plover.com (Mark Jason Dominus) wrote in message news:<3b1fcd80.1ac6$3...@news.op.net>...

> In article <slrn9husp1...@tadmc26.august.net>,
> Tad McClellan <ta...@augustmail.com> wrote:
> >dave <us...@cyberspace.org> wrote:
> >>$translate_dollar_sign = "\$$key =~ s/\$/(dollar-sign)/g";
> >>eval "$translate_dollar_sign";
> >>if ($@) {bail ("Error stripping \$$key $@");}
> >>
> >You appear to be using Symbolic References.
>
> It may appear so, but you are mistaken.
> ('strict refs' agrees with me on this.)
>
> I nominate this code as a #1 example of why the dictum "Always use
> strict, even if you don't understand it" is bad advice.

Thanks for the advice guys, the reason the \$$key ....eval is there (I
normally wouldn't do this, is that it is in the middle of a CGI script
and I wanted to create a way to create a variable for each parameter
without having to do:

$some_parameter = $query->param('some_parameter');

which hard codes parameters that will change, so I have:
foreach $key ($query->param)
{
$create_variable = "\$$key = \$query->param('$key');";
eval "$create_variable";
if ($@) { bail ("Error creating \$$key : $@"); }

#code from before to strip out special characters...

}

I know this is nasty, slow (b/c eval?) and not as easy to read, and
uses symbolic references, any advice?

Thanks again (Java, PHP, et. al) don't have the sort of community that
Perl does, so thanks again,

dave

gnari

unread,
Jun 8, 2001, 8:47:45 AM6/8/01
to
>Thanks for the advice guys, the reason the \$$key ....eval is there (I
>normally wouldn't do this, is that it is in the middle of a CGI script
>and I wanted to create a way to create a variable for each parameter
>without having to do:
>
>$some_parameter = $query->param('some_parameter');
>
>which hard codes parameters that will change, so I have:
>foreach $key ($query->param)
>{
> $create_variable = "\$$key = \$query->param('$key');";
> eval "$create_variable";
> if ($@) { bail ("Error creating \$$key : $@"); }
>
> #code from before to strip out special characters...
>
>}
>
>I know this is nasty, slow (b/c eval?) and not as easy to read, and
>uses symbolic references, any advice?
>
above all, this is terribly unsafe. a malicious user can take advantage
of this to do things you may not anticipate.

gnari

Tad McClellan

unread,
Jun 8, 2001, 8:41:38 AM6/8/01
to
dave <us...@cyberspace.org> wrote:
>m...@plover.com (Mark Jason Dominus) wrote in message news:<3b1fcd80.1ac6$3...@news.op.net>...
>> In article <slrn9husp1...@tadmc26.august.net>,
>> Tad McClellan <ta...@augustmail.com> wrote:
>> >dave <us...@cyberspace.org> wrote:
>> >>$translate_dollar_sign = "\$$key =~ s/\$/(dollar-sign)/g";
>> >>eval "$translate_dollar_sign";
>> >>if ($@) {bail ("Error stripping \$$key $@");}
>> >>
>> >You appear to be using Symbolic References.
>>
>> It may appear so, but you are mistaken.
>> ('strict refs' agrees with me on this.)


I should have said "symbolic references" instead of "Symbolic References".

Looks to me like he is doing an end-around on symrefs, getting their
effect without actually using them.

And, as is usual for folks trying to do symref-like things, there
is probably a Better Way, often involving:

I don't know what your original problem is,
but I suggest to use a hash.

-Rafael Garcia-Suarez

ie. it is often an "XY problem".
^^^^^^^^^^

Do you (or anyone else) have a description/definition for that term?

I have often wanted to invoke it, but don't want to have to define
it each time ('cause I'll probably mess up the description).

I was kinda hoping for the OP to help us understand the "original problem".


>Thanks for the advice guys, the reason the \$$key ....eval is there (I
>normally wouldn't do this, is that it is in the middle of a CGI script
>and I wanted to create a way to create a variable for each parameter
>without having to do:
>
>$some_parameter = $query->param('some_parameter');
>
>which hard codes parameters that will change,


And here we have "Z" revealed :-)

A: Use a hash as a "portable namespace" instead of using perl's
symbol table (or heap if my()d).


>so I have:
>foreach $key ($query->param)
>{
> $create_variable = "\$$key = \$query->param('$key');";
> eval "$create_variable";
> if ($@) { bail ("Error creating \$$key : $@"); }
>
> #code from before to strip out special characters...
>
>}
>
>I know this is nasty, slow (b/c eval?) and not as easy to read, and
>uses symbolic references, any advice?


untested:

my %p; # my own little namespace
foreach my $key ($query->param) {
$p{$key} = $query->param($key);
}
# instead of using "$some_parameter", use "$p{some_parameter}" here


No symrefs. No string evals. Ah, that feels better :-)

Mark Jason Dominus

unread,
Jun 8, 2001, 10:32:10 AM6/8/01
to
>Thanks for the advice guys, the reason the \$$key ....eval is there (I
>normally wouldn't do this, is that it is in the middle of a CGI script
>and I wanted to create a way to create a variable for each parameter
>without having to do:
>
>$some_parameter = $query->param('some_parameter');

Then just use the ->import_names() function.
That is exactly what it does do.

Ren Maddox

unread,
Jun 8, 2001, 9:00:21 AM6/8/01
to
On 8 Jun 2001, us...@cyberspace.org wrote:

> Thanks for the advice guys, the reason the \$$key ....eval is there
> (I normally wouldn't do this, is that it is in the middle of a CGI
> script and I wanted to create a way to create a variable for each
> parameter without having to do:
>
> $some_parameter = $query->param('some_parameter');
>
> which hard codes parameters that will change, so I have:
> foreach $key ($query->param)
> {
> $create_variable = "\$$key = \$query->param('$key');";
> eval "$create_variable";
> if ($@) { bail ("Error creating \$$key : $@"); }
>
> #code from before to strip out special characters...
>
> }
>
> I know this is nasty, slow (b/c eval?) and not as easy to read, and
> uses symbolic references, any advice?

As MJD already pointed out, this doesn't actually use symbolic
references. That doesn't make it any less nasty. Any reason you
cannot simply use a hash? Better yet, have a look at the import_names
function in CGI.pm.

--
Ren Maddox
r...@tivoli.com

Mark Jason Dominus

unread,
Jun 8, 2001, 10:34:03 AM6/8/01
to
In article <slrn9i1i02...@tadmc26.august.net>,

Tad McClellan <ta...@augustmail.com> wrote:
>ie. it is often an "XY problem".
> ^^^^^^^^^^

An XY problem is when you want to do X, but you ask how to do Y
instead, because you've decided that Y is the best way to accomplish X.

> Do you (or anyone else) have a description/definition for that term?

Greg Bacon coined this phrase, by the way.

Mark Jason Dominus

unread,
Jun 8, 2001, 10:35:47 AM6/8/01
to
In article <m37kynp...@dhcp9-173.support.tivoli.com>,

Ren Maddox <r...@tivoli.com> wrote:
>As MJD already pointed out, this doesn't actually use symbolic
>references. That doesn't make it any less nasty.

It makes it more nasty. An error with symbolic references can smash a
variable anywhere in the program. An error with the eval can erase
your hard disk.

Greg Bacon

unread,
Jun 8, 2001, 11:18:33 AM6/8/01
to
In article <3b20e25a.320b$2...@news.op.net>,
Mark Jason Dominus <m...@plover.com> wrote:

: In article <slrn9i1i02...@tadmc26.august.net>,


: Tad McClellan <ta...@augustmail.com> wrote:
:
: >ie. it is often an "XY problem".
: > ^^^^^^^^^^
:
: An XY problem is when you want to do X, but you ask how to do Y
: instead, because you've decided that Y is the best way to accomplish X.
:
: > Do you (or anyone else) have a description/definition for that term?
:
: Greg Bacon coined this phrase, by the way.

Thanks for the credit, but I thought *you* coined the phrase. :-)

Greg, who can claim coining "Perl golf"
--
A lot of people mistake a short memory for a clear conscience.
-- Doug Larson

Mark Jason Dominus

unread,
Jun 8, 2001, 11:24:08 AM6/8/01
to
In article <ti1r69...@corp.supernews.com>,

Greg Bacon <gba...@hiwaay.net> wrote:
>: Greg Bacon coined this phrase, by the way.
>
>Thanks for the credit, but I thought *you* coined the phrase. :-)

I'll take credit for recognizing the phenomenon, but not for thinking
of the name. One of those varvarname articles has an excessively
ornate description of the problem, involving not just X and Y but also
Z and W. You're the one who first thought of calling it "the XY
problem".

Since we're on the subject, I believe it was Philip Gwyn who had the
idea of calling the $%@*& characters 'sigils'.

Randal L. Schwartz

unread,
Jun 8, 2001, 11:25:46 AM6/8/01
to
>>>>> "Greg" == Greg Bacon <gba...@HiWAAY.net> writes:

MJD> Greg Bacon coined this phrase, by the way.

Greg> Thanks for the credit, but I thought *you* coined the phrase. :-)

Well, there's always "XYZ problem" in Purl's current mindspace:

They ask how to do Z, but that's because they think they want to
do Y and think that Z will get them there, but really it's because
they're a lunkhead, and that's the main (X) problem

I won't make any claims about who put that factoid there.
--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<mer...@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!

dave

unread,
Jun 8, 2001, 12:45:25 PM6/8/01
to
Thanks guys, I will end up using a hash or import_names(). I have
heard that XY problem (George Bacon?) a few times. When you have a
hammer the whole word is a nail, and how can we use Java to build the
next Ford Taurus?

IMHO, or at least I hope, I was not guilty of forcing a solution on a
problem. The problem is that I didn't want a maintainer later to have
to define the variable in all the scripts before using it in DB
queries. My inexperience with Perl showed greatly, not thinking of a
hash (pretty stupid on my part) and not knowing about import_names().
At the least, I would hope that if I was forcing a solution it would
not be 'why don't we use a pseudo-sym-ref and an eval in a loop?'

At any level, thanks for the help and advice.

dave

Greg Bacon

unread,
Jun 8, 2001, 1:47:59 PM6/8/01
to
In article <3b20ee02.332c$3...@news.op.net>,

Mark Jason Dominus <m...@plover.com> wrote:

: In article <ti1r69...@corp.supernews.com>,


: Greg Bacon <gba...@hiwaay.net> wrote:
:
: >: Greg Bacon coined this phrase, by the way.
: >
: >Thanks for the credit, but I thought *you* coined the phrase. :-)

:
: [...] You're the one who first thought of calling it "the XY problem".

Then I'll just have to defer to your wisdom.

Greg
--
Santa: Stan, remember the choo-choo when you were three?
Jesus: I died for your sins, boys; don't forget that..

Greg Bacon

unread,
Jun 8, 2001, 1:49:09 PM6/8/01
to

: [...] I will end up using a hash or import_names(). I have
: heard that XY problem (George Bacon?) a few times. [...]

Not Gum. My name is Gumby, dammit!

Greg, always liked Eddie Murphy on SNL
--
Politics is the conduct of public affairs for private advantage.
-- Ambrose Pierce

Damian James

unread,
Jun 9, 2001, 4:11:34 AM6/9/01
to
Mark Jason Dominus chose Fri, 08 Jun 2001 14:35:47 GMT to say this:
>...

>It makes it more nasty. An error with symbolic references can smash a
>variable anywhere in the program. An error with the eval can erase
>your hard disk.
>

Well, indeed. I was worried when I saw you suggest symrefs to the OP as an
alternative, and composed a followup suggesting a hash. But I thought about
it some more and decided to butt out. I know when I'm out of my depth.

Cheers,
Damian
[ not in terms of the actual programming constructions, more in terms of the
heavyweights hanging around on this thread.]
--
@:=grep!($;+=m!$/|#!),split//,<DATA>;@;=0..$#:;while(@;){for($;=@;;--$;;)
{@;[$;,$:]=@;[$:,$;]if($:=rand$;+$|)!=$;}push@|,shift@;if$;[0]==@|;select
$,,$,,$,,1/80;print qq x\bxx((@;+@|)*$|++),@:[@|,@;],!@;&&$/} __END__
...es gibt hier kein(e?) JAPH

Bernie Cosell

unread,
Jun 9, 2001, 10:26:50 AM6/9/01
to
gnari <gna...@hotmail.com> wrote:

} > $create_variable = "\$$key = \$query->param('$key');";
} > eval "$create_variable";

} above all, this is terribly unsafe. a malicious user can take advantage

} of this to do things you may not anticipate.

While I agree with all the comments that you should really use a hash [I
can only say that that's what I use in MY cgi pgms :o)], your followup
comment isn't correct I don't think. He was careful to put the call to
$query->param in the eval'ed string, NOT the *results* of fetching the
parameter, so it should all be OK. Now, if he had done something like:
"\$$key = \"".$query->param($key).'"'
then *THAT* would've been a disaster waiting to happen, but I don't think
you can get into trouble just eval'ing a call to query->param.. can you??

/Bernie\
--
Bernie Cosell Fantasy Farm Fibers
ber...@fantasyfarm.com Pearisburg, VA
--> Too many people, too few sheep <--

gnari

unread,
Jun 9, 2001, 12:55:50 PM6/9/01
to
In article <kfc4it4k35svcc3s4...@news.supernews.net>,

Bernie Cosell <ber...@fantasyfarm.com> wrote:
>gnari <gna...@hotmail.com> wrote:
>
>} In article <e2c00ae.01060...@posting.google.com>,
>} dave <us...@cyberspace.org> wrote:
>
>} > $create_variable = "\$$key = \$query->param('$key');";
>} > eval "$create_variable";
>
>} above all, this is terribly unsafe. a malicious user can take advantage
>} of this to do things you may not anticipate.
>
>While I agree with all the comments that you should really use a hash [I
>can only say that that's what I use in MY cgi pgms :o)], your followup
>comment isn't correct I don't think. He was careful to put the call to
>$query->param in the eval'ed string, NOT the *results* of fetching the
>parameter, so it should all be OK. Now, if he had done something like:
> "\$$key = \"".$query->param($key).'"'
>then *THAT* would've been a disaster waiting to happen, but I don't think
>you can get into trouble just eval'ing a call to query->param.. can you??
>

i am sorry, but you are wrong. with a little imagination, it is easy
to take advantage of this. if you want a demonstration, put this code
in a cgi on your site (exactly as dave posted),
and i will email you your password file.
hint: the main weakness lies in the "\$$key=" part, not in the
query->param part

of course, it is easy to make it more secure by using Safe.pm,
or just a separate package with a little filtering of the input,
but you really need to have extensive understanding of perl and of the
whole system to be sure to have plugged all the holes, so why take such
riscs when the wonderful hash is at hand.

some people say that eval is bad, but eval on unknown and unvalidated
input is positively evil.

practice safe sex, specially with CGI

gnari

Mark Jason Dominus

unread,
Jun 9, 2001, 6:58:34 PM6/9/01
to
In article <slrn9i3mh5...@puma.qimr.edu.au>,

Damian James <dam...@qimr.edu.au> wrote:
>Mark Jason Dominus chose Fri, 08 Jun 2001 14:35:47 GMT to say this:
>>...
>>It makes it more nasty. An error with symbolic references can smash a
>>variable anywhere in the program. An error with the eval can erase
>>your hard disk.
>>
>
>Well, indeed. I was worried when I saw you suggest symrefs to the OP as an
>alternative,

Here's what I was thinking. The symrefs can get you in trouble, so
it's worth trying to suggest that someone using symrefs should rewrite
the code a little and use a hash instead. Sometimes people whine
about this; they don't want to use a hash. Maybe they won't take
youre advice. Oh well.

But this guy wasn't using symrefs; he had the 'eval' instead. This is
a hundred times more dangerous than using symrefs. So rather than
suggest that he change the code to use a hash, which he might whine
about, I suggested the simplest possible change that would solve the
biggest possible problem, namely that he replace the eval with
symrefs. Sure, it's not a complete solution, but it's 99% of the way
there, and the change is trivial.

It's all a matter of triage. When someone comes into the emergency
room with their head cut off, you don't worry about fixing their
cirrhosis, and in fact if putting the heada back on will cause acute
cirrhosis, you don't worry about that either.

Reply all
Reply to author
Forward
0 new messages