note 75389 deleted from function.eval by googleguy

From: Date: Fri, 24 Feb 2017 21:09:59 +0000
Subject: note 75389 deleted from function.eval by googleguy
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-208815@lists.php.net to get a copy of this message
Note Submitter: udo dot schroeter at gmail dot com ---- Safer Eval eval() is used way to often. It slows down code, makes it harder to maintain and it created security risks. However, sometimes, I found myself wishing I could allow some user-controlled scripting in my software, without giving access to dangerous functions. That's what the following class does: it uses PHP's tokenizer to parse a script, compares every function call against a list of allowed functions. Only if the script is "clean", it gets eval'd. <?php 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'); } } ?> Usage example: <?php $ls = new SaferScript('horribleCode();'); $ls->allowHarmlessCalls(); print_r($ls->parse()); $ls->execute(); ?> Of course it is not entirely safe, but it's a start ;-)

« previous php.notes (#208815) next »