note 86466 added to function.php-check-syntax

From: Date: Mon, 20 Oct 2008 20:20:20 +0000
Subject: note 86466 added to function.php-check-syntax
Groups: php.notes 
Request: Send a blank email to php-notes+get-145525@lists.php.net to get a copy of this message
Hi again, here is my last contribution to the subject : this php_syntax_error() function returns false if there is no syntax error in $code, or an array($message, $line) if there is one (idea borrowed from kevin's code) . For exemple, php_syntax_error(' DELIBERTE PHP ERROR; ') returns array('unexpected T_STRING', 1) ;) Please note that the dead code sandbox IS important. A "return" at the beginning of the evaluated string can easily be broken: try eval('return; function strlen(){}') versus eval('if(0){function strlen(){}}'). <?php function php_syntax_error($code) { $braces = 0; $inString = 0; // First of all, we need to know if braces are correctly balanced. // This is not trivial due to variable interpolation which // occurs in heredoc, backticked and double quoted strings foreach (token_get_all('<?php ' . $code) as $token) { if (is_array($token)) { switch ($token[0]) { case T_CURLY_OPEN: case T_DOLLAR_OPEN_CURLY_BRACES: case T_START_HEREDOC: ++$inString; break; case T_END_HEREDOC: --$inString; break; } } else if ($inString & 1) { switch ($token) { case '`': case '"': --$inString; break; } } else { switch ($token) { case '`': case '"': ++$inString; break; case '{': ++$braces; break; case '}': if ($inString) --$inString; else { --$braces; if ($braces < 0) break 2; } break; } } } // Display parse error messages and use output buffering to catch them $inString = @ini_set('log_errors', false); $token = @ini_set('display_errors', true); ob_start(); // If $braces is not zero, then we are sure that $code is broken. // We run it anyway in order to catch the error message and line number. // Else, if $braces are correctly balanced, then we can safely put // $code in a dead code sandbox to prevent its execution. // Note that without this sandbox, a function or class declaration inside // $code could throw a "Cannot redeclare" fatal error. $braces || $code = "if(0){{$code}\n}"; if (false === eval($code)) { if ($braces) $braces = PHP_INT_MAX; else { // Get the maximum number of lines in $code to fix a border case false !== strpos($code, "\r") && $code = strtr(str_replace("\r\n", "\n", $code), "\r", "\n"); $braces = substr_count($code, "\n"); } $code = ob_get_clean(); $code = strip_tags($code); // Get the error message and line number if (preg_match("'syntax error, (.+) in .+ on line (\d+)$'s", $code, $code)) { $code[2] = (int) $code[2]; $code = $code[2] <= $braces ? array($code[1], $code[2]) : array('unexpected $end' . substr($code[1], 14), $braces); } else $code = array('syntax error', 0); } else { ob_end_clean(); $code = false; } @ini_set('display_errors', $token); @ini_set('log_errors', $inString); return $code; } ?> ---- Server IP: 195.221.21.36 Probable Submitter: 81.57.178.244 ---- Manual Page -- http://www.php.net/manual/en/function.php-check-syntax.php Edit -- https://master.php.net/note/edit/86466 Del: integrated -- https://master.php.net/note/delete/86466/integrated Del: useless -- https://master.php.net/note/delete/86466/useless Del: bad code -- https://master.php.net/note/delete/86466/bad+code Del: spam -- https://master.php.net/note/delete/86466/spam Del: non-english -- https://master.php.net/note/delete/86466/non-english Del: in docs -- https://master.php.net/note/delete/86466/in+docs Del: other reasons-- https://master.php.net/note/delete/86466 Reject -- https://master.php.net/note/reject/86466 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#145525) next »