Возможна ли двоичная целочисленная операция, которая приводит к переполнению, чтобы перезаписать смежную память? - PullRequest
1 голос
/ 24 февраля 2011

Этот вопрос не о какой-либо ошибке, которую я сейчас вижу, а о теории и обучении различным изменениям в дизайне и реализации архитектуры HW.


Сценарий 1: Предполагается, что 16-битный процессор с 16-битными регистрами, 16-битной адресацией и sizeof (int) = 16 бит:
unsigned int a, b, c, d;
a=0xFFFF;
b=0xFFFF;
c=a+b;

Возможно ли перезаписать область памяти рядом с c?
(В этом случае я ожидаю, что флаг переполнения будет установлен во время операции add , и c либо останется неизменным, либо будет заполнен неопределенными данными.)


Сценарий 2: Предполагается, что 32-разрядный процессор с 32-разрядными регистрами, 32-разрядной адресацией, sizeof (int) = 32 бита и sizeof (short int) = 16 бит:
unsigned int a, b;
unsigned short int c, d;
a=0xFFFF;
b=0xFFFF;
c=a+b;

Возможно ли перезаписать область памяти рядом с c?
(Я ожидаю, что во время операции добавления не будет подниматься флаг переполнения, но будет ли или нет подниматься флаг доступа к памяти или переполнения во время операции присваивания, будет зависеть от фактического проектирования и реализации HW. Если d находился в верхних 16 битах того же 32-битного адреса (вероятно, это невозможно даже при 32-битной адресации), он может быть перезаписан.)


Сценарий 3: Предполагается, что 32-разрядный процессор с 32-разрядными регистрами, 16 -битная адресация, sizeof (int) = 32 бита и sizeof (short int) = 16 бит:
unsigned int a, b;
unsigned short int c, d;
a=0xFFFF;
b=0xFFFF;
c=a+b;

Возможно ли перезаписать область памяти рядом с c?
(Я ожидаю, что какой-либо флаг переполнения или флаг нарушения памяти будет поднят во время операции преобразования типа и назначения.)


Сценарий 4: Предполагается, что 32-разрядный процессор с 32-разрядными регистрами, 32-разрядной адресацией и sizeof (int) = 32 бита:
unsigned int a, b;
struct {
    unsigned int c:16;
    unsigned int d:16;
} e;
a=0xFFFF;
b=0xFFFF;
e.c=a+b;

Возможно ли перезаписать область памяти рядом с c, а именно d? (В этом случае, поскольку ожидается, что c и d будут находиться в одном и том же 32-разрядном адресе, и оба являются технически 32-разрядными целыми числами, возможно, что при добавлении или назначении не будут установлены флаги переполнения, и d могут быть затронуты.)


Я не пытался проверить это на реальном оборудовании, потому что мой вопрос больше касается теории и возможных изменений в дизайне и реализации. Любое понимание будет оценено.
  • Возможна ли двоичная целочисленная операция, которая приводит к переполнению, чтобы перезаписать смежную память?
  • Есть ли в настоящее время какие-либо реализации HW, которые страдают от подобных проблем с перезаписью памяти, или в прошлом были системы, которые имели эту проблему?
  • Какие устройства используются типичными процессорами для защиты от перезаписи соседней памяти от операций арифметики и присваивания?

Ответы [ 3 ]

4 голосов
/ 24 февраля 2011

Ни один из ваших 1,2,3,4 не приведет к повреждению памяти или записи "за" память для целочисленного местоположения, для которого вы выполняете арифметику. C определяет, что должно происходить при переполнении целых чисел без знака. Это предполагает, что компилятор создает код, который должен. Ничто не защитит вас от ошибочного компилятора, который генерирует код, который копирует 4 байта в 2-байтовую переменную.

Вот что говорит C99 (6.2.5):

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

Итак, четко определено, что произойдет, если вы попытаетесь "переполнить" целое число без знака.

Теперь, если ваши целые числа были целыми числами со знаком, это другая история. Согласно C, переполнение целого числа со знаком приводит к неопределенному поведению. А неопределенное поведение означает, что может произойти что угодно, включая повреждение памяти. Я еще не видел компилятор C, который мог бы испортить что-либо из-за переполнения целого числа.

Какие устройства используются типичными процессорами для защиты от перезаписи соседней памяти от операций арифметики и присваивания?

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

На несколько ином уровне ЦП может выдавать traps , если он не может выполнить операцию (например, указанная операция памяти не существует) или пытается выполнить какую-то недопустимую операцию (например, деление нулем, или встречает код операции, который процессор не понимает, или пытается сделать доступ к данным без выравнивания).

1 голос
/ 24 февраля 2011

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

Поведение переполнений со знаковыми типами не определено.Хотя наиболее распространенными последствиями переполнения могут быть либо присвоение некоторого ошибочного значения, либо прямое падение, в стандарте C нет ничего, что гарантировало бы, что процессор не вызовет ошибку переполнения таким образом, что скомпилированный код пытается восстановить,но который по какой-то причине стирает содержимое переменной стека или регистра.Также возможно, что переполнение может привести к тому, что флаг будет установлен таким образом, которого код не ожидает, и что такой флаг может вызвать ошибочное поведение в будущих вычислениях.

Другие языки могут иметь другую семантику для чегопроисходит, когда происходит переполнение.

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

1 голос
/ 24 февраля 2011

Операция сложения обрабатывается внутри процессора afaik, поэтому, что бы вы ни делали, операция добавления будет выполняться внутри процессора (точнее в ALU) Регистр переполнения будет установлен в случае переполнения, и результат все еще будет в регистре, а затем скопирован обратно в вашу область памяти без риска повреждения соседней памяти. Вот как код (вроде бы) будет переведен в asm:

mov ax, ptr [memory location of a]
mov bx, ptr [memory location of b]
add ax,bx
mov ptr [memory location of c], ax

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

...