Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > variables inside a string

Reply
Thread Tools

variables inside a string

 
 
Jürgen Exner
Guest
Posts: n/a
 
      12-03-2010
Martin Keiter <(E-Mail Removed)> wrote:
>Ok, I found "eval", and it works, although I do not yet fully understand
>why


Actually it is very simple.
You just have to understand the difference between code and data.

>This does what I want:
>
>my $sentence = "\$1 is here!";


This line, including the double-quoted text is code. It is executed at
runtime and at that moment the content of the variable becomes data.
Obviously you cannot execute data.

> my $bar = eval $code;


Exception being eval(), which converts data (i.e. text) back into code,
such that it can be executed again.

> my $code =" \"$sentence\" ";
>but do I really have to introduce this additional variable $code ?
>I tried:
>eval \"$sentence\";
>eval "$sentence";
>eval $sentence;
>but all of them produce errors...


The thingy that you pass to eval must be legal Perl code.
$1 is here!
is not legal Perl code.

jue
 
Reply With Quote
 
 
 
 
Martin Keiter
Guest
Posts: n/a
 
      12-03-2010
On 2010-12-03, J. Gleixner <(E-Mail Removed)> wrote:
> Martin Keiter wrote:
>> On 2010-12-03, Martijn Lievaart <(E-Mail Removed)> wrote:
>>
>>> $sentence =~ s/\$1/$1/;

>>
>> this produces:
>> Use of uninitialized value in substitution iterator at .//test.pl line 13.
>>
>> what I do now is:
>>
>> my $sentence = "\$1 is here!";
>> my $string = "foo comes in";
>> my $reg = "(.*) comes in";
>>
>> my $text = $sentence;
>> if ($string =~ m/$reg/)
>> {
>> foreach my $i (1..9) {
>> if (${$i}) {
>> my $tmp = ${$i};
>> $text =~ s/\$$i/$tmp/
>> }
>> }
>> print "$text\n";
>> }
>>
>>
>> no eval any more, so it should be safe, although I find it a bit ugly.

>
> Maybe you're making this more complex than you need to. Provided your
> example is close to your actual code you could simplify it a lot.
>
> if( $string =~ m/$reg/ ){ print "$1 is here"; }


the example is relatively close to my code, but of course I have
simplified a bit: actually I have regexps and corresponding sentences in
an array, and then do a test of $string against all regexps inside a
loop. Most of the sentences will not contain a "$1", but some will.


$test[0]{'regexp'} = "(.*) comes in";
$test[0]{'sentence'} = "\$1 is here!";
....
....

# actually this will come from the outside world:
my $string = "foo comes in";

foreach my $i (0..$#talk)
{
if ($string =~ m/$test[$1]{'regexp'} /)
{
$text = $test[$i]{'sentence'};
# now if there is a (XXX) inside of $test[$1]{'regexp'}
# replace $1 in $text by XXX
}
}

 
Reply With Quote
 
 
 
 
Martin Keiter
Guest
Posts: n/a
 
      12-03-2010
On 2010-12-03, Jürgen Exner <(E-Mail Removed)> wrote:
> Martin Keiter <(E-Mail Removed)> wrote:
>>Ok, I found "eval", and it works, although I do not yet fully understand
>>why

>
> Actually it is very simple.


So I hoped!

> You just have to understand the difference between code and data.


I think I did, but am quite shure, I do not yet understand all this
quoting stuff.

>>This does what I want:
>>
>>my $sentence = "\$1 is here!";

>
> This line, including the double-quoted text is code. It is executed at
> runtime and at that moment the content of the variable becomes data.
> Obviously you cannot execute data.


agreed

>> my $bar = eval $code;

>
> Exception being eval(), which converts data (i.e. text) back into code,
> such that it can be executed again.


ok.

>> my $code =" \"$sentence\" ";
>>but do I really have to introduce this additional variable $code ?
>>I tried:
>>eval \"$sentence\";
>>eval "$sentence";
>>eval $sentence;
>>but all of them produce errors...

>
> The thingy that you pass to eval must be legal Perl code.
> $1 is here!
> is not legal Perl code.


ok.
But why does this work then?

my $sentence = "\$1 is here!";
my $code =" \"$sentence\" ";
eval $code;

is it that
"$1 is here!"
is passed to eval (including the quotes) and this is a valid expression?

Thanks for your patience!

 
Reply With Quote
 
sln@netherlands.com
Guest
Posts: n/a
 
      12-03-2010
On 3 Dec 2010 16:09:34 GMT, Martin Keiter <(E-Mail Removed)> wrote:

>On 2010-12-03, J. Gleixner <(E-Mail Removed)> wrote:
>> Martin Keiter wrote:
>>> On 2010-12-03, Martijn Lievaart <(E-Mail Removed)> wrote:
>>>
>>>> $sentence =~ s/\$1/$1/;
>>>
>>> this produces:
>>> Use of uninitialized value in substitution iterator at .//test.pl line 13.
>>>
>>> what I do now is:
>>>
>>> my $sentence = "\$1 is here!";
>>> my $string = "foo comes in";
>>> my $reg = "(.*) comes in";
>>>
>>> my $text = $sentence;
>>> if ($string =~ m/$reg/)
>>> {
>>> foreach my $i (1..9) {
>>> if (${$i}) {
>>> my $tmp = ${$i};
>>> $text =~ s/\$$i/$tmp/
>>> }
>>> }
>>> print "$text\n";
>>> }
>>>
>>>
>>> no eval any more, so it should be safe, although I find it a bit ugly.

>>
>> Maybe you're making this more complex than you need to. Provided your
>> example is close to your actual code you could simplify it a lot.
>>
>> if( $string =~ m/$reg/ ){ print "$1 is here"; }

>
>the example is relatively close to my code, but of course I have
>simplified a bit: actually I have regexps and corresponding sentences in
>an array, and then do a test of $string against all regexps inside a
>loop. Most of the sentences will not contain a "$1", but some will.
>
>
>$test[0]{'regexp'} = "(.*) comes in";
>$test[0]{'sentence'} = "\$1 is here!";
>...
>...
>
># actually this will come from the outside world:
>my $string = "foo comes in";
>
>foreach my $i (0..$#talk)
>{
> if ($string =~ m/$test[$1]{'regexp'} /)
> {
> $text = $test[$i]{'sentence'};
> # now if there is a (XXX) inside of $test[$1]{'regexp'}
> # replace $1 in $text by XXX
> }
>}


If you going to use eval, you could always use the suggs posted
by others with something like this.

-sln

use strict;
use warnings;

my @template = (
{ regexp => q{(.*) comes in},
sentence => qq{"\$1 is here!\\n"}
},
{ regexp => q{(.*) sometimes comes in},
sentence => qq{"\$1 is sometimes there!\\n"}
},
);

my @instrings = (
'foo comes in here',
'bar sometimes comes in',
'baz comes in here',
);

for my $sample (@instrings)
{
for my $i (0..$#template)
{
if ( $sample =~ /$template[ $i ]{'regexp'}/ ) {
print eval $template[ $i ]{'sentence'};
}
}
}

__END__

 
Reply With Quote
 
Willem
Guest
Posts: n/a
 
      12-03-2010
Martin Keiter wrote:
) On 2010-12-03, Martijn Lievaart <(E-Mail Removed)> wrote:
)
)> $sentence =~ s/\$1/$1/;
)
) this produces:
) Use of uninitialized value in substitution iterator at .//test.pl line 13.

Obviously, since the substitution itself makes a new $1.

) what I do now is:
)
) my $sentence = "\$1 is here!";
) my $string = "foo comes in";
) my $reg = "(.*) comes in";
)
) my $text = $sentence;
) if ($string =~ m/$reg/)
) {
) foreach my $i (1..9) {
) if (${$i}) {
) my $tmp = ${$i};
) $text =~ s/\$$i/$tmp/
) }
) }
) print "$text\n";
) }
)
)
) no eval any more, so it should be safe, although I find it a bit ugly.

Try this:

if (my @matches = $string =~ m/$reg/) {
$text =~ s/\$(\d+)/$matches[$1]/g;
}


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
Reply With Quote
 
Willem
Guest
Posts: n/a
 
      12-03-2010
Willem wrote:
) Try this:
)
) if (my @matches = $string =~ m/$reg/) {
) $text =~ s/\$(\d+)/$matches[$1]/g;
) }

Oops, off-by-one error.

if (my @matches = $string =~ m/$reg/) {
$text =~ s/\$(\d+)/$matches[$1-1]/g;
}



SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
Reply With Quote
 
Martin Keiter
Guest
Posts: n/a
 
      12-03-2010
On 2010-12-03, Willem <(E-Mail Removed)> wrote:
> Willem wrote:
> ) Try this:
> )
> ) if (my @matches = $string =~ m/$reg/) {
> ) $text =~ s/\$(\d+)/$matches[$1]/g;
> ) }
>
> Oops, off-by-one error.
>
> if (my @matches = $string =~ m/$reg/) {
> $text =~ s/\$(\d+)/$matches[$1-1]/g;
> }
>


That's good:
- it works
- I understand how it works
- it does not use eval

thank you!

 
Reply With Quote
 
Martin Keiter
Guest
Posts: n/a
 
      12-03-2010
On 2010-12-03, http://www.velocityreviews.com/forums/(E-Mail Removed) <(E-Mail Removed)> wrote:

> If you going to use eval, you could always use the suggs posted
> by others with something like this.
>
> -sln
>
> use strict;
> use warnings;
>
> my @template = (
> { regexp => q{(.*) comes in},
> sentence => qq{"\$1 is here!\\n"}
> },
> { regexp => q{(.*) sometimes comes in},
> sentence => qq{"\$1 is sometimes there!\\n"}
> },
> );


I definitely have to learn about all this quoting! (you don't need to
explain it - I'll read and learn!

> my @instrings = (
> 'foo comes in here',
> 'bar sometimes comes in',
> 'baz comes in here',
> );
>
> for my $sample (@instrings)
> {
> for my $i (0..$#template)
> {
> if ( $sample =~ /$template[ $i ]{'regexp'}/ ) {
> print eval $template[ $i ]{'sentence'};
> }
> }
> }


this also works. But is it not dangerous if the instrings are provided
by potentially dangerous users?

 
Reply With Quote
 
sln@netherlands.com
Guest
Posts: n/a
 
      12-03-2010
On 3 Dec 2010 18:31:34 GMT, Martin Keiter <(E-Mail Removed)> wrote:

>On 2010-12-03, (E-Mail Removed) <(E-Mail Removed)> wrote:
>
>> If you going to use eval, you could always use the suggs posted
>> by others with something like this.
>>
>> -sln
>>
>> use strict;
>> use warnings;
>>
>> my @template = (
>> { regexp => q{(.*) comes in},
>> sentence => qq{"\$1 is here!\\n"}
>> },
>> { regexp => q{(.*) sometimes comes in},
>> sentence => qq{"\$1 is sometimes there!\\n"}
>> },
>> );

>
>I definitely have to learn about all this quoting! (you don't need to
>explain it - I'll read and learn!
>
>> my @instrings = (
>> 'foo comes in here',
>> 'bar sometimes comes in',
>> 'baz comes in here',
>> );
>>
>> for my $sample (@instrings)
>> {
>> for my $i (0..$#template)
>> {
>> if ( $sample =~ /$template[ $i ]{'regexp'}/ ) {
>> print eval $template[ $i ]{'sentence'};
>> }
>> }
>> }

>
>this also works. But is it not dangerous if the instrings are provided
>by potentially dangerous users?


Eval in itself is not dangerous, its what's in the eval after its code.
If, after its code, its result is a STRING scalar as opposed to bareword functions,
thats all it is. It depends on how you quote it.

Consider this:

print eval qq{"system(\\"dir aa.*\\");\\n"};
print eval qq{system("dir aa.*");};

I think the first cannot be executed, so if you set up
'sentence' by qq{ " <capture from user> "} you are quoting "" and it
( here ^ and here ^ )
is a scalar.
Anyway, thats the theory I think, but there could be oddities I guess.

-sln
 
Reply With Quote
 
sln@netherlands.com
Guest
Posts: n/a
 
      12-04-2010
On Fri, 03 Dec 2010 11:18:25 -0800, (E-Mail Removed) wrote:

>On 3 Dec 2010 18:31:34 GMT, Martin Keiter <(E-Mail Removed)> wrote:
>
>>On 2010-12-03, (E-Mail Removed) <(E-Mail Removed)> wrote:
>>
>>> If you going to use eval, you could always use the suggs posted
>>> by others with something like this.
>>>

[...]
>>this also works. But is it not dangerous if the instrings are provided
>>by potentially dangerous users?

>
>Eval in itself is not dangerous, its what's in the eval after its code.
>If, after its code, its result is a STRING scalar as opposed to bareword functions,
>thats all it is. It depends on how you quote it.
>
>Consider this:
>
> print eval qq{"system(\\"dir aa.*\\");\\n"};
> print eval qq{system("dir aa.*");};
>
>I think the first cannot be executed, so if you set up
>'sentence' by qq{ " <capture from user> "} you are quoting "" and it
> ( here ^ and here ^ )
>is a scalar.
>Anyway, thats the theory I think, but there could be oddities I guess.
>


I'm going to have to backtrack on this whole thing.
So forget everything I said with the eval "" format.
It is not safe at all if using external, possibly malicious data.

The docs say that eval BLOCK is compiled only once. But that won't
do any good for dynamic variable substitution ala \$var.
The eval "" form will recompile every time.

The fact is that if a user knows (or guesses) your statement form,
he/she will be able to splice in code, in any construction of eval "".

I see no way around it, it is dangerous, so use another method.
Test case:

my $val = ").system('dir a*.*').qq(";
eval "print qq($val)";

-sln
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Finding a string inside string arnuld C Programming 3 11-23-2010 09:49 AM
Put variables into member variables or function variables? tjumail@gmail.com C++ 9 03-23-2008 04:03 PM
good practice to initalize all instance variables with type String to emptry string?? Matt Java 4 06-23-2004 06:14 AM
Problem with inside to inside traffic after upgrading PIX 515 Cisco 5 06-15-2004 06:34 AM
Dynamic temp. datagrid col.gen. -Session access inside a class inside a UserCtrl Andy Eshtry ASP .Net 0 03-01-2004 11:48 PM



Advertisments