facebook / hhvm

A virtual machine for executing programs written in Hack.
https://hhvm.com
Other
18.13k stars 2.99k forks source link

fopen(..., ..., true) does not interpret '.' in include path correctly #5185

Open nghc opened 9 years ago

nghc commented 9 years ago

There is a problem with HHVM and roundcube. I can't use roundcube, because I receive only a blank white page with the error 500 (hphp_invoke). On php5-fpm it works fine.

Here is my system: Debian Wheezy; nginx/1.6.3; 5.6.99-hhvm

oyamauchi commented 9 years ago

We'll need more information to be able to understand what's going on. We'll need at least the config you're using to run HHVM, and if it's behind nginx, the nginx config will be helpful too.

J0WI commented 9 years ago

I have the same problem using nginx 1.6.2 and HipHop VM 3.7.0 on Ubuntu 15.04 with Roundcube 1.1.1.

Test case to reproduce:

nginx vhost

location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/hhvm/hhvm.sock;
}

hhvm php.ini

include_path = ".:/usr/share/php:/usr/share/pear"

error.log

\nFatal error: Class undefined: html in /srv/roundcube/program/lib/Roundcube/rcube_plugin_api.php on line 566

Same configuration works fine with php5-fpm 5.6.4 (just change fastcgi_pass).

J0WI commented 9 years ago

see also #2891

J0WI commented 9 years ago

maybe related: https://phabricator.wikimedia.org/T91919

J0WI commented 9 years ago

@oyamauchi can you reproduce with these infos?

fredemmott commented 9 years ago

Simplified test case. The autoloader is kind-of bad, but given it works, on PHP5, we're probably misinterpreting '.'

fred@hhvm-oss-bench:/tmp/roundcubemail-1.1.2$ cat test.php
<?php
require_once('program/lib/Roundcube/miniboostrap.php');

html::tag('foo');
fred@hhvm-oss-bench:/tmp/roundcubemail-1.1.2$ cat program/lib/Roundcube/miniboostrap.php
<?php

// Based on bootstrap.php but simplified

set_include_path(__DIR__.'/lib:.');
spl_autoload_register('rcube_autoload');

/**
 * Use PHP5 autoload for dynamic class loading
 *
 * @todo Make Zend, PEAR etc play with this
 * @todo Make our classes conform to a more straight forward CS.
 */
function rcube_autoload($classname)
{
    $filename = preg_replace(
        array(
            '/Mail_(.+)/',
            '/Net_(.+)/',
            '/Auth_(.+)/',
            '/^html_.+/',
            '/^rcube(.*)/'
        ),
        array(
            'Mail/\\1',
            'Net/\\1',
            'Auth/\\1',
            'Roundcube/html',
            'Roundcube/rcube\\1'
        ),
        $classname
    );

    if ($fp = @fopen("$filename.php", 'r', true)) {
        fclose($fp);
        include_once "$filename.php";
        return true;
    }

    return false;
}
fred@hhvm-oss-bench:/tmp/roundcubemail-1.1.2$ /opt/php5-5.6.9/bin/php test.php
fred@hhvm-oss-bench:/tmp/roundcubemail-1.1.2$ hhvm test.php

Fatal error: Class undefined: html in /tmp/roundcubemail-1.1.2/test.php on line 4
fredemmott commented 9 years ago

It's the fopen call that fails; if that check is skipped, the icnlude works fine

fredemmott commented 9 years ago

Isolated example:

<?php

set_include_path('.');
chdir('/tmp');
$fp = fopen(basename(__FILE__), 'r', true);
var_dump($fp);

http://3v4l.org/UjXXo

J0WI commented 9 years ago

I think this also breaks thumbnail generating in Piwigo.

ju2kr commented 9 years ago

I have the same issue like @J0WI

dpopham commented 8 years ago

Re: \nFatal error: Class undefined: html in /srv/roundcube/program/lib/Roundcube/rcube_plugin_api.php on line 566

A little long winded, but I got it to work.........

Running HipHop VM 3.10.1 (rel), nginx/1.9.3, roundcube v1.2RC, Ubuntu 15.10 server and received the same error.

Root of problem I found was the html class file is in a different folder that the auto loader could not find.

Basically index.php loads program/include/iniset.php, which contains the function rcmail_autoload($classname).

That function checks that the class name begins with rcmail and if it does, it will load program/include/$classname.php.

In the program/include/ folder you will see all the rcmail_something files.

After loading these (and only these) class files, index.php calls rcmail::get_instance()...

The rcmail class was loaded fine in the rcmail_autoload function, so it gets invoked from the program/includes/rcmail.php file. In it the get_instance function calls startup, which in turn calls the init function for the array of plugins (at the very end of get_instance). In my case, the jqueryui init was the first plugin to trigger the problem, and once triggered, the app is dead.

Within the plugins/jqueryui/jqueryui.php file the init function makes a call to the plugins include_script function, which is found in program/lib/Roundcube/rcube_plugin.php, This include_script then calls the plugin api version of include_script found in program/lib/Roundcube/rcube_plugin_api.php, and here lies the problem.

This include_script tries to execute $this->output->add_header(html::tag('script', array('type' => "text/javascript", 'src' => $src)));

Notice the call inside add_header to html::tag(), which is found in the html class.......

So what is html?

It exists inside the program/lib/Roundcube/ folder as html.php. It is not in the program/include/ named something like rcmail_html.php.

So it is not preloaded and the html class does not exist. As a result, \nFatal error: Class undefined: html in /srv/roundcube/program/lib/Roundcube/rcube_plugin_api.php

As a quick and dirty fix which so far is working on my personal server I just changed the autoload function to include the existing html class in its different location from the other class files. It seems to work (at least I can use roundcube now and not get a simple 500 error all the time) but I am sure a more elegant solution, like perhaps moving the html class to the includes folder and renaming the file, might be more elegant. But I was busy, and quick and dirty won the race. Not sure why it seems to work for people using php5 /shrug. I should have just loaded the html file once instead of triggering for every classname, but phhht, it works and it's time to go for food :-) I'll fix it for myself later, but at least this is enough to get you going.

function rcmail_autoload($classname) { if (strpos($classname, 'rcmail') === 0) { $filepath = INSTALL_PATH . "program/include/$classname.php"; if (is_readable($filepath)) { include_once $filepath; return true; } } if ($classname == 'html') { $filepath = INSTALL_PATH . "program/lib/Roundcube/$classname.php"; if (is_readable($filepath)) { include_once $filepath; return true; } } return false; }

J0WI commented 8 years ago

Maybe someone from roundcube could have a look? cc @alecpl

alecpl commented 8 years ago

I'm not sure what I can help here. To make Roundcube Framework classes (these in lib/Roundcube) working you need to use rcube_autoload(). Why it does not work with HHVM I have no idea. Maybe your include path is wrong, so fopen() can't find the html.php file.

bugz8unny69 commented 8 years ago

I am also experiencing this particular issue with Roundcube 1.2-RC but thankfully alecpl just recently commited a fix: https://github.com/roundcube/roundcubemail/commit/0eece8222babd9ea87fbb39ea1a594a7ae979b73

@alecpl Would it be cleaner to bump the version to 1.2.1-RC? The changelog still indicates 1.2RC.

I will clone the latest revision and see if this issue has been fix and report back. However, I didn't quite interpret the fopen() bug (if it's a bug or not).

bugz8unny69 commented 8 years ago

The latest git works here.

Regards, Horace

alecpl commented 8 years ago

we plan to release 1.2.0 (stable) soon, anyway.

Jo-Con-El commented 7 years ago

Roundcube 1.2.5 has been release, and 1.2 is the stable version already. Please close.

fredemmott commented 7 years ago

Might not affect roundcube any more, but the fopen issue still exists.