views:

378

answers:

3

I think I may have found a bug in PHP's crypt() function under Windows.

However: I recognize that it's probably my fault. PHP is used by millions and worked on by thousands; my code is used by tens and worked on by me. (This argument is best explained on Coding Horror.)

So I'm asking for help: show me my fault. I've been trying to find it for a few days now, with no luck.

The setup

I'm using a Windows server installation with Apache 2.2.14 (Win32) and PHP 5.3.2. My development box runs Windows XP Professional; the 'production' server (this is an intranet setup) runs Windows Storage Server 2003. The problem happens on both.

I don't see anything in php.ini related to crypt(), but will happily answer questions about my config.

The problem

Several scripts in my PHP app occasionally hang: the page sits there on 'waiting for localhost' and never finishes. Each of these scripts uses crypt to hash a user's password before storing it in the database, or, in the case of the login page, to hash the entered password before comparing it to the version stored in the database.

Since the login page is the simplest, I focused on it for testing. I repeatedly logged in, and found that it would hang maybe 4 out of 10 times.

As an experiment, I changed the login page to use the plain text password and changed my password in the database to its plain text version. The page stopped hanging.

I saw that PHP's latest version lists this bugfix:

Fixed bug #51059 (crypt crashes when invalid salt are [sic] given).

So I created a very simple test script, as follows, using the same salt given in an official example:

$foo = crypt('rasmuslerdorf','r1');
echo $foo;

This page, too, will hang, if I reload it like crazy. I only see it hanging in Chrome, but regardless of browser, the effect on Apache is the same.

Effect on Apache

When these pages hang, Apache's server-status page (which I explained here, regarding a different problem) increments the number of requests being processed and decrements the number of idle workers. The requests being processed almost all have a status of 'Sending Reply,' though sometimes for a moment they will show either 'Reading request' or 'keepalive (read).'

Eventually, Apache may crash. When it does, the Windows crash report looks like this:

szAppName: httpd.exe
szAppVer: 2.2.14.0
szModName: php5ts.dll
szModVer: 5.3.1.0 // OK, this report was before I upgraded to PHP 5.3.2, 
                  // but that didn't fix it
offset: 00a2615

Is it my fault?

I'm tempted to file a bug report to PHP on this. The argument against it is, as stated above, that bugs are nearly always my fault.

However, my argument in favor of 'it's PHP's fault' is:

  1. I'm using Windows, whereas most servers use Linux (I don't get to choose this), so the chances are greater that I've found an edge case
  2. There was recently a bug with crypt(), so maybe it still has issues
  3. I have made the simplest test case I can, and I still have the problem

Can anyone duplicate this? Can you suggest where I've gone wrong? Should I file the bug after all?

Thanks in advance for any help you may give.

+2  A: 

Yes. It's a known bug,

http://bugs.php.net/bug.php?id=50947

You can simulate the crypt() result using mcrypt. If you can change your password hash, you should really use hash_hmac(), which is more secure and we have no issues with it On Apache. No experiences on Windows though.

ZZ Coder
`hash_hmac()` works fine! What makes it more secure?
Nathan Long
I'm not sure that's the same bug. It's a SIGSEGV on Solaris, while Nathan's issue is a hang on Windows.
Matthew Flaschen
@Matthew - I thought the same. I decided to open my own but report. Thanks!
Nathan Long
+2  A: 

This question has now been viewed 128 times and upvoted 9 times. The only answer I've received says it's a bug, and points to one in the PHP bug database. I don't think it's exactly the same one, but it does seem to validate my diagnosis.

Therefore, with some hesitation, I have filed a bug report:

Bug #51666 - Using crypt() makes Apache hang or crash

Thanks to everyone who has looked at this with me - even if you didn't reply, just knowing that others were considering this with me, and not telling me I'm crazy, has been helpful.

Nathan Long
+2  A: 

The bugs 51059 (only about passing invalid inputs) or 50947 (not the same code, 5.3 has new algorithms and features implemented in php, on all platforms) are not related to this problem.

However http://bugs.php.net/bug.php?id=51424 is. I already posted a partial patch there, but it solves most of the possible locks but it is indeed not sufficient. A full fix will be present in the next 5.3 release.

By the way, it is not windows specific but about the threaded SAPI (windows apache 2.2 for example).

Pierre
Awesome! Thanks, it's very gratifying to get a response from someone who's contributing patches to PHP.
Nathan Long