前两天遇到一个灵异现象,记录下来。
cchFullHeaderLen += strlen("Request-Line: ") +
strlen(pSessionData->HttpOpenReq.lpszVerb) +
strlen(" ") +
strlen(pSessionData->HttpOpenReq.lpszObjectName) +
(NULL != pSessionData->HttpOpenReq.lpszVersion) ? (strlen(" ") + strlen(pSessionData->HttpOpenReq.lpszVersion)) : 0 +
strlen("\r\n");
调试的过程中发现,pSessionData->HttpOpenReq.lpszVersion为NULL,但是依然会执行“(strlen(" “) + strlen(pSessionData->HttpOpenReq.lpszVersion))”。
确认不是编码错误后,反汇编调试:
Boxr!MyFunction+0x2b2
6a515742 xor edx,edx
6a515744 cmp dword ptr [ecx+23Ch],0
6a51574b setne dl
6a51574e add esi,edx
6a515750 je Boxr!MyFunction+0x2ed (6a51577d)
6a515752 push offset Boxr!std::_Arithmetic_traits::_Rank+0xc88 (6a5fc0f8)
6a515757 call Boxr!strlen (6a5b5bd0)
6a51575c add esp,4
其中ecx+23Ch就是pSessionData->HttpOpenReq.lpszVersion,查看如下:
0:005> dd ecx+23c
0a27b18c 00000000
确认pSessionData->HttpOpenReq.lpszVersion确实为NULL。
理论上6a515750处的跳转会执行的,但是没有。单步跟踪:
0:005> p
eax=00000014 ebx=00cc000c ecx=0a27af50 edx=00000000 esi=00000027 edi=0485d5ec
eip=6a515744 esp=0485d518 ebp=0485d5f8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
Boxr!MyFunction+0x2b4:
6a515744 cmp dword ptr [ecx+23Ch],0 ds:0023:0a27b18c=00000000
0:005> p
eax=00000014 ebx=00cc000c ecx=0a27af50 edx=00000000 esi=00000027 edi=0485d5ec
eip=6a51574b esp=0485d518 ebp=0485d5f8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
Boxr!MyFunction+0x2bb:
6a51574b setne dl
0:005> r zf
zf=1
0:005> p
eax=00000014 ebx=00cc000c ecx=0a27af50 edx=00000000 esi=00000027 edi=0485d5ec
eip=6a51574e esp=0485d518 ebp=0485d5f8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
Boxr!MyFunction+0x2be:
6a51574e add esi,edx
0:005> r zf
zf=1
0:005> p
eax=00000014 ebx=00cc000c ecx=0a27af50 edx=00000000 esi=00000027 edi=0485d5ec
eip=6a515750 esp=0485d518 ebp=0485d5f8 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
Boxr!MyFunction+0x2c0:
6a515750 je Boxr!MyFunction+0x2ed (6a51577d) [br=0]
0:005> r zf
zf=0
可以看出,原本是准备要跳转的,但是
6a51574e add esi,edx
这条指令改变了zf寄存器,于是没有跳转。
那这条指令是干什么的呢?怎么会有这么一条指令?
最开始怀疑是编译器优化出问题了。
于是准备以发现编译器优化错误为主体写一篇BLOG。
但是在整理本文的过程中,仔细分析了一遍汇编代码,发现,丫是个低级错误 - 运算符优先级错误……
实际上,C代码真正的执行逻辑是这样的:
cchFullHeaderLen += (strlen("Request-Line: ") + strlen(pSessionData->HttpOpenReq.lpszVerb) + strlen(" ") + strlen(pSessionData->HttpOpenReq.lpszObjectName) + (NULL != pSessionData->HttpOpenReq.lpszVersion) )
? (strlen(" ") + strlen(pSessionData->HttpOpenReq.lpszVersion)) : ( 0 + strlen("\r\n") );
我的编码风格PPT又多了一条素材……