Making Evil eval() Safer Date: 2007-05-26 19:52:55
If you're thinking about using eval() - don't do it. Just don't. Few things get me as riled up as reviewing source code and discovering totally unnecessary eval() statements. That goes for any language, but let's talk about PHP here. I'd argue that 99% of the time, this is a complete waste of processor time, makes the script harder to read, harder to debug, and it's a huge security risk.
People use eval() for all sort of sillyness:
Reading JSON or other data formats: dude, use the built-in JSON functions or other appropriate functionality that's already there.
Totally useless code fragments like $dynamicCall = 'myCoolFunction();'; eval($dynamicCall);: there is a perfectly good way to do this, just write $dynamicCall(); It will work. It looks better. It will get you laid.
Stupid attempts to obfuscate your code: think about it for a second and come to the conclusion that every village idiot can decode your precious, nobel-prize-winning code so easily it's not even funny. So stop being silly.
There are valid scenarios for using eval(). One of them would be allowing limited user-defined scripting in your apps. But with the way PHP handles eval(), you can only do this if you trust the user completely. However, there is a way to make your user-defined eval() safer by checking it first for illegal function calls. You can use something like this to check if your user-provided code is clean:
Still, pretty unsafe. But it's a start.
People use eval() for all sort of sillyness:
Reading JSON or other data formats: dude, use the built-in JSON functions or other appropriate functionality that's already there.
Totally useless code fragments like $dynamicCall = 'myCoolFunction();'; eval($dynamicCall);: there is a perfectly good way to do this, just write $dynamicCall(); It will work. It looks better. It will get you laid.
Stupid attempts to obfuscate your code: think about it for a second and come to the conclusion that every village idiot can decode your precious, nobel-prize-winning code so easily it's not even funny. So stop being silly.
There are valid scenarios for using eval(). One of them would be allowing limited user-defined scripting in your apps. But with the way PHP handles eval(), you can only do this if you trust the user completely. However, there is a way to make your user-defined eval() safer by checking it first for illegal function calls. You can use something like this to check if your user-provided code is clean:
class SaferScript {
var $source, $allowedCalls;
function SaferScript($scriptText) {
$this->source = $scriptText;
$this->allowedCalls = array();
}
function allowHarmlessCalls() {
$this->allowedCalls = explode(',',
'explode,implode,date,time,round,trunc,rand,ceil,floor,srand,'.
'strtolower,strtoupper,substr,stristr,strpos,print,print_r');
}
function parse() {
$this->parseErrors = array();
$tokens = token_get_all(''.'php '.$this->source.' ?'.'>');
$vcall = '';
foreach ($tokens as $token) {
if (is_array($token)) {
$id = $token[0];
switch ($id) {
case(T_VARIABLE): { $vcall .= 'v'; break; }
case(T_STRING): { $vcall .= 's'; }
case(T_REQUIRE_ONCE): case(T_REQUIRE): case(T_NEW): case(T_RETURN):
case(T_BREAK): case(T_CATCH): case(T_CLONE): case(T_EXIT):
case(T_PRINT): case(T_GLOBAL): case(T_ECHO): case(T_INCLUDE_ONCE):
case(T_INCLUDE): case(T_EVAL): case(T_FUNCTION): {
if (array_search($token[1], $this->allowedCalls) === false)
$this->parseErrors[] = 'illegal call: '.$token[1];
}
}
}
else
$vcall .= $token;
}
if (stristr($vcall, 'v(') != '')
$this->parseErrors[] = array('illegal dynamic function call');
return($this->parseErrors);
}
function execute($parameters = array()) {
foreach ($parameters as $k => $v)
$$k = $v;
if (sizeof($this->parseErrors) == 0)
eval($this->source);
else
print('cannot execute, script contains errors');
}
}
$ls = new SaferScript(implode("\n", file('example.php')));
$ls->allowHarmlessCalls();
print_r($ls->parse());
$ls->execute();
Still, pretty unsafe. But it's a start.
Comments
Name
Email
URL(optional)
Text




