[Python-Dev] PEP 215 redux: toward a simplified consensus?

Paul Prescod paul@prescod.net
Mon, 25 Feb 2002 13:37:26 -0800


Jeff Epler wrote:
> 
> ...
> 
> Imagine that you have:
>     def print_crypted_passwd(name, plaintext, salt="Xx"):
>         crypted = crypt.crypt(plaintext, salt)
>         print _("""%(name)s, your crypted password is %(crypted)s.""") % locals()
> 
> and that some crafty devil translates this as
>     msgstr "%(name)s, your plaintext password is %(plaintext).  HA HA HA"
> 
> i.e., the translator (or other person who can influence the format
> string) can access other information in the dict you pass in, even if
> you didn't intend it.

Right. I don't claim that this is a killer problem. I'm actually much
more concerned about the usability aspects. But if we can improve
security at the same time, then lets.

> Personally, I tend to view this as showing that using % locals() is
> unsanitary.  But that means that the problem is in using the locals()
> dictionary, a problem made worse by making the use of locals() implicit.

If it is done a compile time then the crafty devil couldn't get in the
alternate string!

On the other hand, if you're doing runtime translation stuff then of
course you need to use a runtime function, like "%" or maybe a new
"interpol". I am not against the existence of such a thing. I'm against
it being the default way to do interpolation. It's like "eval" a
compile-time tool that sophisticated users have access to at runtime.

> (And under $-substitution, if locals() is implicit, how do I substitute
> with a dictionary other than locals()?

Well I don't think you should have to, because you could use the
"interpol" function (maybe from the "interpol" module). But anyhow, your
question has a factual answer and you already gave it!

>     def print_crypted_passwd(accountinfo):
>         def really_subst(name, crypted):
>             return $"$name, your crypted password is $crypted"
>         print really_subst(accountinfo.name, accountinfo.crypted)
> or
>     def print_crypted_passwd(accountinfo):
>         name = accountinfo.name
>         crypted = accountinfo.crypted
>         print $"$name, your crypted password is $crypted"

This last one looks very clear and simple to me! What's the problem with
it?

Still, I don't argue against the need for something at runtime -- as a
power tool. Either we could just keep "%" or make a function. 

Okay, so my proposal for $ doesn't do everything that % does. It was
never spec'd to do everything "%" does. For instance it doesn't do float
formatting tricks.

 Paul Prescod