Ash
Ash

Reputation: 1

PHP exec() not working as expected

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

Upvotes: 0

Views: 565

Answers (2)

Carlos Campderr&#243;s
Carlos Campderr&#243;s

Reputation: 23002

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.

Upvotes: 3

Tarek Fadel
Tarek Fadel

Reputation: 1959

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";
   }
}

Upvotes: 0

Related Questions