Если вы заметили, что функция htmlspecialchars() начала возвращать пустую строку (внешний признак — пустые поля в формочках), не пугайтесь. Это не баг, это фича.

Именно так по замыслу разработчиков PHP и должна работать функция со строками в кодировке cp1251 и прочими «нацменьшинствами». Вы, кончено, будете возражать: «Раньше работала нормально. Значит — баг!» Ничего подобного! Задокументированный баг считается фичей. Вот вам выдержка из инструкции по миграции с php 5.3 на php 5.4:

Кодировкой по умолчанию для функций htmlspecialchars() и htmlentities() сейчас является UTF-8, вместо прежней ISO-8859-1. Обратите внимание, что изменения кодировки вывода с помощью конфигурационной опции default_charset не действует на вышеупомянутые функции до тех пор, пока вы не передадите «» (пустую строку) в качестве параметра кодировки в вызовы функций htmlspecialchars()/ htmlentities(). В целом, мы не рекомендуем так делать, потому что вы должны иметь возможность изменить кодировку вывода без воздействия на кодировку во время исполнения, используемую этими функциями. Самый безопасный подход — явно установить кодировку при каждом вызове функций htmlspecialchars() и htmlentities().

То есть, разработчикам и эксплуататорам движков и скриптов, использующих кодировку отличную от utf-8 предлагается либо переходить на utf-8, либо исправлять все(!) вхождения функций htmlspecialchars() и htmlentities() на такой, полный, формат:

htmlspecialchars($str, ФЛАГ, 'кодировка сайта');

Однако, можно попробовать использовать более универсальный код (в 5.6 уже не работает):

htmlspecialchars($str, NULL, '');

Такой код избавит вас от необходимости каждый раз править все вызовы при смене кодировки, что очень важно, если заранее не известно, в какой кодировке придется работать скрипту. Этот «универсальный» код работает и с utf-8, и с cp1251 в php 5.4.6 даже без маневров с default_charset. То есть — как раньше. Видимо из-за этого, разработчики его и не рекомендуют 😉

А что делать тем, у кого скрипты свёрнуты ионкубом или зендом? Выпить йаду. Договаривать с хостером об откате php на предыдущую версию, менять хостера, брать VPS/VDS, короче, крутиться кто как может, не забывая посылать лучи ненависти в строну разрабов php.

В заключение хочу искренне поблагодарить разработчиков php, что они не вспомнили о функциях preg_*, которые тоже можно было перевести на utf по умолчанию, изменив смысл флага «u» на противоположный.

UPD В PHP 5.6 код: htmlspecialchars($str, NULL, ''); тоже возвращает пустую строку.
Спасибо, Андрей, за уточнение.