Re: perlfaq4: expanding variables in strings
[email protected] (Brian McCauley)
| Newsgroups | perl.perlfaq.workers |
|---|---|
| Message-ID | <[email protected]> |
Kevin Meltzer <[email protected]> writes: > I'm also, specifically, not convinced this change is the best: > > - $text =~ s/\$(\w+)/${$1}/g; # no /e needed > + $text = '@{[ system "rm -rf /" ]}' That should not be seen as a single change. One bit has been removed. Unrelated to that, another bit has been inserted. It's just an artifact that diff sees it as a change. > Especially, since that is a poor use of system(), I cannot see how it can be relevant that the fact that something an attacker may do is poor style. > and -T should catch it. Aggh! You've got the wrong end of the stick. -T will completely prevent externally sourced strings from being used in eval(). But this whole FAQ is about using externally sourced strings in eval(). It doesn't say so explicitly in the question, but in practice the strings to be interpolated come from a file or database of message templates. It therefore does not make sense to say that -T will protect you. (And IIRC DBI doesn't taint by default anyhow). > So, as Robert said, "People still learn perl poorly, and still write > things "the old bad way" that needs to be fixed." I didn't understand the relevance of it then. I don't understand the relevance when you repeat it. > Anyways, I wouldn't mind seeing the patch reworked, even if in smaller > bits at a time to get it "just right". Personally I'd settle for "a damn sight better than it was" but in defference to that request here's my latest attempt to incorporate your suggestions into answer. I'm not going to express it as a patch at this stage as that seems to have caused confusion: How can I expand/interpolate variables in text strings? You can process a string through Perl's interpolation engine like this: $text = 'this has a $foo in it...\n ...and a $bar'; # Assume $text does not contain "\nEND\n" chop ( $text = eval "<<END\n$text\nEND\n" ); die if $@; This will not work, and for good reason, if $text is com- ing form a tainted source. For explanation of how $text could contain arbitrary Perl code see ``How do I expand function calls in a string?'' in this section of the FAQ. If $text is coming from a source external to the Perl script (typically a file) and you would content to trust executable code from that source then you simply make the source untainted. This is no more or less dangerous than using "do()". If you do not trust the source that much then you can limit and launder the parts of the string that are passed to eval() something like this: $text =~ s/(\$\w+)/$1/eeg; # needed /ee, not /e This still gives unrestricted access to your scalar vari- ables. It is often better to use a hash: %user_defs = ( foo => 23, bar => 19, ); $text =~ s/\$(\w+)/$user_defs{$1}/g; For other variations on the theme of text templates see the sprintf() function and numerous modules on CPAN.