На сайте, который поддерживал программист, пользователи могли оставлять комментарии. В какой-то момент было решено помечать комментарии, содержащие упоминания брендов, как возможный спам.
Программист реализовал простую проверку “текст содержит слово из списка запрещенных”, изменения в коде получились совсем небольшими:
И что же, вы думаете, случилось дальше?
Во-первых, был весьма высок процент ошибок типа false negative (текст был хороший, но помечался как содержащий слова из списка).
Во-вторых, если присмореться, в массиве @posts
встречались
вот такие нелепые хеши:
Почему 'word_count'
в contains_brand_name
?
Откуда ключ 4
?
Источник проблем – функция contains_brand_name
,
а точнее – ее поведение в списковом контексте.
В скалярном контексте сопоставление с шаблоном возвращает истину или ложь – признак успешности сопоставления. В списковом же контексте возвращается список строк, которые были захвачены скобками, или пустой список в случае неудачного сопоставления.
Конструирование же хеша предоставляет как раз списковый контекст, так что хеш
превращается в
, а так как =>
– это всего лишь запятая,
дополнительно заключающая свой левый операнд в кавычки,
хеш получается таким:
Конечно, это не то, на что рассчитвал программист.
Кстати, если программист использует use warnings
,
то при выполнении кода увидит по крайней мере предупреждение
Odd number of elements in anonymous hash
.
Для исправление программы стоило бы поменять код функции contains_brand_name
,
и сопоставление с регулярным выражением выполнять всегда
в скалярном контексте: