Я нашел ошибку в PHP `crypt()`?

Я думаю, что я нашел ошибку в PHP crypt() функции под Windows.

Однако: я понимаю, что это, вероятно, моя ошибка. PHP используется миллионами и обрабатывается тысячами; мой код используется десятками и работал мной. (Этот аргумент лучше объясненный в Coding Horror.)

Итак, я прошу помощи: показать мне свою ошибку. Я пытался найти его в течение нескольких дней, без везения.

Настройка

Я использую установку сервера Windows с Apache 2.2.14 (Win32) и PHP 5.3.2. В моем окне разработки работает Windows XP Professional; сервер "production" (это интрасети) запускает Windows Storage Server 2003. Проблема возникает и на обоих.

Я не вижу ничего в php.ini, относящегося к crypt(), но с радостью ответит на вопросы о моей конфигурации.

Проблема

Иногда несколько скриптов в моем приложении PHP зависают: страница сидит там в ожидании localhost и никогда не заканчивается. Каждый из этих сценариев использует crypt для хеширования пользовательского пароля перед сохранением его в базе данных или, в случае страницы входа, для хеширования введенного пароля, прежде чем сравнивать его с версией, хранящейся в базе данных.

Поскольку страница входа является самой простой, я сосредоточился на ней для тестирования. Я неоднократно вошел в систему и обнаружил, что он может висеть, возможно, 4 раза в 10 раз.

В качестве эксперимента я изменил страницу входа в систему, чтобы использовать простой текстовый пароль и изменил свой пароль в базе данных на его текстовую версию. Страница перестала висит.

Я видел, что последняя версия PHP содержит это исправление:

Исправлена ​​ошибка # 51059 (crypt вылетает, когда недействительная соль указаны [sic]).

Итак, я создал очень простой тест script следующим образом, используя ту же соль, что и в официальный пример:

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

Эта страница тоже будет зависать, если я перезагружу ее, как сумасшедшую. Я только вижу, который висит в Chrome, но независимо от браузера эффект на Apache одинаковый.

Эффект на Apache

Когда эти страницы зависают, Apache страница состояния сервера (что я объяснил здесь, в отношении другой проблемы) увеличивает количество обрабатываемых запросов и уменьшает количество незанятых работников. Обработанные запросы почти все имеют статус "Отправка ответа", хотя иногда на мгновение они будут показывать либо "Чтение запроса", либо "keepalive" (чтение). '

В конце концов, Apache может сбой. Когда это произойдет, отчет о сбое Windows выглядит следующим образом:

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

Это моя вина?

У меня возникает соблазн представить отчет об ошибке на PHP. Аргумент против него, как указано выше, в том, что ошибки почти всегда являются моей ошибкой.

Однако мой аргумент в пользу "этого ошибки PHP":

  • Я использую Windows, в то время как большинство серверов используют Linux (я не могу это выбрать), поэтому шансов больше, чем я нашел краевой случай
  • Недавно была ошибка с crypt(), поэтому, возможно, у нее все еще есть проблемы.
  • Я сделал простейший тестовый пример, и у меня все еще есть проблема.

Может ли кто-нибудь повторить это? Можете ли вы предложить, где я ошибся? Должен ли я записывать ошибку?

Заранее благодарим за любую помощь, которую вы можете дать.

Ответы

Ответ 1

Ошибки 51059 (только о передаче недопустимых входов) или 50947 (не тот же код, 5.3 имеют новые алгоритмы и функции, реализованные в php, на всех платформах) не связаны с этой проблемой.

Однако http://bugs.php.net/bug.php?id=51424. Я уже разместил там частичный патч, но он решает большинство возможных замков, но этого действительно недостаточно. Полное исправление будет присутствовать в следующей версии 5.3.

Кстати, речь идет не о конкретных окнах, а о потоковом SAPI (например, windows apache 2.2).

Ответ 2

Этот вопрос сейчас был просмотрен 128 раз и включен 9 раз. Единственный ответ, который я получил, говорит об ошибке, и указывает на одно в базе данных ошибок PHP. Я не думаю, что это точно то же самое, но, похоже, это подтверждает мой диагноз.

Поэтому, с некоторым колебанием, я опубликовал отчет об ошибке:

Ошибка # 51666 - Использование crypt() приводит к зависанию или сбою Apache

Спасибо всем, кто посмотрел на это со мной - даже если вы не ответили, просто зная, что другие рассматривают это со мной, а не говорят мне, что я сумасшедший, было полезно.

Ответ 3

Да. Это известная ошибка,

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

Вы можете имитировать результат crypt(), используя mcrypt. Если вы можете изменить свой хэш пароля, вы действительно должны использовать hash_hmac(), который более безопасен и у нас нет проблем с ним. На Apache. Однако никаких проблем с Windows не было.