Несколько лет назад мне позвонил мой бывший коллега и рассказал о проблеме, которую он должен был исправить с помощью моего кода, который являлся роутером для транзакций по кредитным картам.
Префикс номера карты состоит из 6-значного BIN (идентификационного номера банка) и нескольких дополнительных цифр, которые банки используют по своему усмотрению, например, Банк имеет BIN для карты Visa Classic 456789 и резервирует 2 дополнительные цифры для обозначения субпродукта, например, 01 для студенческого билета, 02 для совместного бренда в местном универмаге и так далее. В этом случае префикс карты, который в основном является идентификатором продукта, становится длиной 8 цифр. Когда я кодировал эту часть, я решил, что 9 цифр «должно хватить всем». Я работал нормально 2 года, пока однажды банк не выпустил новые карточные продукты с префиксом из 10 цифр (понятия не имею, зачем им это нужно). Нетрудно представить, что произошло - маршрутизатор отключился, вся система остановилась, потому что она не может функционировать без транзакционного маршрутизатора, все банкоматы этого банка (один из крупнейших в стране) не функционировали в течение нескольких часов, пока проблема не была обнаружена и неподвижная.
Я не могу опубликовать код здесь, во-первых, потому что у меня его нет, а во-вторых, он защищен авторским правом компании, но нетрудно представить strcpy()
без проверки размера целевого буфера.
Также как man strcpy
говорит:
Если строка назначения
strcpy () недостаточно велик (что
есть, если программист был глуп
или ленивый, и не смог проверить размер
перед копированием)
бывает. Переполнение фиксированной длины
струны любимый взломщик
техника.
Я был очень смущен. Это было хорошее время для совершения seppuku :)
Но я хорошо усвоил урок и не забудьте (обычно :)) проверить размер целевого буфера. Я бы не советовал изучать его трудным способом - просто выработайте привычку проверять целевой буфер перед strcpy()
и strcat()
.
Редактировать: хорошее предложение от Healthcarel - используйте strncpy()
вместо strcpy()
. Это не добавляет конечный 0, но я обычно использую следующий макрос, чтобы обойти это:
#define STRNCPY(A,B,C) do {strncpy(A,B,C); A[C] = 0; } while (0)