Тут в процессе прочтения, весьма интересной книги "24 греха компьютерной безопасности" наткнулся на один весьма любопытный и очень не очевидный пример "дырки" которая может приводить к переполнению буфера. Дело в том что "проблема" показанная в данном примере может встречаться так же в программах для МК, что в свою очередь может приводить к не верной работе программы или её сбою. Вот код: Код (Text): #define MAX_BUF 256 void someFunction( char* input ) { short len; char buf[ MAX_BUF ]; len = strlen( input ); if ( len < MAX_BUFF ) { strcpy( buf, input ); } } Попробуйте разобраться в том в каких случаях этот код станет не безопасным и приведет к переполнению массива в переменной buf. Вроде все верно, указан максимальный размер, проверяется длинна и производится сравнение ... но нет.. тут есть "дырка" Весьма любопытный пример надо сказать Через сутки я напишу тут подробный ответ, а пока не стоит писать ответы и спойлерить если вы догадались, дайте другим поломать голову
И так в чем была проблема. Давайте для простоты представим что тип short равен 1 байту а int равен 2 байтам, так будет проще понять. Предположим что мы передали в функцию строку длинною 511 байт. Функция stlen() имеет возвращаемый тип size_t что как правило соответствует некоему целочисленному значению без знака, размер обычно варьируется от системы к системе и может иметь и 32 и 64 разряда. Предположим что в нашем случае size_t является unigned int и соответствует 2 байтам. Таким образом функция вернет нам значение 511 что в двоичном виде будет выглядеть так: 1 байт [00000001] 2 байт [11111111] Но принимающей переменной у нас является переменная short размер которой составляет всего 1 байт, следовательно возвращаемое значение слишком велико и оно будет усечено, просто 1 байт будет выкинут и в переменную len будет записан 2 байт. Но наша переменная является знаковой а как известно старший значащий бит в знакомых числах интерпретируется как наличие или отсутствие знака, в итоге в нашей переменой len окажется ничто иное как отрицательное значение -127 Объявленное в define число будет интерпретироваться как signed int, то есть число со знаком и при операции сравнения, наше переменная len будет повышена до signed int с сохранением знака. В итоге len будет всегда меньше 256 и условие будет выполняться. Ну а так как функция strcpy определяет конец строки по нулевому байту, она послушно скопирует 511 байт, выйдя далеко за границы отведенной для буфера памяти. Вот собственно и все Как сказал Unixon - РЕШЕТО Ну а кто не в курсе чем опасны дырки с переполнением буфера, почитайте инет, очень удивитесь P.s. Вообще функции типа srtcpy и её давании собраться, давно помечены как не безопасные, а при их использовании современные компиляторы выдают предупреждения, а им на смену пришли доработанные и более безопасные варианты
Это еще не всё Что сделает strcpy, если фактическая длина строки окажется больше, чем можно записать в size_t ? На всякий случай стоит заменить strcpy на strncpy, там хотя бы размер буфера можно указать.
Вероятнее всего речь идет о strlen ?, strcpy как я понимаю вообще длину никак не отслеживает. А strlen теоретически при превышении размера size_t, переменная обнулится (и не раз если передать строку длинною size_t x2 или х3 или х4 и тд) и строка длиною в много миллионов символов может оказаться всего в 1 символ например, проверка это дело пропустит а strcpy все это многомиллионное добро попытается записать По сути получается проблема целочисленного переполнения. Так ?