«Обычный человек не хочет быть свободным. Он просто хочет быть в безопасности». - Н. Л. Менкен
Я пытаюсь писать очень надежно. C. Ниже я перечислю некоторые методы, которые я использую, и спрашиваю, насколько они безопасны, как мне кажется. Пожалуйста, не стесняйтесь разрывать мой код / предубеждения в клочья. Любой ответ, который найдет даже самую тривиальную уязвимость или научит меня новой идее, будет высоко оценен .
Чтение из потока:
Согласно Руководство по программированию GNU C getline:
Функция getline будет
автоматически увеличить блок
память по мере необходимости, через realloc
функция, поэтому никогда не бывает недостатка
пространства - одна из причин, почему getline
так безопасно. [..] Обратите внимание, что getline может
безопасно обрабатывать вашу строку ввода, нет
независимо от того, как долго это.
Я полагаю, что getline должна при всех входах предотвращать переполнение буфера при чтении из потока.
- Правильно ли мое предположение? Существуют ли схемы ввода и / или распределения, при которых это может привести к эксплойту? Например, что если первый символ в потоке - это какой-то причудливый управляющий символ , может быть 0x08 BACKSPACE (ctl-H).
- Была ли проделана какая-либо работа, чтобы математически доказать, что getline безопасна?
Маллок возвращает ноль при ошибке:
Если malloc обнаруживает ошибку, malloc возвращает нулевой указатель. Это создает угрозу безопасности, поскольку к указателю NULL (0x0) все еще можно применить арифметику указателя, поэтому википедия рекомендует
/* Allocate space for an array with ten elements of type int. */
int *ptr = (int*)malloc(10 * sizeof (int));
if (ptr == NULL) {
/* Memory could not be allocated, the program should handle
the error here as appropriate. */
}
Безопасный sscanf:
При использовании sscanf Я привык распределять размер подлежащих извлечению строк по размеру входной строки, надеясь избежать возможности переполнения. Например:
const char *inputStr = "a01234b4567c";
const char *formatStr = "a%[0-9]b%[0-9]c":
char *str1[strlen(inputStr)];
char *str2[strlen(inputStr)];
sscanf(inputStr, formatStr, str1, str2);
Поскольку str1 и str2 имеют размер inputStr и из inputStr не может быть прочитано больше символов, чем strlen (inputStr), кажется невозможным, учитывая все возможные значения для inputStr вызвать переполнение буфера
- Я прав? Есть странные угловые случаи, о которых я не думал?
- Есть ли лучшие способы написать это? Библиотеки, которые уже решили это?
Общие вопросы:
Хотя я опубликовал большое количество вопросов, я не ожидаю, что кто-нибудь ответит на все из них. Вопросы в большей степени ориентированы на те ответы, которые я ищу. Я действительно хочу научиться безопасному мышлению С.
- Какие еще безопасные идиомы C существуют?
- В каких угловых случаях мне нужно всегда проверять ?
- Как мне написать модульные тесты для обеспечения соблюдения этих правил?
- Как я могу применить ограничения тестируемым или доказуемо правильным способом?
- Любая рекомендуемая техника статического / динамического анализа или инструменты для C?
- Каким безопасным практикам C вы следуете и как оправдываете себя и других?
Ресурсы:
Многие ресурсы были заимствованы из ответов.