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

Jeff Epler jepler@unpythonic.dhs.org
Mon, 25 Feb 2002 15:20:36 -0600

On Mon, Feb 25, 2002 at 03:55:15PM -0500, Fred L. Drake, Jr. wrote:
> Paul Prescod writes:
>  > Plus, operator-based evaluation has some security implications that
>  > compile time evaluation does not. In particular, if the left-hand thing
>  > can be any string then you have the potential of accidentally allowing
>  > the user to supply a string that allows him/her to introspect your local
>  > variables. That can't happen if the interpolation is done at compile
>  > time.
> I'm not sure I understand this.

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.

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.

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

    def print_crypted_passwd(accountinfo):
	print "%(name)s, your crypted password is %(crypted)s." \
		    % accountinfo.__dict__
    def print_crypted_passwd(accountinfo):
	def really_subst(name, crypted):
	    return $"$name, your crypted password is $crypted"
	print really_subst(accountinfo.name, accountinfo.crypted)
    def print_crypted_passwd(accountinfo):
	name = accountinfo.name
	crypted = accountinfo.crypted
	print $"$name, your crypted password is $crypted"