если Вы жалуетесь на, добирается (), почему бы не то же с scanf (“%s”, …)?

От man gets:

Никогда не используйте, добирается (). Поскольку невозможно сказать, не зная данные заранее, сколько символов добирается (), будет читать, и потому что добирается (), продолжит хранить символы мимо конца буфера, чрезвычайно опасно использовать. Это использовалось для повреждения компьютерной безопасности. Используйте fgets () вместо этого.

Почти везде я вижу scanf быть используемым способом, которое должно иметь ту же проблему (переполнение буфера / переполнение буфера): scanf("%s",string). Эта проблема существует в этом случае? Почему нет никаких ссылок об этом в scanf страница справочника? Почему gcc не предупреждает при компиляции этого с -Wall?

PS: Я знаю, что существует способ указать в строке формата максимальную длину строки с scanf:

char str[10];
scanf("%9s",str);

править: Я не спрашиваю к determe, если предыдущий код является правильным или нет. Мой вопрос: если scanf("%s",string) является всегда неправильным, почему нет никаких предупреждений и нет ничего об этом в странице справочника?

5
задан dbarbosa 4 June 2010 в 21:47
поделиться

5 ответов

Ответ просто в том, что никто не написал в GCC код, который бы выдавал это предупреждение.

Как вы отметили, предупреждение для конкретного случая "%s" (без ширины поля) вполне уместно.

Однако следует помнить, что это относится только к случаю scanf(), vscanf(), fscanf() и vfscanf(). Этот спецификатор формата может быть совершенно безопасным при использовании sscanf() и vsscanf(), поэтому предупреждение в этом случае выдаваться не должно. Это означает, что вы не можете просто добавить его в существующий код анализа "scanf-style-format-string"; вам придется разделить его на опции "fscanf-style-format-string" и "sscanf-style-format-string".

Я уверен, что если вы выпустите патч для последней версии GCC, то у него есть все шансы быть принятым (и, конечно, вам нужно будет представить патчи для заголовочных файлов glibc).

5
ответ дан 14 December 2019 в 01:02
поделиться

Использование gets() никогда не является безопасным. scanf() можно использовать безопасно, как вы сказали в своем вопросе. Однако определить, безопасно ли вы его используете - более сложная задача для компилятора (например, если вы вызываете scanf() в функции, где в качестве аргументов вы передаете буфер и количество символов, он не сможет определить это); в этом случае ему придется предположить, что вы знаете, что делаете.

4
ответ дан 14 December 2019 в 01:02
поделиться

Когда компилятор просматривает строку форматирования scanf , он видит строку! Предполагается, что строка форматирования не вводится во время выполнения. Некоторые компиляторы, такие как GCC, имеют некоторые дополнительные функции для анализа строки форматирования, если она введена во время компиляции. Эта дополнительная функциональность не является исчерпывающей, потому что в некоторых ситуациях требуются накладные расходы времени выполнения, что НЕТ НЕТ для таких языков, как C. Например, можете ли вы обнаружить небезопасное использование, не вставляя в этом случае дополнительный скрытый код:

char* str;
size_t size;
scanf("%z", &size);
str = malloc(size);
scanf("%9s"); // how can the compiler determine if this is a safe call?!

Конечно, есть способы написать безопасный код с помощью scanf , если вы укажете количество символов для чтения и достаточно памяти для хранения строки. В случае, если получает , нет способа указать количество символов для чтения.

3
ответ дан 14 December 2019 в 01:02
поделиться

Я не уверен, почему на странице руководства для scanf не упоминается вероятность переполнения буфера, но vanilla scanf не является безопасным вариантом. Довольно устаревшая ссылка - http://blogs.msdn.com/b/rsamona/archive/2005/10/24/484449.aspx показывает это как раз. Также проверьте это (не gcc, но информативно) - http://blogs.msdn.com/b/parthas/archive/2006/12/06/application-crash-on-replacing-sscanf-with-sscanf -s.aspx

1
ответ дан 14 December 2019 в 01:02
поделиться

Это может быть просто, что scanf будет выделять пространство в куче в зависимости от того, сколько данных прочитано. Поскольку он не выделяет буфер, а затем читает, пока не будет прочитан нулевой символ, он не рискует перезаписать буфер. Вместо этого он читает в свой собственный буфер, пока не будет найден нулевой символ, и предположительно копирует этот буфер в другой буфер правильного размера в конце чтения.

-4
ответ дан 14 December 2019 в 01:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: