How do you set up a stack?

5 views
Skip to first unread message

the_2nd_coming

unread,
May 8, 2001, 10:01:35 PM5/8/01
to
hello,
I am a python/programming newbie (Python is my first language),
and I am writing a program that will be able to take a mathematical
function, that, as of right now, is restricted to Multiply and Divide with
one operator, (2/4 or 3*7). I want to be able for the end-user to be able
to type the function at the python prompt and to have the program create a
list of the characters in the list, I am using raw_input and I think I need
to implement a stack in order to pass each character to the list as I pop
them off the stack. this is good and all, however, I do not know how to
implement this.

this is what the layout is at this point:


function = raw_input("put your function hear")
.
. #this is where the stack will be implemented and the
. # charactors will be placed in the list.
operator = function_list[1] # item 1 will be the position of the operator
#in the list after any whitespace is striped.

if operator == "*": #the operator is the astrik
multiplication(function_list[0], Function_list[2])

else:
Division(Function_list[0], Function_list[2])

# the rest of the program

so, how do I implement a stack, and, is there any other way I could
acomplish this task?

thank-you in advance

Jeremy Petzold

Tyler Eaves

unread,
May 8, 2001, 10:39:14 PM5/8/01
to
On Wed, 09 May 2001 02:01:35 GMT, the_2nd_coming
<jpet...@twmi.rr.com> wrote:


try this code:

f=raw_input('>')
print eval(f)

the_2nd_coming

unread,
May 8, 2001, 10:43:00 PM5/8/01
to

> f=raw_input('>')
> print eval(f)

Thanks, while I know I should not feel stupid, since I am a newbie, I still
feel stupid :-)

I appreciate it.

Jeremy

Tyler Eaves

unread,
May 8, 2001, 10:47:23 PM5/8/01
to
On Wed, 09 May 2001 02:43:00 GMT, the_2nd_coming
<jpet...@twmi.rr.com> wrote:

Sure, np/ I remeber when I was a newbie, and it wasn't all that long
ago. Send me a copy when you finish it.

kosh

unread,
May 8, 2001, 11:17:05 PM5/8/01
to
Umm. While this solution will work I think there are some things that need
to be dealt with. Mainly you need to check f for items that should not be
in there. eval will evaulatuate any valid piece of python code so the other
things that can be done are large. This is a fairly large security risk at
this point I think. At the very least I would check if it has any letter
characters and if so not run then.

Tyler Eaves wrote:

>> #striped.

Nick Perkins

unread,
May 9, 2001, 2:05:33 AM5/9/01
to

don't feel stupid, it was a good question.

if you are learning python, it's not such a bad exercise,
and 'print eval(f)' doesn't really help you learn much.

..to make a stack..

any list can be used as a stack:

>>> a = [1,2,3,4,5]
>>> a.pop()
5
>>> a
[1, 2, 3, 4]
>>> a.append(99)
>>> a
[1, 2, 3, 4, 99]


( note that 'append' is used as the 'push' function )
we just pretend that the list is a stack, with the
'top' of the stack at the end of the list.

you can use one or two stacks to evaluate simple expressions..
go ahead and give it a try..

s71...@student.gu.edu.au

unread,
May 9, 2001, 2:06:15 PM5/9/01
to
kosh wrote:
>
> Umm. While this solution will work I think there are some things that need
> to be dealt with. Mainly you need to check f for items that should not be
> in there. eval will evaulatuate any valid piece of python code so the other
> things that can be done are large. This is a fairly large security risk at
> this point I think. At the very least I would check if it has any letter
> characters and if so not run then.

Eval will (should?) only evaluate legal pythonic numeric functions. This
actually covers quite a bit, but unless you define wierd class
structures that overwrite numerical operators to do non-numerical
operations, you shouldn't have to worry too much about using eval.

Simple maths.
>>> eval("1+2")
3

Math with complex numbers (Except "i" is replaced with "j" in python.
Ask the engineers why. *sighs*)
>>> eval("(1+2j)-3j")
(1-1j)

You can also import the math module and use these functions inside the
eval statement.
>>> import math
>>> eval("1+math.sqrt(2)")
2.4142135623730949

However, all of these are dealing with numbers. I'd be interested to see
if someone did have an example of a malicious eval use. (In fact I'd be
downright anxious to know of any eval security weaknesses. *grins*)

I try to eval a non-numerical statement.
>>> eval("print 'hello'")
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<string>", line 1
print 'hello'
^
SyntaxError: invalid syntax

Now I try a different statement that barfs on a different piece of
syntax.
>>> eval("if 1==1: print 'hello'")
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<string>", line 1
if 1==1: print 'hello'
^
SyntaxError: invalid syntax
>>>

In order to "evaluate" or execute a string as a command, rather than an
expression, the exec command has to be used. However, if you are really
paranoid, or would like to convert the following complex number
statements "1+32i" to correct python, "1+32j", look up the re module.

Anycase, have fun. You should have a great time with the language, and
with this newsgroup.

Joal Heagney/AncientHart

Michael Hudson

unread,
May 9, 2001, 4:28:11 AM5/9/01
to
s71...@student.gu.edu.au writes:

> In order to "evaluate" or execute a string as a command, rather than an
> expression, the exec command has to be used.

That's only what you think.

->> eval("eval(compile('print 1','','exec'))")
1

you can get around this by restricing the builtins

->> eval("eval(compile('print 1','','exec'))",{"__builtins__":{}})


Traceback (most recent call last):

File "<input>", line 1, in ?
File "<string>", line 0, in ?
NameError: name 'eval' is not defined

but this still leaves potential DoS attacks like

eval("'a'*(2**26)")

Don't eval user input, IOW.

Cheers,
M.

--
Sufficiently advanced political correctness is indistinguishable
from irony. -- Erik Naggum

Duncan Booth

unread,
May 9, 2001, 4:31:07 AM5/9/01
to
"Nick Perkins" <nper...@home.com> wrote in
<N65K6.97828$HF.22...@news4.rdc1.on.home.com>:

> any list can be used as a stack:
>

<snip>


>
> ( note that 'append' is used as the 'push' function )
> we just pretend that the list is a stack, with the
> 'top' of the stack at the end of the list.
>

If you prefer to have a type called a Stack you can always do this:
>>> class Stack:
... def __init__(self):
... self.stack = []
... self.push = self.stack.append
... self.pop = self.stack.pop
...
>>> s = Stack()
>>> s.push(1)
>>> s.push(2)
>>> s.pop()
2
>>> s.pop()
1


--
Duncan Booth dun...@rcp.co.uk
int month(char *p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3"
"\6\7\xb\1\x9\xa\2\0\4"];} // Who said my code was obscure?

Fredrik Lundh

unread,
May 9, 2001, 4:42:29 AM5/9/01
to
s71...@student.gu.edu.au wrote:
> However, all of these are dealing with numbers. I'd be interested to see
> if someone did have an example of a malicious eval use.

from the eff-bot guide to the standard library:

eval("__import__('os').remove('file')")
eval("__import__('os').system('rm -rf /')")
eval("'*'*1000000*2*2*2*2*2*2*2*2*2")

(etc)

eval("whatever", {"__builtins__": {}}) takes care of many
of them, but not memory/CPU attacks.

Cheers /F


kosh

unread,
May 9, 2001, 4:37:00 AM5/9/01
to
s71...@student.gu.edu.au wrote:

> kosh wrote:
>>
>> Umm. While this solution will work I think there are some things that
>> need to be dealt with. Mainly you need to check f for items that should
>> not be in there. eval will evaulatuate any valid piece of python code so
>> the other things that can be done are large. This is a fairly large
>> security risk at this point I think. At the very least I would check if
>> it has any letter characters and if so not run then.
>
> Eval will (should?) only evaluate legal pythonic numeric functions. This
> actually covers quite a bit, but unless you define wierd class
> structures that overwrite numerical operators to do non-numerical
> operations, you shouldn't have to worry too much about using eval.
>

Eval can evaluate any python expression by default. The other stuff you
tried were statements and as such they would need exec. I have some complex
thing being done with eval in places that are not numeric at all. However
it is checked thoroughly.

Remco Gerlich

unread,
May 9, 2001, 5:13:20 AM5/9/01
to
s71...@student.gu.edu.au <s71...@student.gu.edu.au> wrote in comp.lang.python:

> However, all of these are dealing with numbers. I'd be interested to see
> if someone did have an example of a malicious eval use. (In fact I'd be
> downright anxious to know of any eval security weaknesses. *grins*)

eval("getattr(__import__('os'), 'system')('ls')")

This only relies on builtin names. Finding more malicious commands than 'ls'
is left as an excercise for the reader.

--
Remco Gerlich

Alex Martelli

unread,
May 9, 2001, 5:48:03 AM5/9/01
to
<s71...@student.gu.edu.au> wrote in message
news:3AF98717...@student.gu.edu.au...
...

> Eval will (should?) only evaluate legal pythonic numeric functions. This

>>> eval('__import__("os").system("echo yeah right")')
yeah right
0
>>>

Not sure what you mean by 'should' here, but it definitely doesn't
work that way in Python. Guess what substrings could take the
place of that "echo yeah right" and possibly cause problems...:-).

> operations, you shouldn't have to worry too much about using eval.

DO worry any time you eval or exec code coming from a user
you don't trust 101%...:-). Taking precautions is better
than worrying, of course -- you can prepare dictionaries, to
be passed to eval as its namespace-environments, that will
take away all the dangerous builtin, and as you're at it you
might as well inject the useful math operations from the
math module's namespace, etc.

> However, all of these are dealing with numbers. I'd be interested to see
> if someone did have an example of a malicious eval use. (In fact I'd be
> downright anxious to know of any eval security weaknesses. *grins*)

Hmmm, is my example above sufficient...?

> I try to eval a non-numerical statement.

Statements are not a worry for eval (only for exec), but that's not
the point -- destructive behavior can easily be had in expressions
that include function calls to suitable library functions. So,
go through the list of builtins and only include those that are
truly needed for the expressions you want to eval (if any) -- I
expect '__import__' will not be there, for example:-).

>>> nobi={'__builtins__':None}
>>> eval('__import__("os").system("echo yeah right")',nobi)


Traceback (most recent call last):
File "<stdin>", line 1, in ?

File "<string>", line 0, in ?
NameError: There is no variable named '__import__'
>>>

Passing 'nobi' as the namespace for the eval removes all
built-ins, including in particular "import". We may do
better...:

>>> import math
>>> nobi.update(math.__dict__)
>>> # check nothing was broken
...
>>> eval('__import__("os").system("echo yeah right")',nobi)


Traceback (most recent call last):
File "<stdin>", line 1, in ?

File "<string>", line 0, in ?
NameError: There is no variable named '__import__'
>>> # ok, now check math works as intended
...
>>> eval('sin(0.3)',nobi)
0.29552020666133955
>>>


Not too much work, is it? And you may choose to do even
more, again without too much work, by examining all the
functions and variables the expression-in-string-form
may need, by splitting the eval step into a preliminary
compile() call, that gives you a code-object -- you
can check the names it uses and prompt the user for
variables you don't yet know about, e.g.:

>>> code=compile('sin(x)','<user-entered string>','eval')
>>> for name in code.co_names:
... if not nobi.has_key(name):
... value = raw_input("Variable %s:"%name)
... nobi[name] = float(value)
...
Variable x:0.3
>>> eval(code,nobi)
0.29552020666133955
>>>


Alex

pi...@cs.uu.nl

unread,
May 9, 2001, 6:40:02 AM5/9/01
to
>>>>> Tyler Eaves <ty...@tylereaves.com> (TE) writes:

TE> On Wed, 09 May 2001 02:01:35 GMT, the_2nd_coming
TE> <jpet...@twmi.rr.com> wrote:


TE> try this code:

TE> f=raw_input('>')
TE> print eval(f)

Which is equivalent to the simpler:
print input('>')
--
Piet van Oostrum <pi...@cs.uu.nl>
URL: http://www.cs.uu.nl/~piet [PGP]
Private email: P.van....@hccnet.nl

s71...@student.gu.edu.au

unread,
May 11, 2001, 12:41:50 PM5/11/01
to

Youchy. My bad. Sorry guys for opening my gab without checking back on
the documents. These posts are getting added to my python email
scrapbook.
Joal Heagney/AncientHart

the_2nd_coming

unread,
May 11, 2001, 9:48:27 PM5/11/01
to
Hey I would just like to thank everyone for giving their advice, it realy
helped alot :-)
Reply all
Reply to author
Forward
0 new messages