Почему проверка границ не реализована в некоторых языках? - PullRequest
4 голосов
/ 14 сентября 2011

Согласно Википедии (http://en.wikipedia.org/wiki/Buffer_overflow)

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

Итак, почему «Проверка границ» не реализована внекоторые языки, такие как C и C ++?

Ответы [ 5 ]

10 голосов
/ 14 сентября 2011

По сути, это потому, что каждый раз, когда вы изменяете индекс, вы должны делать оператор if.

Давайте рассмотрим простой цикл C:

int ary[X] = {...};  // Purposefully leaving size and initializer unknown

for(int ix=0; ix< 23; ix++){
    printf("ary[%d]=%d\n", ix, ary[ix]);
}

если у нас есть проверка границ, сгенерированный код для ary[ix] должен выглядеть примерно так:

LOOP:
    INC IX          ; add `1 to ix
    CMP IX, 23      ; while test
    CMP IX, X       ; compare IX and X
    JGE ERROR       ; if IX >= X jump to ERROR
    LD  R1, IX      ; put the value of IX into register 1
    LD  R2, ARY+IX  ; put the array value in R2
    LA  R3, Str42   ; STR42 is the format string
    JSR PRINTF      ; now we call the printf routine
    J   LOOP        ; go back to the top of the loop

;;; somewhere else in the code
ERROR:
    HCF             ; halt and catch fire

Если у нас нет этой проверки границ, то вместо этого мы можем написать:

    LD R1, IX
LOOP:
    CMP IX, 23
    JGE END
    LD R2, ARY+R1
    JSR PRINTF
    INC R1
    J   LOOP

Это сохраняет 3-4 инструкции в цикле, что (особенно в старые времена) много значило.

На самом деле, на машинах PDP-11 было даже лучше, потому что было что-то, называемое «автоинкрементная адресация». На PDP все содержимое регистра и т. Д. Превратилось во что-то вроде

CZ  -(IX), END    ; compare IX to zero, then decrement; jump to END if zero

(И любой, кто помнит PDP лучше, чем я, не доставляет мне проблем с точным синтаксисом и т. Д., Вы старый пердун, как я, вы знаете, как эти вещи ускользают.)

3 голосов
/ 14 сентября 2011

Все дело в производительности. Однако утверждение, что C и C ++ не имеют проверки границ, не совсем корректно. Версии каждой библиотеки «отладочные» и «оптимизированные» довольно распространены, и нередко бывает, что проверка границ включена в версиях отладки различных библиотек.

Преимуществом этого является быстрое и безболезненное нахождение недопустимых ошибок при разработке приложения и одновременное устранение снижения производительности при запуске программы для realz.

Я также должен добавить, что снижение производительности не является пренебрежимо малым, и многие языки, кроме C ++, будут предоставлять различные высокоуровневые функции, работающие с буферами, которые реализованы непосредственно в C и C ++ специально, чтобы избежать проверки границ. Например, в Java, если вы сравниваете скорость копирования одного массива в другой, используя чистую Java, с использованием System.arrayCopy (который выполняет проверку границ один раз, но затем выполняет прямое копирование массива без проверки границ каждого отдельного элемента), вы увидите довольно большую разницу в производительности этих двух операций.

3 голосов
/ 14 сентября 2011

Это проще для реализации и быстрее как для компиляции, так и во время выполнения.Это также упрощает определение языка (так как можно пропустить немало вещей, если это пропустить).

В настоящее время, когда вы делаете:

int p = (int ) таНос (SizeOf (INT));* p = 50;

C (и C ++) просто говорит: «Ладно, ладно! Я помещу что-то в это место в памяти».

Если бы требовалась проверка границ, С должен был бы сказать: «Хорошо, сначала давайте посмотрим, смогу ли я что-то там поместить? Это было выделено? Да? Хорошо. Я сейчас вставлю».Пропустив тест, чтобы увидеть, есть ли что-то, что там можно написать, вы экономите очень дорогой шаг.С другой стороны, (она была в перчатке), мы сейчас живем в эпоху, когда «оптимизация предназначена для тех, кто не может позволить себе оперативную память», поэтому аргументы о скорости становятся намного слабее.

1 голос
/ 14 сентября 2011

Поскольку это приведет к повреждению этих языков общего назначения для требований HPC.Существует множество приложений, в которых переполнение буфера действительно не имеет значения ни на йоту, просто потому, что они не происходят.Такие функции намного лучше в библиотеке (где на самом деле вы уже можете найти примеры для C / C ++).Для языков, специфичных для предметной области, возможно, имеет смысл внедрить такие функции в определение языка и обменять полученный результат на производительность для повышения безопасности.

1 голос
/ 14 сентября 2011

Основной причиной является снижение производительности при добавлении проверки границ в C или C ++.Хотя эти накладные расходы могут быть существенно уменьшены с помощью современных технологий (до 20-100% накладных расходов, в зависимости от приложения), они все еще достаточно велики, чтобы заставить многих людей колебаться.Я не уверен, является ли эта реакция рациональной - я иногда подозреваю, что люди слишком много внимания уделяют производительности, просто потому, что производительность поддается количественной оценке и измерению - но, тем не менее, это факт жизни.Этот факт уменьшает стимул для крупных компиляторов прилагать усилия для интеграции новейшей работы по проверке границ в свои компиляторы.

Вторая причина связана с опасениями, что проверка границ может сломать ваше приложение.В частности, если вы делаете прикольные вещи с арифметикой указателей и приведением, которые нарушают стандарт, проверка границ может заблокировать то, что в данный момент выполняется вашим приложением.Большие приложения иногда делают удивительно грубые и безобразные вещи.Если компилятор ломает приложение, то нет смысла указывать на то, что винить в коде хитрый код;люди не собираются продолжать использовать компилятор, который ломает их приложение.

Другая важная причина заключается в том, что проверка границ конкурирует с ASLR + DEP .ASLR + DEP воспринимаются как решение 80% проблемы или около того.Это уменьшает предполагаемую необходимость полноценной проверки границ.

...