以下是代码的一部分:
// Culture dependent
sortDate = System.DateTime.Parse("2001-04-01");
// Better
sortDate = new DateTime(2001, 04, 01);
这是来自clang的二进制代码,用Hopper反汇编:
static uint32_t mp4_atom_containers[] = {
ATOM('m', 'o', 'o', 'v'),
ATOM('t', 'r', 'a', 'k'),
ATOM('m', 'd', 'i', 'a'),
ATOM('m', 'i', 'n', 'f'),
ATOM('s', 't', 'b', 'l')
};
typedef struct {
uint32_t size;
uint32_t type;
u_char data[0];
} __packed mp4_atom_hdr_t;
static ngx_int_t f(mp4_file_t *mp4f, mp4_atom_t *atom)
{
ngx_uint_t i;
uint32_t atom_size;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4f->log, 0, "f:: type: %i", atom->hdr->type);
if (atom->hdr->type == ATOM('t', 'r', 'a', 'k'))
mp4f->trak = atom;
else if (atom->hdr->type == ATOM('s', 't', 's', 'z'))
mp4f->stsz = (mp4_atom_stsz_t *)atom->hdr;
else if (atom->hdr->type == ATOM('s', 't', 's', 'c'))
mp4f->stsc = (mp4_atom_stsc_t *)atom->hdr;
else if (atom->hdr->type == ATOM('m', 'v', 'h', 'd'))
mp4f->mvhd = (mp4_atom_mvhd_t *)atom->hdr;
// point #1
for (i = 0; i < sizeof(mp4_atom_containers); i++) {
if (atom->hdr->type == mp4_atom_containers[i])
goto found;
}
return 0;
found:
atom_size = be32toh(atom->hdr->size) - sizeof(*hdr);
// rest of the code
return 0;
}
出于某种原因,clang被删除或以错误的方式优化,在第1点检查。在反汇编代码中,如果type不是00000001000750c2 mov rdx, qword [ds:r13+0x28] ; XREF=_mp4_parse_atom+35
00000001000750c6 mov eax, dword [ds:rdx+4]
00000001000750c9 cmp eax, 'srak'
00000001000750ce jg 0x1000750e0
00000001000750d0 cmp eax, 'stsc'
00000001000750d5 jne 0x1000750f0
00000001000750d7 mov qword [ds:r14+0x140], rdx ; mp4f->stsc = (mp4_atom_stsz_t *)atom->hdr;
00000001000750de jmp 0x10007510e
00000001000750e0 cmp eax, 'stsz' ; XREF=_mp4_parse_atom+78
00000001000750e5 jne 0x100075100
00000001000750e7 mov qword [ds:r14+0x138], rdx ; mp4f->stsz = (mp4_atom_stsc_t *)atom->hdr;
00000001000750ee jmp 0x10007510e
00000001000750f0 cmp eax, 'mvhd' ; XREF=_mp4_parse_atom+85
00000001000750f5 jne 0x10007510e
00000001000750f7 mov qword [ds:r14+0x130], rdx ; mp4f->mvhd = (mp4_atom_mvhd_t *)atom->hdr;
00000001000750fe jmp 0x10007510e
0000000100075100 cmp eax, 'trak' ; XREF=_mp4_parse_atom+101
0000000100075105 jne 0x10007510e
0000000100075107 mov qword [ds:r14+0x128], r13 ; mp4f->trak = atom;
000000010007510e mov rbx, r14 ; XREF=_mp4_parse_atom+94, _mp4_parse_atom+110, _mp4_parse_atom+117, _mp4_parse_atom+126, _mp4_parse_atom+133
0000000100075111 mov eax, dword [ds:rdx]
0000000100075113 bswap eax
0000000100075115 xor r12d, r12d
0000000100075118 add eax, 0xfffffff8
000000010007511b mov qword [ss:rbp+var_38], rax ; atom_size = be32toh(atom->hdr->size) - sizeof(*hdr);
000000010007511f je 0x10007527f ; point #2
0000000100075125 lea rax, qword [ds:r13+0x18]
0000000100075129 mov qword [ss:rbp+var_48], rax
000000010007512d xor r14d, r14d
0000000100075130 mov r15, rdx
0000000100075133 jmp 0x100075144
0000000100075135 nop word [cs:rax+rax]
; other code
类型之一,则必须转到#2点。
答案 0 :(得分:2)
mp4_atom_containers[i]
访问越界,调用未定义的行为。
允许编译器以这种方式优化循环条件。
for (i = 0; i < sizeof(mp4_atom_containers); i++)
应该是
for (i = 0; i < sizeof mp4_atom_containers / sizeof *mp4_atom_containers; i++)
sizeof(mp4_atom_containers)
是整个数组的大小(以字节为单位),但sizeof mp4_atom_containers / sizeof *mp4_atom_containers
是数组中元素的数量。
允许编译器假设i
永远不会是5,因为这将是一个超出范围的访问,因此i
将始终小于sizeof(mp4_atom_containers)
(这是最可能20)所以这是一个无限循环。