views:

355

answers:

5

I've noticed an unusual problem with some of my php programs. Sometimes when visiting a page like profile.edit.php, the browser throws a dialogue box asking to download profile.edit.php page. When I download it, there's nothing in the file. profile.edit.php is supposed to be a web form that edits user information.

I've noticed this on some of my other php pages as well. I look in my apache error logs, and I see a segmentation fault message:

[Mon Mar 08 15:40:10 2010] [notice] child pid 480 exit signal Segmentation fault (11)

And also, the issue may or may not appear depending on which server I deploy my application too.

Additonal Details This doesn't happen all the time though. It only happens sometimes. For example, profile.edit.php will load properly. But as soon as I hit the save button (form action="profile.edit.php?save=true"), then the page asks me to download profile.edit.php. Could it be that sometimes my php scripts consume too much resources?

Sample code

Upon save action, my profile.edit.php includes a data_access_object.php file. I traced the code in data_access_object.php to this line here

 if($params[$this->primaryKey])
 {
                        $q = "UPDATE $this->tableName SET ".implode(', ', $fields)." WHERE ".$this->primaryKey." = ?$this->primaryKey";
                        $this->bind($this->primaryKey, $params[$this->primaryKey], $this->tblFields[$this->primaryKey]['mysqlitype']);
}
 else
{
$q = "INSERT $this->tableName SET ".implode(', ', $fields);
}
// Code executes perfectly up to this point
// echo 'print this'; exit; // if i uncomment this line, profile.edit.php will actually show 'print this'.  If I leave it commented, the browser will ask me to download profile.edit.php
if(!$this->execute($q)){ $this->errorSave = -3; return false;}
// When I jumped into the function execute(), every line executed as expected, right up to the return statement.  

And if it helps, here's the function execute($sql) in data_access_object.php

function execute($sql)
{

        // find all list types and explode them
        // eg. turn ?listId into ?listId0,?listId1,?listId2 
        $arrListParam = array_bubble_up('arrayName', $this->arrBind);

        foreach($arrListParam as $listName)
           if($listName)
           {
                $explodeParam = array();
                $arrList = $this->arrBind[$listName]['value'];
                foreach($arrList as $key=>$val)
                {
                        $newParamName = $listName.$key;
                        $this->bind($newParamName,$val,$this->arrBind[$listName]['type']);
                        $explodeParam[] = '?'.$newParamName;
                }
                $sql = str_replace("?$listName", implode(',',$explodeParam), $sql);
           }

        // replace all ?varName with ? for syntax compliance
        $sqlParsed = preg_replace('/\?[\w\d_\.]+/', '?', $sql);
        $this->stmt->prepare($sqlParsed);

        // grab all the parameters from the sql to create bind conditions
        preg_match_all('/\?[\w\d_\.]+/', $sql, $matches);
        $matches = $matches[0];

        // store bind conditions
        $types = ''; $params = array();
        foreach($matches as $paramName)
        {
                $types .= $this->arrBind[str_replace('?', '', $paramName)]['type'];
                $params[] = $this->arrBind[str_replace('?', '', $paramName)]['value'];
        }

        $input = array('types'=>$types) + $params;



        // bind it
        if(!empty($types))
        call_user_func_array(array($this->stmt, 'bind_param'), $input);

        $stat = $this->stmt->execute();
        if($GLOBALS['DEBUG_SQL'])
                echo '<p style="font-weight:bold;">SQL error after execution:</p> ' . $this->stmt->error.'<p>&nbsp;</p>';

        $this->arrBind = array();
        return $stat;
}
+1  A: 

That is likely caused by incorrect server configuration. The server is sending the file directly, not interpreting it as a PHP program. Since you're using Apache, the following configuration setting (from here) should fix the problem:

<FilesMatch \.php$>
    SetHandler application/x-httpd-php
</FilesMatch>

Edit: There appears to be a deeper problem. See comments under this answer and on the original question.

Brett Daniel
The server's not sending the PHP file directly if it's empty... something else is at play here.
Josh
You're right. Judging from the additional information, it looks like a deeper problem. Should I delete this answer as per http://meta.stackoverflow.com/questions/37738/when-or-should-you-delete-your-incorrect-answer ?
Brett Daniel
The bottom line of the highest voted answer to that question on meta is "Just because it isn't exactly right, doesn't mean it doesn't add any value to the OP or future readers." So I would say no, don't delete, just edit and make it clear that while this is the most common case, it doesn't appear to apply here. I guess. Anyone else want to weigh in? :-)
Josh
A: 

This typically means you do not have PHP installed or configured correctly on the server.

cdburgess
In this case it's something else. He has PHP installed, it's just segfaulting when he executes an SQL query.
Josh
+1  A: 

I think it should be AddType application/x-httpd-php .php .phtml in the httpd.conf

I'm saving my answer because it's a fix but his real problem is the use of "action" in the HTML form. The form should be:

<form action="myphpfile.php" method="get">
  <input type="hidden" name="save" value="true" />
  First name: <input type="text" name="firstname" /><br />
  Last name: <input type="text" name="lastname" /><br />
  <input type="submit" value="Submit" />
</form>

You don't use a query in the form action you place a hidden input. I think that is why it seg faults. I would not use "get" as the method you should use "post" if you are going to save data. I actually use "post" all the time.

Clutch
He has PHP installed OK, the issue is PHP is segfaulting when he executes a specific SQL query.
Josh
+1  A: 

Also, be careful with browser caching. Even if applying the correct settings and the right file handler, the browser still prompt for a download of the file. This can be fixed by rebooting the browser/emptying the browser cache.

Roberto Aloi
I don't think this applies to his issue.
Josh
A: 

What does the final SQL statement being generated look like? Where you have:

// echo 'print this'; exit; 

What if you changed that to:

echo "Query: $q";
exit;

And posted the results in your question...

From what I can tell, your query will look like:

INSERT some_table SET field1, field2, field3

When it should be:

INSERT INTO some_table SET field1='value 1', field2='value 2', field3='value 3'
Josh