[Python-Dev] PEP_215_ (string interpolation) alternative EvalDict

Steven Majewski sdm7g@Virginia.EDU
Mon, 14 Jan 2002 17:59:08 -0500 (EST)


On Mon, 14 Jan 2002, Paul Prescod wrote:

> Steven Majewski wrote:
> >
> >....
> >
> >  But if you're going to allow interpolation of the results of arbitrary
> > function into a string, it's going to be a security problem whether
> > or not you use 'eval' to do it. My code hides the eval in the object's
> > python code. u" strings would hide the eval in the C code. How is one
> > more or less secure than the other.
>
> I think you mean $" strings, not u" strings. Given:

Oops. Yes.

>
> a = $"foo.bar: $foo.bar(abc, 5)"
>
> I can translate that *at compile time* to:
>
> a = $"foo.bar: %s" % foo.bar(abc, 5)
>
> No runtime evaluation is necessary. So I see no security issues here. On
> the other hand, evaldict really does have the same semantics as an eval,
> right? Probably it is no more or less dangerous if you only do a single
> level of EvalDict-ing. But once you get into multiple levels you could
> get into a situation where user-provided code is being evaluated. The
> first level of EvalDict incorporates the user-provided code into the
> string and the second level evaluates it.

The multiple level was an addition to the last version because that
was what some people expressed a desire for in the earlier string
interpolation discussion. EvalDict2 does a single level eval.
( Again: that seems to me to be an argument for several alternative
  object versions rather than one builtin syntax change. )


> Ping's current runtime implementation does use "eval" but you could
> imagine an alternate implementation that actually parses the relevant
> parts of the string according to the Python grammar, and merely applies
> the appropriate semantics. It would use "." to trigger getattr, "()" to
> trigger apply, "[]" to trigger getitem and so forth. Then there would be
> no eval and thus way to eval user-provided code.

 The same things holds for an object implementation. eval isn't required
for an implementation. But EVERY implementation of that semantics allows
implicit function calls. ( I was going to say 'hidden' function calls,
but I'll admit that may be provocative/argumentative.)
 Your point about compile time optomization holds here: yes, the
builtin syntax version allows much of that analysis to be done at
compile time, while the object version would need to do all of the
analysis on the fly at execution. However, as I noted -- the object
implementation would allow customizing a restricted environment
( which is a simple security implementation than code analysis.)
And having an explicit argument for the namespace allows more control,
as well as reminding you of the magic going on behind the curtains.
At least if there's a security problem, you have somewhere to look
for holes other than the Python C source code.

 If I keep an eval based implementation, I probably ought to make
a restricted __builtin__ the default.

-- Steve