Home > Uncategorized > eval( “round 2″ )

eval( “round 2″ )

In my previous post entitled Don’t be lazy. Don’t use eval(), I outlined a few reasons why eval() is a bad (if really, really, cool) function to use.  So bad for programmers (both practically and rhetorically) in fact, that my thesis has become to forget it’s very existence.  From that article:

we are spoiled.  All of us.  We are lulled into a false sense of security by believing that throwing more (and better) hardware at a problem is a sufficient excuse for writing poor code, shoddy algorithms, and overall paying less attention to detail.  Don’t get me wrong, Jeff’s argument is carefully thought out and well presented.  But I take it with a grain of salt.  In fact, lots of salt.  Don’t use fast hardware as an excuse to be lazy.  Where does the habit of eschewing proper paradigm and using your hardware as a crutch stop?

There are several points in that paragraph I think are worth noting.

  1. Yes, programmer time is expensive, and hardware is cheap.  There is a lot (a lot) of store to be set by simply getting  job X done quickly.  And, in certain circumstances, more hardware is the way to go.  Some problems can’t be solved by reducing algorithmic complexity and micro-optimizing code at the assembly level – some problems, by nature, require scale.  But that doesn’t mean that we can abandon complexity theory, cast memory consumption to the wind, and start blowing processor cycles on pointless memory lookups for every program we generate.
  2. eval(), in any language, is a security risk.  Perhaps that risk is minimized when running a sandbox, but there is still risk.  And if someone is determined enough to break something, they’re going to do it anyway.  The old adage “locks only keep honest men honest” applies here.  Why make it that much easier?  PHP and JavaScript can’t sandbox though, so you’d be living a fools paradise to use eval() in those places.  In Python, sure, you’ve got your “safe zone”.  But, as several readers have pointed out, there are still ways to exploit the system.  A precaution to this of course, is to perform input scrubbing, before running eval().  Ensure that all identifiers strung together in your to-be-eval()’d code are valid tokens in their own right.  But – at that point, you’re spending so much time worrying about hand-holding the code going through eval() that you might as well have just programmed it yourself using iteration, function pointers, callbacks, and the like.  The argument at the heart of the eval() security debate lies along the same lines as “blacklisting” versus “whitelisting”.  Cleansing eval() input is blacklisting.  Choosing an alternative method of doing the same thing without eval() is whitelisting.  This post traveled through a number of firewalls to reach your eyes.  Firewalls are whitelists.  Symantec is a blacklist.  Which fail more frequently, firewalls or antivirus programs?
  3. eval() can evoke massive laziness.  There have been about three times can recall considering it’s use (yes, against my own thesis).  Each time, I sat back, and thought about an alternative solution.  Each time, I was able to envision a module designed without eval() – and the said alternative designs were always more architecturally sound than the code produce when eval() was thrown in the mix.  “But it still would have been quicker to use eval()” you might say.  And you’d be right.  In the short term. Overall, maintenance would be more difficult, readability and reusability suffer, bugs become more difficult to track (even with unit testing) and you’ve done neither yourself, nor anyone else, any favors in taking the cheap route.

All that having been said, one reader noted that without eval(), Firebug (a web development plugin for Firefox without which I’d be lost) would not be possible.  I disagree with that statement.  I use Firebug daily, and I’ve used the console to run code on the fly a grand total of two times – and one of them was just for the sake of trying it.  Firebug presents such advanced reporting (both in DOM traversal, scripting errors, and traffic analyzation) that I simply don’t use the console in that fashion – and I don’t see how anyone else would need to rely on it.  I understand that it’s widely used – my point is that it’s in no way necessary to practically debug web apps, or to rhetorically advance the state of the art of programming, metaprogramming, et. al.  However, it’s a widely used feature by many fine folk I’d consider top-notch developers, so there you have it.

In class, Dr. Parson presented us with a direct example of how eval() is used in some of his upper level classes.  He said that eval() is used to generate functions which get attached to classes (and thus become members) at runtime, saving the developer many pointless repetitive keystrokes writing banal code.  I agree – eval() can have a purpose here.  But not in the production system.  No – a more responsible use of eval() would be in a developer script to generate these methods in a blank file, and then copy/paste the code into the class definition.  You get the same effect: developers hitting less keys (here, here!) but you avoid the pitfalls of having eval() run every time your application fires up.

Those who claim that Python (and PHP, JavaScript, et. al.) are themselves giant eval()s are absolutely correct in their assertion; however they draw illegitimate conclusions from the fact.  That premise isn’t sufficient ground to argue that eval() is just dandy.  This type of faux logic is tantamount replacing the drivers seat of your sedan with a Go-Kart – you could make a hundred arguments in favor of doing so, but at the end of th day, it just doesn’t make sense.

For those of you who caught my minor rhetorical shift there, you’ll note that I’m essentially qualifying my thesis with the following: in the final product.  Developers create throw-away one-time “scriptlets” all the time to get quick and dirty jobs done.  I go through several per day, just in my quest to have the computer do what it’s better than me at (which is iteratively following rules).  Go ahead – instantiate a Knife object, invent some code involving butter, toss it to eval(), slam that in a loop, and run it until your process reaches it’s virtual memory limit* – but that type of thing appears in your final product (the code that matters to everyone else), then I submit that you could be doing a better job.  Perhaps you aren’t doing a bad job, but you could be doing better.  Maybe I’m a perfectionist, maybe I’m just a little loopy, but whenever I get the feeling that I could be doing something better, it bugs me until I go back and address it.

*This reference comes from an absolutely hilarious quip Dr. Parson made at the end of his rebuttal of the original post.

  1. Brian
    June 15th, 2009 at 14:55 | #1

    The problem with your bold claims is that you are using your extremely limited experience in programming as a basis for your argument. In particular:

    “I use Firebug daily, and I’ve used the console to run code on the fly a grand total of two times – and one of them was just for the sake of trying it.”

    It would seem you haven’t done much serious javascript debugging, or at the very least don’t understand how helpful the console can be in doing so. Don’t impose your own limitations on others. You sound absolutely ridiculous using this example as a basis for argument.

    Moving on…

    “PHP and JavaScript can’t sandbox though, so you’d be living a fools paradise to use eval() in those places.”

    Again, bold claims without a true understanding of what you’re talking about. Sandboxing is not a function of any particular language. Python doesn’t have built-in sandboxing with it’s eval. Sand boxing is the act of running code in a process with limited privileges. It is completely independent of the code being run. What’s particularly funny about your javascript comment is that the vast majority of javascript written is run within a sand box, right inside the browser.

    Just a bit of advice if you plan on working as a programmer. Stop assuming you know everything. You’ll be much more successful if you assume you know nothing.