0

I'm writing an application that will allow approved developers to submit php code to our database to be run at a later time.

I'm attempting to implement a system where before their code is run it is checked for any issues.

I found the following code at http://bytes.com/topic/php/answers/4819-before-eval-how-can-one-test-string-see-if-valid-php-code

function checkPHP($string) {
    $string = escapeshellcmd($string);
    exec("php -r \"$string\"",$output,$exit);
    if($exit==0) return TRUE;
    else return FALSE;
}

/* tests */
$test = array ("print ('foo');",
               "print (\"foo\");",
               "pint ('foo');",
               "print ('foo);",
               "print ('foo','bar');"
);

for($i=0;$i<sizeof($test);$i++) {
    print $test[$i];
    if(checkPHP($test[$i])) {
      print " is ok.<br />\n";
    } else {
      print " not ok.<br />\n";
    }
}

When I use it I get:

print ('foo'); is ok.
print ("foo"); is ok.
pint ('foo'); is ok.
print ('foo); is ok.
print ('foo','bar'); is ok.

I'm running Apache 2.2 / PHP 5.3.8 Safe Mode off

1
  • Installed modules that may be relavant include mod_suexec and mod_cgi. Commented Sep 5, 2011 at 7:57

2 Answers 2

3

Try using php -l -r. The -l flag performs a syntax check. I don't know if the -r flag is necessary if you use -l.

update: I tried this in the command line. Here's what I got when using correct syntax:

$ php -l            # what I executed
<?php                   #
print ('foo');          #  What I entered
?>                      #
No syntax errors detected in -   # What I got

$ echo $?  
0             # exit status

And the next using incorrect syntax:

$ php -l
<?php
print ('foo);
?>

Warning: Unexpected character in input:  ''' (ASCII=39) state=1 in - on line 2
No syntax errors detected in -

$ echo $?
0

And one last try:

$ php -l
<?php
kla asd a sss;    # after entering this line, the command aborted itself with the
                  # next message

Parse error: syntax error, unexpected T_STRING in - on line 2
Errors parsing -

$ echo $?
255

First and last case result in what we should expect, but the middle case is not. I would expect a != 0 exit status on this, but it seems that everything is ok (which clearly is not). So maybe your only option (that I can think of, at least) is, if you get 0 exit stats, parse the output and count the number of lines, look for warning or some other specific words?

Also, take note that -l only checks for syntax error, and cannot find errors at runtime. This means that calling an undefined function will be undetected by php -l.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you. Unfortunately it still doesn't work. With php -l -r I get the same, but with php -l I get not ok on all lines.
-r makes unnecessary to put the opening and closing tags. Maybe you can try adding them yourself $string = "<?php " . escapeshellcmd($string) . " ?>"; and do just php -l ?
Thanks Carlos - still no joy - getting not ok as before. Curious as to what was being returned I added print $exit to the else statement and I'm getting 255
Thank you Carlos. Not quite what I'm after. Your time is much appreciated.
0

The php command expects to execute code from either STDIN or a file. The -r flag will evaluate what follows without the need for the <?php ?> tags, however it's still waiting for a filename after that.

One solution is to write the code you want evaluated and pass its name to php. That'd change your eval command to eval ("php $string", $output, $exit); where $string is the filename where the code to be executed (tested) resides.

You will need to make sure that the file begins with <?php so as not to get an error.

This works

function checkPHP($string) {
   $string = escapeshellcmd($string);
   exec("php -l $string",$output,$exit);
   return ($exit == 0 ? TRUE : FALSE);
}

/* tests */
$test = array ("print ('foo');",
               "print (\"foo\");",
               "pint ('foo');",
               "print ('foo);",
               "print ('foo','bar');"
);

foreach ($test as $code){
   $fd = fopen('code.dat', 'w');
   fwrite($fd, "<?php \n" . $code . "\n ?>\n");
   fclose($fd);

   print $code;
   if(checkPHP("code.dat")) {
      print " is ok.<br />\n";
   } else {
      print " not ok.<br />\n";
   }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.