Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #45, АВГУСТ 2004 г.

Integer Overflow

Мысла Владислав

Спецвыпуск Xakep, номер #045, стр. 045-026-4


Таким образом, если аргумент функции intUserNameSize будет больше, чем 0xFFFF, то в shUserNameSize запишутся только последние 16 разрядов. Например, если указать, что длина имени составляет 0х10001 (65537), в проверке произойдет сравнение требуемой длины строки с длиной имени 0х0001 (1). 0х0001 – потому, что первая единичка отбрасывается, так как она не входит в младшие 16 разрядов. Естественно, что в таком случае проверка на максимальную длину строки не сработает и выполнение функции будет продолжено. Но самое интересное! При записи используется переменная intUserNameSize (см. [2]), и поэтому вместо копирования одного байта происходит копирование 0х10001 байт. А это уже не что иное, как переполнение, которое может быть успешно эксплуатировано.

Проблема приобретения старших разрядов

Часто бывает так, что для того чтобы обезопасить функцию от получения отрицательных значений, программисты ошибочно используют конвертирование знаковой переменной в беззнаковую. Этот подход требует дополнительной проверки переменной перед конвертированием, потому что эта операция может привести к вращению вокруг нуля. Такие проверки делаются очень редко и поэтому могут стать причиной возникновения ошибок. Еще более интересная особенность проявляется при преобразовании числа из типа с меньшим количеством разрядов в тип с большим (например, из char в short). Дело в том, что если источник был типа char, то при переводе его в short значение приобретет дополнительных 8 разрядов. И если значение char было отрицательным (<0x7F), то эти разряды станут равными единице (0xFF). Взгляни на рисунок, чтобы понять, о чем идет речь.

Пример 3. Проблема конвертирования типов

char chValue = 0x80; // chValue = -128

short shValue = chValue; // shValue = 0xff80 ( -128 )

unsigned short ushValue = shValue;// ushValue = 0xff80 ( 65408 ) [1]

Таким образом, переменная shValue получит правильное значение (за счет заполнения верхних разрядов в 0xFF), но проблема возникает при переводе со знакового слова в беззнаковое (см. [1]). Переменная ushValue приобретает значение 65408, а это уже далеко не -128.

Проблема определения типа

Если более детально изучить пример 2, то можно выделить еще одну проблему относительно параметра intUserNameSize (длины строки). Более того, в примере 4 она присутствует тоже, хотя в нем нет преобразований типов, так же, как и нет математических операций, которые могли бы привести к переполнению intUserNameSize. Условие [1] создано, чтобы запретить запись в буфер строк, которые превосходят его по длине.

Назад на стр. 045-026-3  Содержание  Вперед на стр. 045-026-5