Я нашел ошибку в 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 не было.