note 103360 added to function.eval

From: Date: Sat, 09 Apr 2011 11:17:08 +0000
Subject: note 103360 added to function.eval
Groups: php.notes 
Request: Send a blank email to php-notes+get-178656@lists.php.net to get a copy of this message
If you really want a bullet-proof eval, you can use a socket_pair and fork(). (Not tested under windows). <?php function lookupErrorCode($errno) { static $lookup = false; if ($lookup == false) foreach (array("E_ERROR", "E_WARNING", "E_PARSE", "E_NOTICE", "E_CORE_ERROR", "E_CORE_WARNING", "E_COMPILE_ERROR", "E_COMPILE_WARNING", "E_USER_ERROR", "E_USER_WARNING", "E_USER_NOTICE", "E_STRICT", "E_RECOVERABLE_". "ERROR", "E_DEPRECATED", "E_USER_DEPRECATED") as $k => $v) $lookup[1<<$k] = $v; return (!empty($lookup[$errno]) ? $lookup[$errno] : "UNKNOWN"); } function child_exit_handler($socket = NULL) { static $paired_socket = false; if ($socket || $socket === false) return $paired_socket = $socket; if ($paired_socket) { $e = error_get_last(); $result = "ERROR_" . lookupErrorCode($e["type"]) . ": {$e["message"]}"; if (socket_write($paired_socket, $result, strlen($result)) === false) echo "socket_write() failed. Reason: ".socket_strerror(socket_last_error($sockets[0])); socket_close($sockets[0]); } exit(2); # Child Process Dies, writing an error to it's paired socket. } function forked_eval($eval) { $sockets = array(); /* On Windows we need to use AF_INET */ $domain = (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' ? AF_INET : AF_UNIX); /* Setup socket pair */ if (socket_create_pair($domain, SOCK_STREAM, 0, $sockets) === false) { echo "socket_create_pair failed. Reason: ".socket_strerror(socket_last_error()); } switch ($child = pcntl_fork()) { case -1: throw new Exception("Could not fork"); case 0: # Child Thread register_shutdown_function("child_exit_handler"); child_exit_handler($sockets[0]); # Register the socket $result = serialize(eval($eval)); child_exit_handler(false); # We didn't crash if (socket_write($sockets[0], $result, strlen($result)) === false) echo "socket_write() failed. Reason: ". socket_strerror(socket_last_error($sockets[0])); socket_close($sockets[0]); exit(3); default : # Parent Thread if (($nread = socket_recv($sockets[1], $data, 1<<16, 0)) < 1) echo "socket_read() failed. Reason: ".socket_strerror(socket_last_error($sockets[1])); if (!strncmp($data, "ERROR_", 6)) { return substr($data, 6); # throw new Exception(substr($data, 6)); } socket_close($sockets[1]); return unserialize($data); } } function safe_eval($cmd, $str = false, $file = false, $line = false, $context = false) { static $err_strings = array(); if ($cmd === true) return count($err_strings) ? $err_strings : false; if ($str !== false) return ($err_strings[] = lookupErrorCode($cmd) . ": $str in $file on line $line") && true; $err_strings = array(); $old_error_handler = set_error_handler(__FUNCTION__, E_ALL); $rv = @eval("return true; $cmd") ? forked_eval($cmd) : ($or = error_get_last()) && call_user_func_array(__FUNCTION__, $or); restore_error_handler(); return $rv; } foreach (array( "return sleep(2) && foobar();" , "return date('Y-m-d');" , "return touch('/error/error/error') ? 'OK' : 'Failed';" , "return ==" , "return 2 + array();" , "return foobar();" , "return 2;") as $cmd) { printf("\nAttempting to evaluate: $cmd\n"); $rv = safe_eval($cmd); printf("%s\n", ($e = safe_eval(true)) ? "ERROR: $e" : "Result: $rv"); } ?> ---- Server IP: 117.55.229.1 Probable Submitter: 124.190.251.137 ---- Manual Page -- http://www.php.net/manual/en/function.eval.php Edit -- https://master.php.net/note/edit/103360 Del: integrated -- https://master.php.net/note/delete/103360/integrated Del: useless -- https://master.php.net/note/delete/103360/useless Del: bad code -- https://master.php.net/note/delete/103360/bad+code Del: spam -- https://master.php.net/note/delete/103360/spam Del: non-english -- https://master.php.net/note/delete/103360/non-english Del: in docs -- https://master.php.net/note/delete/103360/in+docs Del: other reasons-- https://master.php.net/note/delete/103360 Reject -- https://master.php.net/note/reject/103360 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#178656) next »