dynamic assigments

scattered tooscattered at gmail.com
Thu Mar 24 22:51:08 EDT 2011


On Mar 24, 7:18 pm, Steven D'Aprano <steve
+comp.lang.pyt... at pearwood.info> wrote:
> On Thu, 24 Mar 2011 14:39:34 -0700, scattered wrote:
> > Could try:
>
> >>>> my_list = [("x", 7), ("y", 8)]
> >>>> for pair in my_list: exec(pair[0] + " = " + str(pair[1]))
> >>>> x,y
> >>>> (7,8)
>
> Please don't ever do such a thing. The world has enough buggy software
> vulnerable to code injection attacks without you encouraging newbies to
> write more.
>
> If (generic) you, the programmer, can write
>
> my_list = [("x", 7), ("y", 8)]
> for pair in my_list:
>     exec(pair[0] + " = " + str(pair[1]))
>
> in your code, then you should stop messing about and just write:
>
> x = 7
> y = 8
>

Good question - though presumably the OP had some motivation for
wanting to do this dynamically. Possibly some sort of code-template
(though then it would probably make more sense to create a text file
which contains the bindings you want, which could then be expanded to
a full-fledged program).

> instead. The only time this technique is even *possibly* justified is if
> the contents of my_list comes from external data not known at compile-
> time.

Here is another possibility: you are using Python *interactively* in
solving cryptograms (as a matter of fact - I was doing exactly this
yesterday in trying to solve some Playfair ciphers). You have a
ciphertext that is a stream of letters in the range A...Z. You need to
consult frequencies of letters, pairs of letters, triples of letters,
and quadruples of letters that occur. So, you write a script that
steps through the cipher text, creates a dictionary which records
frequencies of strings of length <= 4, and, as an added convienence,
creates bindings of frequencies to these strings. Thus - if you want
to know how often, say, EFW occurs in the ciphertext you just type EFW
(rather than freq["EFW"]) and the Python shell returns the frequency.
While this example may seem far-fetched, I can easily imagine other
situations in which a user might want to create a large number of
bindings for interactive use. Maybe as a teacher (I'm a math teacher)
you have written a student-class which contains things like methods to
compute averages, return lists of missing assignments, etc. At the
prompt you run a script that creates a binding for each student in a
section to a student object so that you can just type something like
JohnDoe.missing() to get a list of their missing assignments. Just
because exec() *can* be misused doesn't mean that there aren't valid
uses for it. You would be foolish to run exec() on unparsed externally
supplied data - but perhaps you are running it on data that you
yourself have generated.

> But that means you're vulnerable to a hostile user injecting code
> into your data:
>
> my_list = [("import os; os.system('echo \"deleting all files...\"'); x",
> 7), ("y", 8)]
> for pair in my_list:
>     exec(pair[0] + " = " + str(pair[1]))
>
> Code injection attacks are some of the most common source of viruses and
> malware, far more common (and much easier to perform!) today than buffer
> overflows. If an unprivileged process can inject code into something that
> a privileged process is running, your computer is compromised.
>
> --
> Steven




More information about the Python-list mailing list