二进制整数运算是否有可能导致溢出并覆盖相邻内存?

发布于 2024-10-19 05:38:05 字数 1956 浏览 1 评论 0原文

这个问题与我目前看到的任何错误无关,更多的是关于理论以及对硬件架构设计和实现的变化的了解。


Scenario 1: Assuming a 16-bit processor with 16-bit registers, 16-bit addressing, and sizeof(int) = 16 bits:

unsigned int a, b, c, d;
a=0xFFFF;
b=0xFFFF;
c=a+b;

c 旁边的内存位置是否有可能被覆盖?
(在这种情况下,我希望在 add 操作期间会引发溢出标志,并且 c 要么保持不变,要么填充未定义的数据。)


Scenario 2: Assuming a 32-bit processor with 32-bit registers, 32-bit addressing, sizeof(int) = 32 bits, and sizeof(short int)=16 bits:

unsigned int a, b;
unsigned short int c, d;
a=0xFFFF;
b=0xFFFF;
c=a+b;

c 旁边的内存位置是否有可能被覆盖?
(我希望在添加操作期间不会引发溢出标志,但是在赋值操作期间是否引发内存访问或溢出标志将取决于硬件的实际设计和实现。如果 d 位于同一 32 位地址位置的高 16 位(对于 32 位寻址可能甚至不可能),它可能会被覆盖。)


Scenario 3: Assuming a 32-bit processor with 32-bit registers, 16-bit addressing, sizeof(int) = 32 bits, and sizeof(short int)=16 bits:

unsigned int a, b;
unsigned short int c, d;
a=0xFFFF;
b=0xFFFF;
c=a+b;

c 旁边的内存位置是否有可能被覆盖?
(我希望在类型转换和赋值操作期间引发一些溢出标志或内存违规标志。)


Scenario 4: Assuming a 32-bit processor with 32-bit registers, 32-bit addressing, and sizeof(int) = 32 bits:

unsigned int a, b;
struct {
    unsigned int c:16;
    unsigned int d:16;
} e;
a=0xFFFF;
b=0xFFFF;
e.c=a+b;

c 旁边的内存位置,即 d 是否有可能被覆盖? (在这种情况下,由于 cd 预计驻留在同一 32 位地址中,并且从技术上讲两者都是 32 位整数,因此可以想象没有溢出标志在添加或赋值期间引发,d 可能会受到影响。)


I have not tried to test this on actual hardware because my question is more about theory and possible variations in design and implementation. Any insight would be appreciated.

  • 二进制整数运算是否有可能导致溢出并覆盖相邻内存?
  • 目前是否有任何硬件实现遇到类似的内存覆盖问题,或者过去是否有系统存在此问题?
  • 典型的处理器使用哪些设备来防止相邻内存被算术和赋值操作覆盖?

This question is not about any error I'm currently seeing, it's more about theory and getting educated on the variations in HW architecture design and implementation.


Scenario 1: Assuming a 16-bit processor with 16-bit registers, 16-bit addressing, and sizeof(int) = 16 bits:

unsigned int a, b, c, d;
a=0xFFFF;
b=0xFFFF;
c=a+b;

Is it possible for the memory location next to c to be overwritten?
(In this case I would expect that an overflow flag would be raised during the add operation, and c either remain unchanged or be filled with undefined data.)


Scenario 2: Assuming a 32-bit processor with 32-bit registers, 32-bit addressing, sizeof(int) = 32 bits, and sizeof(short int)=16 bits:

unsigned int a, b;
unsigned short int c, d;
a=0xFFFF;
b=0xFFFF;
c=a+b;

Is it possible for the memory location next to c to be overwritten?
(I would expect that no overflow flag be raised during the add operation, but whether or not a memory access or overflow flag be raised during the assignment operation would depend on the actual design and implementation of the HW. If d was located in the upper 16 bits of the same 32-bit address location (probably not even possible with 32-bit addressing), it might be overwritten.)


Scenario 3: Assuming a 32-bit processor with 32-bit registers, 16-bit addressing, sizeof(int) = 32 bits, and sizeof(short int)=16 bits:

unsigned int a, b;
unsigned short int c, d;
a=0xFFFF;
b=0xFFFF;
c=a+b;

Is it possible for the memory location next to c to be overwritten?
(I would expect some overflow flag or memory violation flag to be raised during the type conversion and assignment operation.)


Scenario 4: Assuming a 32-bit processor with 32-bit registers, 32-bit addressing, and sizeof(int) = 32 bits:

unsigned int a, b;
struct {
    unsigned int c:16;
    unsigned int d:16;
} e;
a=0xFFFF;
b=0xFFFF;
e.c=a+b;

Is it possible for the memory location next to c, namely d, to be overwritten? (In this case, since c and d are expected to reside in the same 32-bit address and both are technically 32-bit integers, it's conceivable that no overflow flags be raised during addition or assignment, and d could be affected.)


I have not tried to test this on actual hardware because my question is more about theory and possible variations in design and implementation. Any insight would be appreciated.

  • Is it possible for a binary integer operation that results in an overflow to overwrite adjacent memory?
  • Are there currently any HW implementations that suffer from similar memory overwrite problems, or have there been systems in the past that had this problem?
  • What devices do typical processors use to guard against neighboring memory from being overwritten by arithmetic and assignment operations?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

伤痕我心 2024-10-26 05:38:05

1、2、3、4 中的任何一个都不会导致任何内存损坏,或者写入“过去”正在执行算术的整数位置的存储。 C 指定了无符号整数溢出时应该发生的情况。这是假设编译器生成了它应该生成的代码。对于生成将 4 个字节复制到 2 个字节变量的代码的有缺陷的编译器,没有什么可以保护您。

C99 (6.2.5) 是这样说的:

“涉及无符号操作数的计算永远不会溢出,
因为无法用结果无符号整数类型表示的结果是
减少对比最大值大 1 的数取模
由结果类型表示。”

因此,当您尝试“溢出”无符号整数时会发生什么是明确定义的。

现在,如果您的整数是有符号整数,那就是另一回事了。根据 C,溢出有符号整数导致未定义的行为。而未定义的行为意味着任何事情都可能发生,包括内存损坏,但我还没有看到任何与整数溢出相关的 C 编译器。

典型的处理器使用哪些设备来防止相邻内存被算术和赋值操作覆盖?

对于分配和算术运算而言,没有针对相邻内存的防护措施。处理器只是执行给它的机器代码指令(如果这些指令覆盖了内存,那么它不应该按照高级语言所表达的那样执行,处理器并不关心)。

在稍微不同的级别,如果 CPU 无法执行以下操作,它可能会发出 陷阱操作(例如指定不存在的内存位置的操作),或尝试执行某些非法操作(例如除以零,或遇到处理器不理解的操作码,或尝试对数据进行未对齐的访问)。

None of your 1,2,3,4 will result in any memory corruption, or writing "past" the storage for the integer location you are performing arithmetic on. C specifies what should happen on an overflow of unsigned integers. This is assuming the compiler produces the code it's supposed to. Nothing will guard you acainst a buggy compiler that generates code which copies 4 bytes into a 2 byte variable.

Here's what C99 (6.2.5) says:

"A computation involving unsigned operands can never overflow,
because a result that cannot be represented by the resulting unsigned integer type is
reduced modulo the number that is one greater than the largest value that can be
represented by the resulting type."

So, it's well defined what will happen when you try to "overflow" an unsigned integer.

Now, if your integers had been signed integers, it is an other story. According to C, overflowing a signed integer results in undefined behavior. And undefined behavior means anything, including memory corruption, could occur. I have not yet seen a C compiler that would corrupt anything regarding overflowing an integer though.

What devices do typical processors use to guard against neighboring memory from being overwritten by arithmetic and assignment operations?

There's no guards against neighboring memory regarding assignment and arithmetic operations. The processor simply executes the machine code instructions given to it (And if those instructions overwrites memory it was not suppoed to do as expressed in a higher level language, the processor does not care).

At a slightly different level, the CPU might issue traps if it cannot carry out the operation(e.g. the operation specified memory location that does not exist), or tries to do some illegal operation (e.g. division by zero, or encounters an op code the processor does not understand, or tries to do unaligned access to data).

寄离 2024-10-26 05:38:05

加法运算是在处理器内部处理的,所以无论你做什么,加法运算都将在 CPU 内部完成(更准确地说是在 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 中的内容(其大小已知且固定)

The addition operation is processed inside the processor afaik, so whatever you do, the add operation will be done inside the CPU (in the ALU more precisely)
The overflow register would be set in case of overflow, and the result will still be in the register, and then copied back to your memory location without risk of corrupting adjacent memory.
This is how the code would (sort of) be translated in 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

so as you can see, c would only hold what was in ax (which is of a known and fixed size) no matter if an overflow occurred or not

痴骨ら 2024-10-26 05:38:05

在 C 中,无符号类型的溢出行为是明确定义的。任何溢出导致任何与标准预测不同的结果的实现都是不合规的。

有符号类型的溢出行为未定义。虽然溢出最常见的影响要么是分配一些错误的值,要么是彻底崩溃,但 C 标准中没有任何内容保证处理器不会以编译代码尝试恢复的方式触发溢出错误,但由于某种原因,它会破坏堆栈变量或寄存器的内容。溢出也有可能导致标志以代码不期望的方式设置,并且这样的标志可能会导致未来计算的错误行为。

对于发生溢出时发生的情况,其他语言可能有不同的语义。

注意:我见过在溢出时陷入困境的处理器,与外部中断同时发生的意外陷阱可能导致数据损坏的处理器,以及意外的无符号溢出可能导致后续计算关闭一的处理器。我不知道有符号溢出会在哪里锁存一个会干扰后续计算的标志,但有些 DSP 有有趣的溢出行为,所以如果存在这种行为,我不会感到惊讶。

In C, the behavior of overflows with unsigned types is well-defined. Any implementation in which overflow causes any result other than what the standard predicts is non-compliant.

The behavior of overflows with signed types is undefined. While the most common effects of an overflow would either be the assignment of some erroneous value or an outright crash, nothing in the C standard guarantees that the processor won't trigger an overflow fault in a way that the compiled code tries to recover from, but which for some reason trashes the contents of a stack variable or a register. It's also possible that an overflow could cause a flag to get set in a way that code doesn't expect, and that such a flag might cause erroneous behavior on future computations.

Other languages may have different semantics for what happens when an overflow occurs.

note: I've seen processors which trap on overflow, processors where unexpected traps that happen at the same time as an external interrupt may cause data corruption, and processors where an unexpected unsigned overflow could cause a succeeding computation to be off by one. I don't know of any where a signed overflow would latch a flag that would interfere with subsequent calculations, but some DSP's have interesting overflow behaviors, so I wouldn't be surprised if one exists.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文