UASM v2.55, Mar 28 2022:
CASE WM_LBUTTONDOWN
push 1
call someproc
xor eax, eax
mov edx, 11111111h ; marker for debugging
jmp OutHere
CASE WM_RBUTTONDOWN
push 0
call someproc
xor eax, eax
mov edx, 22222222h ; marker for debugging
jmp OutHere
ENDSW
invoke CallWindowProc, opSubCanvas, hwnd, uMsg, wParam, lParam ; subclassing finished, continue with default handler
nops 2 ; 3 would be ok
OutHere: ret
Address Hex dump Command Comments
00403623 . 33C0 xor eax, eax
00403625 . BA 11111111 mov edx, 11111111 ; first jump
0040362A . EB 2F jmp short 0040365B ; wrong jump
0040362C . EB 17 jmp short 00403645
0040362E > 3D 04020000 cmp eax, 204
00403633 . 75 10 jne short 00403645
00403635 . 6A 00 push 0 ; /Arg1 = 0
00403637 . E8 73000000 call 004036AF
0040363C . 33C0 xor eax, eax
0040363E . BA 22222222 mov edx, 22222222 ; second jump
00403643 . EB 16 jmp short 0040365B ; wrong jump
00403645 > FF75 14 push dword ptr [ebp+14] ; /lParam
00403648 . FF75 10 push dword ptr [ebp+10] ; |wParam
0040364B . FF75 0C push dword ptr [ebp+0C] ; |Msg
0040364E . FF75 08 push dword ptr [ebp+8] ; |hWnd
00403651 . FF35 84154100 push dword ptr [411584] ; |WinProc = ntdll.776F11A8
00403657 . E8 82330000 call CallWindowProcA ; \USER32.CallWindowProcA
0040365C . 90 nop
0040365D . 90 nop
0040365E . 5B pop ebx
0040365F . 5F pop edi
00403660 . 5E pop esi
00403661 . C9 leave
00403662 . C2 1000 retn 10
The problem ist the OutHere: ret
This works perfectly:
OutHere:
ret
Have you tried the same case here but not using the SWITCH/ENDSW ? - I'm wondering if the switch is causing the label to not be referenced correctly.
Quote from: johnsa on October 08, 2022, 06:40:48 AM
Have you tried the same case here but not using the SWITCH/ENDSW ? - I'm wondering if the switch is causing the label to not be referenced correctly.
Same for .if ... .else ... .endif chains. Unfortunately only for MasmBasic, which complicates the bug chasing a lot...
Note the bug does
not raise its ugly head in ML and AsmC.
Load the attached exe into OllyDbg, run it with F9, then
- right-click into the edit control to see a correct jump (in SubCanvas)
- right-click into the main window's client area to see the buggy jump
The music plays here:
CASE WM_LBUTTONDOWN ; **** the bug manifests itself here ****
nops 8 ; OxPT_Assembler mlv615 ; delete the x to activate ML
if 0
invoke MessageBox, 0, chr$("LButtondown"), chr$("Title"), MB_OK ; *** no bug ***
else
MsgBox 0, "LButtondown", "Hi", MB_OK ; **** bug ****
endif
xor eax, eax
mov edx, 11111111h ; marker for debugging
INT 3
jmp OutHere
... which translates to this:
004011F3 . 90 nop
004011F4 . 90 nop
004011F5 . 0FAE05 508640 fxsave [408650]
004011FC . 51 push ecx
004011FD . 6A 00 push 0 ; /Type = MB_OK|MB_DEFBUTTON1|MB_APPLMODAL
004011FF . 68 9C704000 push offset 0040709C ; |Caption = "Hi"
00401204 . 68 A0704000 push offset 004070A0 ; |Text = "LButtondown"
00401209 . 6A 00 push 0 ; |hOwner = NULL
0040120B . E8 9E000000 call <jmp.&user32.MessageBoxA> ; \USER32.MessageBoxA
00401210 . 0FAE0D 508640 fxrstor [408650]
00401217 . 59 pop ecx
00401218 . 33C0 xor eax, eax
0040121A . BA 11111111 mov edx, 11111111
0040121F . CC int3
00401220 . EB 20 jmp short 00401242 ; the bad jump
Most likely, the problem is triggered by the MsgBox macro:
MsgBox MACRO dlg:REQ, text:REQ, title:REQ, style:=<MB_OK or MB_SETFOREGROUND>
MbXms ; fxsave [408650]
ifdif <dlg>, <0>
ifdif <dlg>, <NULL>
if @InStr(1, <dlg>, <h>) ne 1
echo
echo XXXX MsgBox 0 or hWnd, "TEXT", "TITLE" [, MB_??] XXXX
echo
.err
endif
endif
endif
push ecx
push style
push repargA(title)
if mbx(text)
if mbx(title)
push -1
else
push 0
endif
call MbGetSlotPointer
push [edx]
else
push repargA(text)
endif
push dlg
call MessageBoxA
MbXmr ; fxrstor [408650]
pop ecx
ENDM
For comparison, the original Masm32 SDK macro:
MsgBox MACRO hndl,txtmsg,titlemsg,styl
invoke MessageBox,hndl,reparg(txtmsg),reparg(titlemsg),styl
ENDM
Quote
The problem ist the OutHere: ret
Interesting bug.
I'm afraid you can't test with jwasm?
To catch the bug, it might be interesting to add another register to the "uses" clause.
Because the "3 bytes off" might be related to
- the 3 registers that are "used"
- a 5-byte jmp forward reduced to a 2 byte short jump by the assember in the 2. pass
The fact that it only breaks when the line contains both the label and the ret is interesting. This makes me wonder if it has something to do with the line queue, as "ret" is technically a macro.
Could you try using the retn 0x10 directly instead of ret ?
Quote from: johnsa on October 19, 2022, 01:25:28 AMCould you try using the retn 0x10 directly instead of ret ?
Test attached:
invoke DefWindowProc, hWnd, uMsg, wParam, lParam ; default processing
if 0
OutHere: pop ebx ; no crash
pop edi
pop esi
leave
retn 4*4
else
OutHere: ret ; crash
endif
WndProc endp
Thanks.. definitely sounds like some strange macro expansion artifact then coinciding with the branch destination shorting over passes..
Now to try make a very simple reproduction test-case.