note 86466 added to function.php-check-syntax
| From: | nicolas dot grekas+php at gmail dot com | 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