在Windows64上使用MinGW GCC 4.8.2编译7-zip源代码我发现了崩溃。
以下是7-zip 9.20,Sha1.cpp:
的代码片段const unsigned kBlockSize = 64;
...
void CContext::UpdateRar(Byte *data, size_t size, bool rar350Mode) {
...
for (int i = 0; i < kBlockSizeInWords; i++) {
UInt32 d = _buffer[i];
data[i * 4 + 0 - kBlockSize] = (Byte)(d); // <<= DISASSEMBLED
data[i * 4 + 1 - kBlockSize] = (Byte)(d >> 8);
data[i * 4 + 2 - kBlockSize] = (Byte)(d >> 16);
data[i * 4 + 3 - kBlockSize] = (Byte)(d >> 24);
}
}
使用MinGW GCC 4.8.2(在Windows上)进行编译得到:
0x0000000045b65f75 <+149>: mov eax,0xffffffc0
0x0000000045b65f7a <+154>: nop WORD PTR [rax+rax*1+0x0]
0x0000000045b65f80 <+160>: mov r10d,DWORD PTR [r11+0x24]
0x0000000045b65f84 <+164>: mov edx,eax
0x0000000045b65f86 <+166>: add r11,0x4
0x0000000045b65f8a <+170>: mov ecx,r10d
0x0000000045b65f8d <+173>: mov BYTE PTR [rbx+rdx*1],r10b
在最后一行rbx
中,应从此地址中减去data
和64
。这是通过添加-64
来完成的。在汇编代码段0xffffffc0
(-64
(Int32))的第一行中保存到eax
,然后移至edx
。但在最后一行
0x0000000045b65f8d <+173>: mov BYTE PTR [rbx+rdx*1],r10b
rdx
寄存器而不是edx
寄存器。此时rdx
的顶部为0,因此+64
可以正常工作。但添加-64
要求rdx
寄存器的顶部部分保留0xFFFFFFFF
。在64位模式下添加&data+0xffffffc0
会产生无效的地址并崩溃。
通过更改分配(添加(int)
强制转换)来解决问题:
data[i * 4 + 0 - (int)kBlockSize] = (Byte)(d);
data[i * 4 + 1 - (int)kBlockSize] = (Byte)(d >> 8);
data[i * 4 + 2 - (int)kBlockSize] = (Byte)(d >> 16);
data[i * 4 + 3 - (int)kBlockSize] = (Byte)(d >> 24);
我的问题是:
更新 事实证明,这种行为不依赖于优化标志,只能在Windows上观察