4

In a project I'm currently working for, we're considering putting system() into php.ini's disable_functions declaration. Now, one meta-module of ours which would ultimately also fall victim to this restriction is syntax-checking files with system("php -l"); calls - prompting me to hunt for alternatives.

Turns out there used to be a php_check_syntax(), but not only did that not restrict itself to merely checking syntax and went on to include the file if it was syntactically valid, but it's been removed as of PHP 5.0.5. The manual suggests php -l in its place, but given that I'm sure disabling system call functions in PHP is a fairly common practise, I'm wondering if there is an accepted, 'better' way of syntax checking PHP files from within PHP files.

(I'm not hell-bent on this, by the way; a 'no' perfectly suffices (and I expect it, really). We can excempt the module from this restriction - but I'm asking this question both out of curiosity as well as in hope of a more graceful solution.)

pinkgothic
  • 6,081
  • 3
  • 47
  • 72
  • Include the file and catch the exception :P – Ignacio Vazquez-Abrams Oct 05 '10 at 08:23
  • 1
    @Ignacio: Just in case that isn't tongue-in-cheek (though I think it is): Converting FATAL ERRORs to Exceptions with an error handler doesn't work, not to mention that including the file would execute it, which this module isn't supposed to do. – pinkgothic Oct 05 '10 at 08:37
  • Definitely tongue-in-cheek. The proper way would be to tell the compiler to compile it and then catch the exception. – Ignacio Vazquez-Abrams Oct 05 '10 at 08:39
  • exactly that is what she can't do (due to disabled system() function) and what the php_ckeck_syntax() manual page tells her to do. – ITroubs Oct 05 '10 at 08:44

3 Answers3

3

I found an alternative using PECL runkit_lint_file().

It does the same check as php_check_syntax().

I think it's worth a look.

ITroubs
  • 11,094
  • 4
  • 27
  • 25
  • Ooh! Absolutely. That looks precisely like what I was looking for. I wonder if we have PECL runkit here -- off to investigate! Out of curiosity, do you know of any security advisories about this function (though they'd be anecdotal for me, the files being checked are trusted)? – pinkgothic Oct 05 '10 at 08:40
  • as far as i can read it from the manual it should be safe because it just trys to parse the php file and then returns if the parsing was successfull. it shouldn't do any execution so i THINK it is safe ;-) – ITroubs Oct 05 '10 at 08:43
  • Well, there have historically been security advisories for functions like `highlight_file()`, too, because you could get around the 'just parsing' that they were supposed to do with the right payload - hence the question. But, as I said, anecdotal - I'm not worried either way in my case, just a curious cookie. – pinkgothic Oct 05 '10 at 08:46
  • ahh i get your point. well i don't have any experience using runkit so i can't tell anything about buffer overrun security problems. it was just a fast search i did – ITroubs Oct 05 '10 at 08:51
  • Thank goodness other people's google-fu is better than mine! :) Thanks, ITroubs. (We don't have PECL runkit, but that can be remedied, so I'm accepting your answer. Thank you!) – pinkgothic Oct 05 '10 at 09:03
  • after almost 10 years of googleing it becomes more effective to search something on google then to ask it in stackoverflow except when the answer is not given yet and therefore not in google – ITroubs Oct 05 '10 at 09:14
2

This can be also an option: When (if ever) is eval NOT evil?

And seems more faster:

$nTestTiempo0 = microtime(true);
exec('php -l yourfile.php',$arrMsgError,$nCodeError);
$nTestTiempo1 = microtime(true);
echo "\n", '<p>Time in verify file with exec : '.($nTestTiempo1-$nTestTiempo0).' secs.</p>';
//Time in verify file with exec : 0.033198118209839 secs.

$nTestTiempo0 = microtime(true);
ob_start ();
var_dump(eval('return true; if(0){?>'.file_get_contents('yourfile.php').'<?php };'));
$arrMsgError = explode("\n",trim(ob_get_contents()));
ob_end_clean();
$nTestTiempo1 = microtime(true);
echo "\n", '<p>Time in verify file with eval : '.($nTestTiempo1-$nTestTiempo0).' secs.</p>';
//Time in verify file with eval : 0.00030803680419922 secs.

$nTestTiempo0 = microtime(true);
@system('php -l yourfile.php',$nCodeError);
$nTestTiempo1 = microtime(true);
echo "\n", '<p>Time in verify file with system : '.($nTestTiempo1-$nTestTiempo0).' secs.</p>';
//Time in verify file with system : 0.032964944839478 secs.
Community
  • 1
  • 1
Galled
  • 4,146
  • 2
  • 28
  • 41
  • +1 for a novel approach! (By the way, `microtime` has a parameter you might want to look at :) It'd make your example code much more compact and easier to read.) Though, for completion's sake: We disallow `eval`, too, albeit through different channels. – pinkgothic May 10 '11 at 21:01
0

See our PHP Formatter. This command-line tool takes a well-formed PHP file and formats it nicely.

Not only does it format, it also syntax checks, and returns command line status telling you whether the file was "well-formed"; it contains a full PHP 5 parser. Because it is a command line tool it would be easy to launch from a PHP script if that's what you need to do, and by checking the returned status you would know if the file was legal.

Ira Baxter
  • 93,541
  • 22
  • 172
  • 341
  • "This command-line tool" -- I'm trying to go away from the command line, though - the idea is to forbid anything in PHP that calls it, after all (`system`/`passthru`/etc). Thanks nonetheless, though. :) – pinkgothic Oct 07 '10 at 07:12