The MASM Forum

General => The Workshop => Topic started by: Antariy on June 07, 2013, 11:00:04 PM

Title: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: Antariy on June 07, 2013, 11:00:04 PM
Here is the macro I mentioned here (http://masm32.com/board/index.php?topic=1984.msg20918#msg20918) about.

It:
• Probes the stack if the size of locals in total is greater than default x86 page size (4096), which prevents silent crashes if proc uses much of locals space. It just continuously probe the stack with the page sized step and allocates the pages properly for usage in the code. If the size of locals is not greater than page size, the probing code is not generated by the macro and is not called. If the macro generates the probing code, it will notify about it in the console. To supress these notification messages, specify the macro "AxProcProl_NoWarnChkStk".
• Zeroes the locals at the start of the proc, so you have them all set to 0 right from first instruction of your code in the proc, if required. You should specify the "AxProcProl_ZeroSpace = 1" equation to turn this feature on.
• Does an optimization of the epilogue :greensml: If you set "AxProcProl_OptimizeSpeed" macro to 1, it will produce "mov esp,ebp \ pop ebp" code, if you set that macro to 0, it will produce "leave" :lol: The default is 0.
• Important feature: it checks the stack balancing at the return and at the same time it checks for buffer overflows (also called as buffer overruns). If at the time of return from the proc there will be detected a corruption of a variable placed in the stack, it will mean that either the stack is imbalanced, or some code has overwritten this value so the return address may potentially point to other location than the proc was called from (this is security threat). If you want this feature to be turned ON - to test your code and to find imbalancing bugs if there are any, or for a release edition for increasing the program security - then you should set the macro "AxProcProl_CheckBuffersOverflow" to 1, otherwise set it to 0.

Also one may want to randomize the "salt" used by code to check the stack state correctness. For this you may manipulate with the variable "AxProcProl_CheckingForOverflowDWord" - XOR it or change it as you want.

Also remember that you can change the macroses' values in any place in the source, so you can turn on or off any feature or set of features for any specific proc.



As for stack checking thing - if there is corruption detected, then message box will be displayed at the time of return from the proc. It will look like:
---------------------------
Error
---------------------------
Warning: in the proc 'start' there is the problem with the stack!   
This may bring to undesired results!   
Continue Executing? (NO - is recommended)
---------------------------
Yes   No   
---------------------------

So user can chose to close program, or to continue it (not recommended but in some circumstancies it maybe important).


It maybe a bit crude, so thoughts and suggestions are welcome :t
Also simple testing proggie is included with example of stack imbalanced proc.
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: qWord on June 07, 2013, 11:18:19 PM
Quote from: Antariy on June 07, 2013, 11:00:04 PMIt:
• Probes the stack if the size of locals in total is greater than default x86 page size (4096), which prevents silent crashes if proc uses much of locals space.
thats new to me  :icon_confused:
(or you are talking about 64 bit processes?)
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: jj2007 on June 07, 2013, 11:34:25 PM
Quote from: Antariy on June 07, 2013, 11:00:04 PM
Here is the macro I mentioned here (http://masm32.com/board/index.php?topic=1984.msg20918#msg20918) about.
...
It maybe a bit crude, so thoughts and suggestions are welcome :t
Also simple testing proggie is included with example of stack imbalanced proc.

Great work, Alex :t


> thats new to me

For playing with the limits. 3930 is fine on Win7-32.

include \masm32\include\masm32rt.inc

crash=3930      ; try 3940

.code
Testme3 proc arg
LOCAL abc, buffer[4096+crash]:BYTE
  mov eax, arg
  mov buffer[0], al
  ret
Testme3 endp

Testme2 proc arg
LOCAL abc, buffer[4096]:BYTE
  invoke Testme3, arg
  ret
Testme2 endp

Testme1 proc arg
LOCAL abc, buffer[4096]:BYTE
  invoke Testme2, arg
  ret
Testme1 endp

start:   invoke Testme1, 123
   inkey "ok"
   exit

end start

Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: Antariy on June 07, 2013, 11:53:26 PM
Strange error when posted - half of message was not posted, so I changed it a bit and explained in more details ::)
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: Antariy on June 07, 2013, 11:58:59 PM
Quote from: qWord on June 07, 2013, 11:18:19 PM
Quote from: Antariy on June 07, 2013, 11:00:04 PMIt:
• Probes the stack if the size of locals in total is greater than default x86 page size (4096), which prevents silent crashes if proc uses much of locals space.
thats new to me  :icon_confused:
(or you are talking about 64 bit processes?)

The default (ok, "default") page size for 32 bit x86 CPU is 4096 bytes (1000h).


Thanks, Jochen :biggrin:

Quote from: jj2007 on June 07, 2013, 11:34:25 PM
For playing with the limits. 3930 is fine on Win7-32.

One will get crash only when is accessing to an uncommited stack page. Since the stack layout is so:


=== top of stack (address, in pages, let's say, 10) ===

some data in the stack

=== esp (address 5,5) ===

== guard page (address 5) ===
=== no access space (address 4) ===


so one needs to allocate from one to two pages in the stack and to access to the lowest variable to get actual and sure crash. The exact size depends only on runtime position of the ESP in the page field and on the lowest commited page. The probing code work is in accessing with the page step, so it will eventually hit the guard page that lies below current ESP value and that lies above the memory that is not commited yet. The system intercepts this hit to a guard page and understand that the stack requirement is growing, and commiting the memory - the guard page becomes commited page, the next page below previously-guard page becomes guard instead of no-access, and so on. So, if the stack requirement increasing consequently and with not too big steps (greater than 1-2 pages), the system allocates it fine. If the code allocates too much - so the locals pointing below the guard page, with accessing to that locating code will cause an exception that system will decide as critical, because it waits only for guard page hits as proper stack increasing. It is just the system design - it does not commits the full stack size for the thread until it is really required - it saves the memory space that way, but the system needs a way to know if the code needs more stack - and this "commited-guard-noaccess" technique is the way how it does so.

That's not fancy stuff - MS's compilers actually have this functionality internally - they probe stack if the function has big locals (programmer can turn this functionality off, but it will lead to unpredictable results - on some systems prog with, let's say, 4200 locals bytes will work fine, on some it will crash, but if function has more than two pages of locals - it will crash for sure on every system). This macroses set just implements in more or less similar manner the techniques that are industrial standards for Windows ::) (stack probing and overflow checking).
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: dedndave on June 08, 2013, 12:32:32 AM
Quote from: Antariy on June 07, 2013, 11:58:59 PM
(programmer can turn this functionality off, but it will lead to unpredictable results - on some systems prog with, let's say, 4200 locals bytes will work fine, on some it will crash, but if function has more than two pages of locals - it will crash for sure on every system)

yah, with a compiler, the programmer really doesn't know how much space is used in locals - lol
with assembly language, you do know   :t

for probe code, i would suggest something like this
        ASSUME  FS:Nothing

    push    eax
    push    ecx
    mov     eax,esp
    mov     ecx,esp
    sub     eax,<(size of locals) AND -4)>
    .repeat
        push    ecx
        mov     esp,fs:[8]
    .until eax>=esp
    mov     esp,ecx
    pop     ecx
    pop     eax

        ASSUME  FS:ERROR


on another note.....
one of the things that bothers me about the assembler prologue/epilogue is the order registers are push/pop'ed
MyFunc PROC USES EBX ESI EDI dwParm:DWORD

    mov     eax,dwParm
    ret

MyFunc ENDP

will generate code that looks like this
MyFunc PROC dwParm:DWORD

    push    ebp
    mov     ebp,esp
    push    ebx
    push    esi
    push    edi
    mov     eax,[ebp+8]
    pop     edi
    pop     esi
    pop     ebx
    leave
    ret     4

MyFunc ENDP


it would be better to do it this way
LEAVE is executed first (balance the stack), then pop the USES registers
MyFunc PROC dwParm:DWORD

    push    ebx
    push    esi
    push    edi
    push    ebp
    mov     ebp,esp
    mov     eax,[ebp+20]
    leave
    pop     edi
    pop     esi
    pop     ebx
    ret     4

MyFunc ENDP


that way, you can use whatever stack you like without balancing it
when the routine exits, the stack is balanced before you restore the USES registers
you simply have to adjust EBP offsets by the space used in USES
i don't know if you can do that with a macro   :P
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: qWord on June 08, 2013, 12:55:15 AM
Quote from: Antariy on June 07, 2013, 11:58:59 PMIf the code allocates too much - so the locals pointing below the guard page, with accessing to that locating code will cause an exception that system will decide as critical, because it waits only for guard page hits as proper stack increasing.
that makes sense - learning never stops.
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: Antariy on June 08, 2013, 02:25:02 AM
Quote from: dedndave on June 08, 2013, 12:32:32 AM
Quote from: Antariy on June 07, 2013, 11:58:59 PM
(programmer can turn this functionality off, but it will lead to unpredictable results - on some systems prog with, let's say, 4200 locals bytes will work fine, on some it will crash, but if function has more than two pages of locals - it will crash for sure on every system)

yah, with a compiler, the programmer really doesn't know how much space is used in locals - lol
with assembly language, you do know   :t

for probe code, i would suggest something like this
...
on another note.....
one of the things that bothers me about the assembler prologue/epilogue is the order registers are push/pop'ed
...
that way, you can use whatever stack you like without balancing it
when the routine exits, the stack is balanced before you restore the USES registers
you simply have to adjust EBP offsets by the space used in USES
i don't know if you can do that with a macro   :P


As for runtime TEB values of the stack top and bottom - yes, I know that - in 2010 in the old forum I posted the prog in the recursion stack-discussion thread, don't remember how attachment is called (the file is TestStack.asm).
Here is the code:

include \masm32\include\masm32rt.inc

.data?
startFlag dd ?
numThreads dd ?
.code

AxGetStackBottom MACRO thereg:REQ, theallocationsize
ASSUME fs:NOTHING
mov thereg, fs:[4]
ifdif <theallocationsize>,<>
sub thereg,theallocationsize
add thereg,1024*32
else
sub thereg,(1024*1024-(1024*32))
endif
ASSUME fs:ERROR
EXITM<thereg>
ENDM

; First parameter is pointer to a structure:
; sampleControl struct
; aThreadNumber dd ?
; dwStackSizeEntered dd ?
; sampleControl ends
; but in main function this structure created with simple pushs - to be local for each thread,
; and for simpleness
; Second parameter is a pointer to a DWORD, which is incremented with each successful recursive
; calling to the next level

RecursiveFunction proc dwParam1:DWORD, dwParam2:DWORD
LOCAL bigbuffer[4000]:BYTE

mov ecx,dwParam1 ; get pointer to 2 DWORD - first is thread num, second is its stack size
mov ecx,[ecx+4]

cmp esp,AxGetStackBottom(eax,ecx)
jbe @tooLowStackLevel

mov ecx,dwParam2
inc dword ptr [ecx]
invoke RecursiveFunction,dwParam1,dwParam2
@tooLowStackLevel:
ret

RecursiveFunction endp

TheThread proc lpVoid:DWORD
lock inc dword ptr numThreads ; lock for case if you too fastly enter values :P

@@:
invoke Sleep,100
cmp startFlag,0
jz @B

mov ecx,lpVoid
mov ecx,[ecx]
invoke crt_printf,CTXT("Hi, this is thread #%u, starting recursive function...",10),ecx

push 0
invoke RecursiveFunction,lpVoid,esp

mov eax,lpVoid
mov eax,[eax]
invoke crt_printf,CTXT("The thread #%u do %u recursive calls (limited to the stack size only)",10),eax
lock dec dword ptr numThreads ; ...the same :P
pop edx
ret


TheThread endp


start:



invoke crt_printf,CTXT("Hi, this is testing program",10,"Enter a number of threads to test: ")
push eax
invoke crt_scanf,CTXT("%u"),esp
pop ebx
mov esi,1

push eax
@@:
invoke crt_printf,CTXT("Enter a stack size for the thread #%u: "),esi
push eax
invoke crt_scanf,CTXT("%u"),esp
mov ecx,[esp] ; thread stack size a second parameter of the structure
push esi ; thread number is a first parameter of the structure
mov edx,esp
push eax
invoke CreateThread,0,ecx,offset TheThread,edx,0,esp
pop eax
inc esi
cmp esi,ebx
jbe @B


or startFlag,1

@@:
invoke Sleep,100
cmp numThreads,0
jnz @B

lea esp,[esp+ebx*8+4]

invoke crt_printf,CTXT("All threads are finished, find and press [Any] key to exit..."),esi
invoke crt__getch

ret
end start


But I actually find it simpler to use the way I used. But your way is good, too :t Maybe it's worth to change it that way (that's why the probing code is a separate proc, not "inlined" code).

As for pushes/pops - I afraid it is not possible. At least as I understand it - the assembler only supports the "displacement" for a values inbetween the ebp and locals. I.e. it's just like the thing I used for the "salt" positioning - it lies between ebp and locals, so the first, let's say, local dword will be reffered not as [ebp-4] but as [ebp-8]. It's the addition that MACRO returns as a result of macro function (localbytes+4). But there are no documented values that may change the level of "up" direction (i.e. [ebp+12] instead of [ebp+8], for example). I decide this as an omission in the design, too - it may be very useful to change the uses pushes/locals placement.

But we can of course do it other way - I thought about it, too, this macros set was even unfinished till today, but the other question is: if something with the code goes that way that it really does crazy things like registers mess etc, is it really required to make things "look like" all is ok and restore execution state - is not it better to warn and / or terminate? The code that goes crazy may be already unpredictable, the data may be corrupted etc etc, and, the main note - in a well designed and tested programs there is no possibility of a stack imbalancing - that maybe accidental thing and it may be caught in a testing stage (with using this or similar prologue macroses), in a "release build" such a mess like regs trashing is not that frequent and important as a buffer overruns are, for an instance. The point is: if there is something wrong with the code and it already flagged that it's buggy, the values of regs that were saved above the locals (or below) may also be trashed - we cannot be sure, and that's a danger thing - just silently restore the state with the values we even cannot be sure are proper, and continue execution.

And, additional note: if we really need to preserve non-volatile regs across call, and if we decide EBP as the reg that will not be trashed in the called code (we decide it so because we anyway need proper EBP in the called buggy code to restore the ESP and, if we doing so, the execution state), then we can simply save the regs in a locals of a calling proc :biggrin: And restore them after a call (and check and warn and anything).

I.e. the sinopsis is that if there is something that really wants to change behaviour or crash our code - it will crash it, at least, if there is nothing such - for what is required such a complicated restoration methods? Restored state is not 100% guaranteed to be the same as it was before (something may even change the data in the .data section, may overwrite data in the stack above locals of current proc etc etc - if the assumed that the code got crazy - the regs will not trash from no reason, so, there was something that intentionally or accidentally makes a mess in the our code/data execution state, that maybe even external function from a DLL etc), and the improperly functionating program is worst than fully unfunctionating (crashed, warned and terminated etc) program.


What is your suggestion, Dave? It's maybe possible to duplicate the USES regs inbetween ebp and locals, but it will be not beautiful solution since assembler does not give other ways to do something like, and, again, buffer overruns will trash these preserved values. Probably it's better to make LOCALS as usually, but preserve regs not via USES but with a manual pushes - it will, at least, put the regs values below the locals (though this not gives much if huge buffer overrun had occured).


Quote from: qWord on June 08, 2013, 12:55:15 AM
that makes sense - learning never stops.

You are perfectly right, qWord :t
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: dedndave on June 08, 2013, 02:58:03 AM
i really don't have a suggestion, Alex
i am not much of a macro guy - lol

i quite often write my own stack frame so i can get what i want,
then i alias the names with TEXTEQU, using an underscore character
        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

GetFirstControlPoints PROC uKnotQty:UINT,lpKnotArray:LPVOID,lpResArray:LPVOID

;-----------------------------------------

_lpResArray   TEXTEQU <dword ptr [ebp+20]>  ;pointer to Res (result) array
_lpKnotArray  TEXTEQU <dword ptr [ebp+16]>  ;pointer to Knot array
_uKnotQty     TEXTEQU <dword ptr [ebp+12]>  ;knot point qty
;                                [ebp+8]    ;RETurn address
;                                [ebp+4]    ;saved EBX contents
;                                [ebp]      ;saved EBP contents

;-----------------------------------------

        push    ebx
        push    ebp
        mov     ebp,esp


i can leave the stack in whatever unbalanced state i like, then...
        leave
        pop     ebx
        ret     12

GetFirstControlPoints ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: jj2007 on June 08, 2013, 03:56:41 AM
Here is a similar option. It uses a standard stack frame but provides an extra large buffer:

include \masm32\MasmBasic\MasmBasic.inc        ; download (http://masm32.com/board/index.php?topic=94.0)

.code
MyProc proc uses esi edi ebx arg        ; ### StackBuffer example ###
LOCAL pBuffer, whatever
  ClearLocals
  mov pBuffer, StackBuffer(100000)        ; 16-byte aligned & probed
  Print "pBuffer=", Hex$(pBuffer)
  StackBuffer()  ; release buffer
  ret
MyProc endp

        Init
        mov ecx, esp
        mov esi, 111111111
        mov ebx, 222222222
        invoke MyProc, 12345h
        sub ecx, esp
        deb 4, "Out", esi, ebx, ecx
        Inkey
        Exit
end start


Output:
pBuffer=001178B0
Out
esi             111111111
ebx             222222222
ecx             0


However, it's not yet the solution that Dave has in mind, i.e. leaving without caring for the stack...
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: dedndave on June 08, 2013, 04:32:10 AM
these might be of help

it may be possible to do USES push first   :P

http://msdn.microsoft.com/en-us/library/4zc781yh%28v=vs.80%29.aspx (http://msdn.microsoft.com/en-us/library/4zc781yh%28v=vs.80%29.aspx)
http://read.pudn.com/downloads149/doc/642485/MASM613/INCLUDE/PROLOGUE.INC__.htm (http://read.pudn.com/downloads149/doc/642485/MASM613/INCLUDE/PROLOGUE.INC__.htm)
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: jj2007 on June 08, 2013, 06:53:13 AM
Excellent links, Dave :t
And it works:

include \masm32\include\masm32rt.inc
include JJLogue.inc

.code
mytest proc uses esi edi ebx arg1, arg2
LOCAL abc, rc:RECT, def, ghi, jkl
  push 123                ; let's play foul...
  push 456
  push 789
  mov abc, 12345678h
  print hex$(arg1), 9, "arg1", 13, 10
  print hex$(arg2), 9, "arg2", 13, 10
  print hex$(abc), 9, "abc", 13, 10, 10
  push 123                ; let's play foul...
  push 456
  push 789
  ret
mytest endp

start:
        mov esi, 11111111h
        mov edi, 22222222h
        mov ebx, 33333333h
        invoke mytest, 123h, 456h
        print hex$(esi), 9, "esi", 13, 10
        print hex$(edi), 9, "edi", 13, 10
        print hex$(ebx), 9, "ebx", 13, 10
        inkey
        exit
end start


Output:
00000123        arg1
00000456        arg2
12345678        abc

11111111        esi
22222222        edi
33333333        ebx

:biggrin:
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: Antariy on June 08, 2013, 07:43:48 AM
Quote from: dedndave on June 08, 2013, 04:32:10 AM
these might be of help

it may be possible to do USES push first   :P

http://msdn.microsoft.com/en-us/library/4zc781yh%28v=vs.80%29.aspx (http://msdn.microsoft.com/en-us/library/4zc781yh%28v=vs.80%29.aspx)
http://read.pudn.com/downloads149/doc/642485/MASM613/INCLUDE/PROLOGUE.INC__.htm (http://read.pudn.com/downloads149/doc/642485/MASM613/INCLUDE/PROLOGUE.INC__.htm)

Yes, we can do pushes before or after stack allocation, but if we do it before stack frame setup, the assembler still have no way to be informed that params of the function now lie higher than usually.
Thank you for the links, Dave :t It seems that missed FORCEFRAME option.

But the way Jochen used works :t Even if we cannot make assembler to refer "higher ebp" values, we still can use inter-macro (non-local) variable - nice and simple solution :biggrin:
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: TouEnMasm on June 08, 2013, 03:01:50 PM
I don't see where is the problem to have a proc who use more than one page of stack memory ?.
Perhaps someone could enlight me or give a sample who have a real problem with that ?.

sample:

;################################################################
Big_stack_proc PROC
Local bigone[1000h]:DWORD
Local  retour:DWORD
         mov retour,1            ;access violation without correction

FindeBig_stack_proc:
         mov eax,retour
         ret
Big_stack_proc endp


Soluce:add this to your code

option dotname
.drectve  segment info
    db "-stack:0x100000,0x5000 "
.drectve ends

and no more problem
The .drectve  is a special object segment dedicated to pass order for link.
Same thing can be done with "link /STACK:0x100000,0x5000 "
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: MichaelW on June 08, 2013, 04:47:57 PM
Quote from: ToutEnMasm on June 08, 2013, 03:01:50 PM
I don't see where is the problem to have a proc who use more than one page of stack memory ?.
Perhaps someone could enlight me or give a sample who have a real problem with that ?.

It depends on the value in ESP at procedure entry. This is obviously a contrived example, but the problem can occur when ESP is anywhere in the bottom page of the stack.

;==============================================================================
include \masm32\include\masm32rt.inc
;==============================================================================
.data
.code
;==============================================================================
Proc1 proc
    LOCAL array[4096]:BYTE
    mov al, array[0]
    ret
Proc1 endp
;==============================================================================
start:
;==============================================================================
    assume fs:NOTHING
    mov ebx, fs:[8]
    printf("Current bottom of stack: %Xh\n", ebx)
    add ebx, 4
    mov esp, ebx
    call Proc1
    mov ebx, fs:[8]
    printf("Current bottom of stack: %Xh\n\n", ebx)
    inkey
    exit
;==============================================================================
end start


From the listing, with comments added:

Proc1 proc
    LOCAL array[4096]:BYTE
    push ebp                ; access into guard page
    mov ebp, esp
    add esp, 0FFFFF000h
    mov al, array[0]        ; access into new guard page
    leave
    ret
Proc1 endp


Current bottom of stack: 12E000h
Current bottom of stack: 12C000h


If I change the LOCAL allocation to 4096*2 then the app crashes because the second access skips over the new guard page and accesses uncommitted stack space.
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: jj2007 on June 08, 2013, 05:06:03 PM
Quote from: ToutEnMasm on June 08, 2013, 03:01:50 PM
I don't see where is the problem to have a proc who use more than one page of stack memory ?

See also reply #2 (http://masm32.com/board/index.php?topic=2003.msg20935#msg20935). For XP, you need crash=3990.
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: sinsi on June 08, 2013, 06:14:05 PM
Quote from: MichaelW on June 08, 2013, 04:47:57 PM
If I change the LOCAL allocation to 4096*2 then the app crashes because the second access skips over the new guard page and accesses uncommitted stack space.
Looks like Windows 8 guards against that, there is no crash.


eax=00000022 ebx=0018e004 ecx=7572c196 edx=004f2438 esi=00000000 edi=00000000
eip=00401009 esp=0018bffc ebp=0018dffc iopl=0         nv up ei pl nz na pe cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000207
image00400000+0x1009:
00401009 8a8500e0ffff    mov     al,byte ptr [ebp-2000h]    ss:002b:0018bffc=??
0:000> t
eax=00000000 ebx=0018e004 ecx=7572c196 edx=004f2438 esi=00000000 edi=00000000
eip=0040100f esp=0018bffc ebp=0018dffc iopl=0         nv up ei pl nz na pe cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000207
image00400000+0x100f:
0040100f c9              leave
0:000> r eip=401009
0:000> r
eax=00000000 ebx=0018e004 ecx=7572c196 edx=004f2438 esi=00000000 edi=00000000
eip=00401009 esp=0018bffc ebp=0018dffc iopl=0         nv up ei pl nz na pe cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000207
image00400000+0x1009:
00401009 8a8500e0ffff    mov     al,byte ptr [ebp-2000h]    ss:002b:0018bffc=00

Notice after "ss:002b:0018bffc=??" we get "ss:002b:0018bffc=00"
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: sinsi on June 08, 2013, 07:16:23 PM
Upon further tests:
     LOCAL array[4096*3-3]:BYTE will crash
     LOCAL array[4096*3-4]:BYTE will work

Current bottom of stack: 18E000h
Current bottom of stack: 18B000h



Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: TouEnMasm on June 08, 2013, 09:51:32 PM

I see nothing that couldn't be solved by a link option.
Except when the reserved stack is fully used.
Perhaps the system is not abble to add more than one page in the same time.
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: Antariy on June 08, 2013, 10:55:13 PM
Here is the info & crash testing proggie.

It's quite clear - read the code.

At least on XP the design is the same - see the results.

Short explanation on how to treat results.

First two tables are for the same page - bottom of the stack, just reffered with ESP and the bottom line.
Here you should look on the State and Protect fields, the memory is commited (1000h) and has PAGE_READWRITE access (4), so, this is normal stack location - ready for use to store the data.

Third table is a next page below the bottom of stack.
Here you may see that it is commited, and has PAGE_READWRITE + PAGE_GUARD access (104h). This is a guard page hitting of which tells the system there is need to grow the stack.

Fourth and fifth table are next two pages below the guard page, they show that this memory location is not commited - it is reserved, and it has no  protect what is, shortly speaking, equal to no access protect (causes a crash if code accesses it with any kind of read/write).


There are 3 steps - you can change the value in the top of the code - that show in real time how the stack is growing, and for every step there will be five (or more - you may at the top of the code change how much pages below the bottom are acessed to show their state). And for my system each step shows the same result - bottom (and upper, of course) of the stack is a normal data location, page below of bottom - is the guard, and the next pages are no access memory location.



After these steps the code will cause a crash - intentionally - to show in which circumstances the crash of this type will occur. Also this code consequently increases the page-step (shortly speaking, the "buffer size" required to crash the program if the locals after entry in the proc will point below the guard page), so it will show the smallest required buffer size to get a crash in a suitable circumstance. In real world this will be random thing - on some machines real prog will crash with the minimal buffer size that there will be shown, on some it will not crash, but for clearness the code produces the enviroment of the worst-case layout - we are on the bottom page, and pointing beyound guard page, the step is starting from 4096 bytes - i.e. one page - plus 4 bytes - to access beyound the guard page.
For me it crashes from first iteration - with 4096 bytes step - just like it should do and was expected (at least for my system).

As for "real world program" note: even if on some systems the program with the locals a bit larger than 4096 bytes is not crashes, this means nothing, really. That's just because the locals were placed NOT in the last page of the stack. That's why it is required to write the proggie like posted one is, to show how this crash works. "Real program" with big locals and no probing code will be real "random crash generator" which will be absolutely unpredictable when and where it will crash.


It will be very interesting to see how it behaves on different systems, especially WinVista/7/8.
Please, since the program dumps much of info, redirect its output to the textual file from the command line, and copy contents of the file here.



=== Dump info for growing stack, 3 steps ===


============== Step #1 ==============

In printinfo1, ESP: 0012DFC8, stack bottom: 0012D000
VirtualQuery for ESP:
        BaseAddress:            0012D000
        AllocationBase:         00030000
        AllocationProtect:      00000004
        RegionSize:             00003000
        State:                  00001000
        Protect:                00000004
        Type:                   00020000

In printinfo1, ESP: 0012DFC8, stack bottom: 0012D000
VirtualQuery for the stack bottom:
        BaseAddress:            0012D000
        AllocationBase:         00030000
        AllocationProtect:      00000004
        RegionSize:             00003000
        State:                  00001000
        Protect:                00000004
        Type:                   00020000

In printinfo1, ESP: 0012DFC8, stack bottom: 0012D000
VirtualQuery for page step below bottom...:
        BaseAddress:            0012C000
        AllocationBase:         00030000
        AllocationProtect:      00000004
        RegionSize:             00001000
        State:                  00001000
        Protect:                00000104
        Type:                   00020000

In printinfo1, ESP: 0012DFC8, stack bottom: 0012D000
VirtualQuery for page step below bottom...:
        BaseAddress:            0012B000
        AllocationBase:         00030000
        AllocationProtect:      00000004
        RegionSize:             00001000
        State:                  00002000
        Protect:                00000000
        Type:                   00020000

In printinfo1, ESP: 0012DFC8, stack bottom: 0012D000
VirtualQuery for page step below bottom...:
        BaseAddress:            0012A000
        AllocationBase:         00030000
        AllocationProtect:      00000004
        RegionSize:             00002000
        State:                  00002000
        Protect:                00000000
        Type:                   00020000


============== Step #2 ==============

In printinfo1, ESP: 0012CFC8, stack bottom: 0012C000
VirtualQuery for ESP:
        BaseAddress:            0012C000
        AllocationBase:         00030000
        AllocationProtect:      00000004
        RegionSize:             00004000
        State:                  00001000
        Protect:                00000004
        Type:                   00020000

In printinfo1, ESP: 0012CFC8, stack bottom: 0012C000
VirtualQuery for the stack bottom:
        BaseAddress:            0012C000
        AllocationBase:         00030000
        AllocationProtect:      00000004
        RegionSize:             00004000
        State:                  00001000
        Protect:                00000004
        Type:                   00020000

In printinfo1, ESP: 0012CFC8, stack bottom: 0012C000
VirtualQuery for page step below bottom...:
        BaseAddress:            0012B000
        AllocationBase:         00030000
        AllocationProtect:      00000004
        RegionSize:             00001000
        State:                  00001000
        Protect:                00000104
        Type:                   00020000

In printinfo1, ESP: 0012CFC8, stack bottom: 0012C000
VirtualQuery for page step below bottom...:
        BaseAddress:            0012A000
        AllocationBase:         00030000
        AllocationProtect:      00000004
        RegionSize:             00001000
        State:                  00002000
        Protect:                00000000
        Type:                   00020000

In printinfo1, ESP: 0012CFC8, stack bottom: 0012C000
VirtualQuery for page step below bottom...:
        BaseAddress:            00129000
        AllocationBase:         00030000
        AllocationProtect:      00000004
        RegionSize:             00002000
        State:                  00002000
        Protect:                00000000
        Type:                   00020000


============== Step #3 ==============

In printinfo1, ESP: 0012BFC8, stack bottom: 0012B000
VirtualQuery for ESP:
        BaseAddress:            0012B000
        AllocationBase:         00030000
        AllocationProtect:      00000004
        RegionSize:             00005000
        State:                  00001000
        Protect:                00000004
        Type:                   00020000

In printinfo1, ESP: 0012BFC8, stack bottom: 0012B000
VirtualQuery for the stack bottom:
        BaseAddress:            0012B000
        AllocationBase:         00030000
        AllocationProtect:      00000004
        RegionSize:             00005000
        State:                  00001000
        Protect:                00000004
        Type:                   00020000

In printinfo1, ESP: 0012BFC8, stack bottom: 0012B000
VirtualQuery for page step below bottom...:
        BaseAddress:            0012A000
        AllocationBase:         00030000
        AllocationProtect:      00000004
        RegionSize:             00001000
        State:                  00001000
        Protect:                00000104
        Type:                   00020000

In printinfo1, ESP: 0012BFC8, stack bottom: 0012B000
VirtualQuery for page step below bottom...:
        BaseAddress:            00129000
        AllocationBase:         00030000
        AllocationProtect:      00000004
        RegionSize:             00001000
        State:                  00002000
        Protect:                00000000
        Type:                   00020000

In printinfo1, ESP: 0012BFC8, stack bottom: 0012B000
VirtualQuery for page step below bottom...:
        BaseAddress:            00128000
        AllocationBase:         00030000
        AllocationProtect:      00000004
        RegionSize:             00002000
        State:                  00002000
        Protect:                00000000
        Type:                   00020000



=== Crash - continuously access below guard page with increasing the step ===

Step size: -4096, ESP: 0012BFFC, Stack bottom: 0012B000
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: TouEnMasm on June 08, 2013, 11:12:09 PM

For me the question is how to avoid these:
Conditions to have a crash in XP is when the proc need more than one page of stack memory.In XP one page is 1000h.
If the stack memory is not allowed,the system do it at the first write.
If the system need to allocate two pages,there is a crash.
This one could be avoid with LInk /STACK option.
If max stack PROC > 1 page Need LInk /STACK   else       no risk
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: Antariy on June 08, 2013, 11:12:25 PM
Quote from: ToutEnMasm on June 08, 2013, 09:51:32 PM

I see nothing that couldn't be solved by a link option.
Except when the reserved stack is fully used.
Perhaps the system is not abble to add more than one page in the same time.


Michael has already shortly and well described when the problem will occur.
And increasing the commited stack size (and/or stack size at all) is not the real solution - in the system there is not only one program running, so the solution like "Let's set our app's stack size to a half of a gigabyte and commit it all!" will a bit surprise the Windows, especially if there will be couple of such programs to run. Or one program but with couple threads (since default thread stack size is equal to the main thread stack size). The growable stack mechanism was intended not to be overcomed with such ways.
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: TouEnMasm on June 08, 2013, 11:15:27 PM

I was writing the results of my test when your post had been write
try to put this rules in fault
If max stack PROC > 1 page Need LInk /STACK   else       no risk
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: Antariy on June 08, 2013, 11:22:45 PM
Quote from: ToutEnMasm on June 08, 2013, 11:12:09 PM

For me the question is how to avoid these:
Conditions to have a crash in XP is when the proc need more than one page of stack memory.In XP one page is 1000h.
If the stack memory is not allowed,the system do it at the first write.
If the system need to allocate two pages,there is a crash.
This one could be avoid with LInk /STACK option.
If max stack PROC > 1 page Need LInk /STACK   else       no risk


The point is: in link time you do not know when and where your program will go to the last page and will at this moment in the proc with huge locals. If such proc does not use probing code, the only "solution" is to make commited stack size = full stack size, but this is not proper thing to do in multitasking environment. And if you commit some other stack size - there is not guarantee that in some system, especially with each new one version, the program will not crash. It will be random crash generator, even if this behaviour will be masked first.
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: TouEnMasm on June 08, 2013, 11:38:26 PM
To antarity,I had have a look on on your CrashStack.zip,here is the result

Windbg answer:[quote][/quote]
004011b5 8b443efc        mov     eax,dword ptr [esi+edi-] :0023:00129ffc=????????
source code:
invoke crt_printf,CTXT("Step size: %d, ESP: %p, Stack bottom: %p",10),esi,ecx,edi
    mov eax,[edi+esi-4]       <<<<<<<<<<<< JUST A BUG

Use a debugger before anything.
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: Antariy on June 08, 2013, 11:44:07 PM
LOOOOOOOOOL
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: jj2007 on June 09, 2013, 03:32:58 AM
Quote from: ToutEnMasm on June 08, 2013, 11:38:26 PM
    mov eax,[edi+esi-4]       <<<<<<<<<<<< JUST A BUG

Yves,

Since you certainly don't understand why Alex writes LOOOOL, just a simple question:

Do you occasionally read comments?


    mov eax,[edi+esi-4]
    ; edi is a stack bottom
    ; esi - is a page sized step
    ; 4 is a displacement to access beyond (lower) than next page (guard)
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: TouEnMasm on June 09, 2013, 03:48:29 AM

The debugger made an enough comment


BAD ADRESS

Perhaps are you able to see this one ?
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: jj2007 on June 09, 2013, 04:33:39 AM
Yves, no need to shout. "Bad address" is the whole point of this thread. The "bad" address is slightly below the current stack, and that's what we are discussing here.
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: TouEnMasm on June 09, 2013, 04:57:16 AM
I made it you more simple,i dont show the calcul.

take a proc at start who call just this proc:

;################################################################
Big_stack_proc PROC
Local bigone[0ff2h]:DWORD
Local retour:DWORD
mov retour,1         <<<< bug here
invoke StackSize

FindeBig_stack_proc:
         mov eax,retour
         ret
Big_stack_proc endp

The debugger show the bad adress:
00401082 c78534c0ffff01000000 mov dword ptr [ebp-3FCCh],1 ss:0023:0012bff0=????????
For what ? The proc just need more than one page of stack and the system failed to allow this two pages and the memory is not allowed,even if there is enough memory reserved (1Mo).

The calcul  of Local bigone[0ff2h]:DWORD is just made to need more than one page with  the start position of esp.

The question stay how to avoid this.Answer

If max stack PROC > 1 page Need LInk /STACK   else       no risk

Reply to the question and you win.
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: jj2007 on June 09, 2013, 05:56:41 AM
Quote from: ToutEnMasm on June 09, 2013, 04:57:16 AM
Reply to the question and you win.

Yves, the system reserves a megabyte or so anyway. It's just not committed, so you have to probe it (that's the main issue of this thread).

Of course, you can commit a gigabyte with /Stack, but for good reasons it's not considered good programming practice.
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: Gunther on June 09, 2013, 08:37:58 AM
Hi Alex,

the program crashed under Windows 7. Here is the rest of the output:


c:\scratch03>CrashStack.exe
=== Dump info for growing stack, 3 steps ===


============== Step #1 ==============

In printinfo1, ESP: 0018DFC8, stack bottom: 0018D000
VirtualQuery for ESP:
        BaseAddress:            0018D000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00003000
        State:                  00001000
        Protect:                00000004
        Type:                   00020000

In printinfo1, ESP: 0018DFC8, stack bottom: 0018D000
VirtualQuery for the stack bottom:
        BaseAddress:            0018D000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00003000
        State:                  00001000
        Protect:                00000004
        Type:                   00020000

In printinfo1, ESP: 0018DFC8, stack bottom: 0018D000
VirtualQuery for page step below bottom...:
        BaseAddress:            0018C000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00001000
        State:                  00001000
        Protect:                00000104
        Type:                   00020000

In printinfo1, ESP: 0018DFC8, stack bottom: 0018D000
VirtualQuery for page step below bottom...:
        BaseAddress:            0018B000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00001000
        State:                  00002000
        Protect:                00000000
        Type:                   00020000

In printinfo1, ESP: 0018DFC8, stack bottom: 0018D000
VirtualQuery for page step below bottom...:
        BaseAddress:            0018A000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00002000
        State:                  00002000
        Protect:                00000000
        Type:                   00020000


============== Step #2 ==============

In printinfo1, ESP: 0018CFC8, stack bottom: 0018C000
VirtualQuery for ESP:
        BaseAddress:            0018C000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00004000
        State:                  00001000
        Protect:                00000004
        Type:                   00020000

In printinfo1, ESP: 0018CFC8, stack bottom: 0018C000
VirtualQuery for the stack bottom:
        BaseAddress:            0018C000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00004000
        State:                  00001000
        Protect:                00000004
        Type:                   00020000

In printinfo1, ESP: 0018CFC8, stack bottom: 0018C000
VirtualQuery for page step below bottom...:
        BaseAddress:            0018B000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00001000
        State:                  00001000
        Protect:                00000104
        Type:                   00020000

In printinfo1, ESP: 0018CFC8, stack bottom: 0018C000
VirtualQuery for page step below bottom...:
        BaseAddress:            0018A000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00001000
        State:                  00002000
        Protect:                00000000
        Type:                   00020000

In printinfo1, ESP: 0018CFC8, stack bottom: 0018C000
VirtualQuery for page step below bottom...:
        BaseAddress:            00189000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00002000
        State:                  00002000
        Protect:                00000000
        Type:                   00020000


============== Step #3 ==============

In printinfo1, ESP: 0018BFC8, stack bottom: 0018B000
VirtualQuery for ESP:
        BaseAddress:            0018B000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00005000
        State:                  00001000
        Protect:                00000004
        Type:                   00020000

In printinfo1, ESP: 0018BFC8, stack bottom: 0018B000
VirtualQuery for the stack bottom:
        BaseAddress:            0018B000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00005000
        State:                  00001000
        Protect:                00000004
        Type:                   00020000

In printinfo1, ESP: 0018BFC8, stack bottom: 0018B000
VirtualQuery for page step below bottom...:
        BaseAddress:            0018A000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00001000
        State:                  00001000
        Protect:                00000104
        Type:                   00020000

In printinfo1, ESP: 0018BFC8, stack bottom: 0018B000
VirtualQuery for page step below bottom...:
        BaseAddress:            00189000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00001000
        State:                  00002000
        Protect:                00000000
        Type:                   00020000

In printinfo1, ESP: 0018BFC8, stack bottom: 0018B000
VirtualQuery for page step below bottom...:
        BaseAddress:            00188000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00002000
        State:                  00002000
        Protect:                00000000
        Type:                   00020000



=== Crash - continuously access below guard page with increasing the step ===

Step size: -4096, ESP: 0018BFFC, Stack bottom: 0018B000


I hope that helps.

Gunther
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: Antariy on June 09, 2013, 09:57:49 AM
Hi Gunther :t

Yes, the crash is intentional - after it dumps info about bottom of growing stack and its near area, the program intentionally causes a crash acessing a bit below over guard page. Your results shows that on Win7 the system strategy is the same - commited data area, then guard page, then uncommited area with no access.
Thank you very much :biggrin:

It would be also interesting to see what will it show on Win8, can I please ask some body to test it on that system?
It's curious if they had enlarged the guard area from one page to more pages in size on Win8.
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: sinsi on June 09, 2013, 11:42:32 AM
Windows 8 Pro x64

=== Dump info for growing stack, 3 steps ===


============== Step #1 ==============

In printinfo1, ESP: 0018CFC8, stack bottom: 0018C000
VirtualQuery for ESP:
        BaseAddress:            0018C000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00004000
        State:                  00001000
        Protect:                00000004
        Type:                   00020000

In printinfo1, ESP: 0018CFC8, stack bottom: 0018B000
VirtualQuery for the stack bottom:
        BaseAddress:            0018B000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00005000
        State:                  00001000
        Protect:                00000004
        Type:                   00020000

In printinfo1, ESP: 0018CFC8, stack bottom: 0018B000
VirtualQuery for page step below bottom...:
        BaseAddress:            0018A000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00001000
        State:                  00001000
        Protect:                00000104
        Type:                   00020000

In printinfo1, ESP: 0018CFC8, stack bottom: 0018B000
VirtualQuery for page step below bottom...:
        BaseAddress:            00189000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00002000
        State:                  00001000
        Protect:                00000104
        Type:                   00020000

In printinfo1, ESP: 0018CFC8, stack bottom: 0018B000
VirtualQuery for page step below bottom...:
        BaseAddress:            00188000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00001000
        State:                  00002000
        Protect:                00000000
        Type:                   00020000


============== Step #2 ==============

In printinfo1, ESP: 0018AFC8, stack bottom: 0018A000
VirtualQuery for ESP:
        BaseAddress:            0018A000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00006000
        State:                  00001000
        Protect:                00000004
        Type:                   00020000

In printinfo1, ESP: 0018AFC8, stack bottom: 00189000
VirtualQuery for the stack bottom:
        BaseAddress:            00189000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00007000
        State:                  00001000
        Protect:                00000004
        Type:                   00020000

In printinfo1, ESP: 0018AFC8, stack bottom: 00189000
VirtualQuery for page step below bottom...:
        BaseAddress:            00188000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00001000
        State:                  00001000
        Protect:                00000104
        Type:                   00020000

In printinfo1, ESP: 0018AFC8, stack bottom: 00189000
VirtualQuery for page step below bottom...:
        BaseAddress:            00187000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00002000
        State:                  00001000
        Protect:                00000104
        Type:                   00020000

In printinfo1, ESP: 0018AFC8, stack bottom: 00189000
VirtualQuery for page step below bottom...:
        BaseAddress:            00186000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00001000
        State:                  00002000
        Protect:                00000000
        Type:                   00020000


============== Step #3 ==============

In printinfo1, ESP: 00188FC8, stack bottom: 00188000
VirtualQuery for ESP:
        BaseAddress:            00188000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00008000
        State:                  00001000
        Protect:                00000004
        Type:                   00020000

In printinfo1, ESP: 00188FC8, stack bottom: 00187000
VirtualQuery for the stack bottom:
        BaseAddress:            00187000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00009000
        State:                  00001000
        Protect:                00000004
        Type:                   00020000

In printinfo1, ESP: 00188FC8, stack bottom: 00187000
VirtualQuery for page step below bottom...:
        BaseAddress:            00186000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00001000
        State:                  00001000
        Protect:                00000104
        Type:                   00020000

In printinfo1, ESP: 00188FC8, stack bottom: 00187000
VirtualQuery for page step below bottom...:
        BaseAddress:            00185000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00002000
        State:                  00001000
        Protect:                00000104
        Type:                   00020000

In printinfo1, ESP: 00188FC8, stack bottom: 00187000
VirtualQuery for page step below bottom...:
        BaseAddress:            00184000
        AllocationBase:         00090000
        AllocationProtect:      00000004
        RegionSize:             00001000
        State:                  00002000
        Protect:                00000000
        Type:                   00020000



=== Crash - continuously access below guard page with increasing the step ===

Step size: -4096, ESP: 00188FFC, Stack bottom: 00187000
Step size: -8192, ESP: 00188FFC, Stack bottom: 00185000
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: Antariy on June 09, 2013, 11:51:27 AM
Hi John :t

Thank you very much!
So, it seems they really had enlarged the guard area - probably for some compatibility reason (actually even on not so modern systems, like WinXP is, there was some problems with "old software", and compatibility fix related to a stack; but it seems that there are probably exist much of handcrafted proggies of early era that have not cared about stack probing - so probably MS decided to increase the compatibility with older software in that extent extending the guard area).
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: Antariy on June 09, 2013, 12:08:26 PM
...and now anyone may merry roll nice procs with up to 8 KB of locals and don't bother with anything (under Win8). Well, that's how the conniving of programmer's lazyness and careless growing on your eyes :lol: Well, these days the "common" RAM size increasing with such speed, that it seems they will soon commit full stack size - less underlying details required from programmer to know, less problems to an OS vendor :greensml:

This is post of humor. Humor??? :biggrin:
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: TouEnMasm on June 09, 2013, 03:56:39 PM

Here a piece of code to made controls in access memory.The sample is adapted to the stack need.


.const
SAFEMEM MACRO adress:REQ
mov keepesp,esp ;preserve esp
mov esp,SafeStackPlace ;usable stack
invoke Good_Adress,addr adress
.if eax == 1
mov esp,keepesp
.else
mov eax,@Line   ;return the line of the error (GetExitCodeProcess)
invoke ExitProcess,eax
.endif
ENDM

.data
SafeStackPlace  dd 0
keepesp dd 0

.code
;--------- at the start of the executable --------------------
mov SafeStackPlace,esp
sub esp,100h                           ;reserve good stack to allow the use of VirtualQuery
;---------- the proc ------------------------------------------
;0 inaccessible
;1 accès autorisé
;################################################################
Good_Adress PROC pchain:DWORD
Local mem_basic_inf:MEMORY_BASIC_INFORMATION
Local  retour:DWORD
      mov retour,0
mov edx,pchain
invoke VirtualQuery,pchain,addr mem_basic_inf,sizeof mem_basic_inf
.if eax != 0
mov eax,mem_basic_inf.AllocationProtect
.if eax == 0
jmp fin
.endif
;------- general access conditions ---------
test eax,PAGE_NOACCESS
jnz fin
test eax,PAGE_EXECUTE
jnz fin
test eax,PAGE_GUARD
jnz fin
;------------ verify for stack ------------
mov eax,mem_basic_inf.State
test eax,MEM_COMMIT
jz fin
mov retour,1
.endif 
fin:
FindeGood_Adress:
         mov eax,retour
         ret
Good_Adress endp

;--------------------- and now use it --------------------------------------------
;################################################################
Big_stack_proc PROC
Local bigone[0ff2h]:DWORD ;The system need to add more than one page to the stack
Local retour:DWORD
SAFEMEM retour
invoke MessageBox,NULL,ADDR All_is_good,addr titre,MB_OK
FindeBig_stack_proc:
         mov eax,retour
         ret
Big_stack_proc endp


Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: farrier on June 09, 2013, 04:14:18 PM
This was first experience with a large set of local variables that caused a GPF.  The best solution from all the suggestions was:

MainDlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lPar am:LPARAM
  LOCAL buffer[4096]:byte
  LOCAL buffer2[256]:byte
  LOCAL buffer3[256]:byte
  LOCAL printout[4096]:byte
   
  LOCAL pos:dword
  LOCAL hdi:HD_ITEM

  ;Touching the stack frame
  mov eax,ebp
  .while eax>esp
     mov dword ptr [eax],0
     sub eax, 4096
  .endw
  push edx
  push esi
  push edi


The following links describe the problem:

http://www.masmforum.com/board/index.php?topic=2011.0

http://www.asmcommunity.net/board/index.php?topic=19497.msg150610#msg150610

http://www.asmcommunity.net/board/index.php?topic=13525.0

My problem showed in WIN95 but not in most others.

hth,

farrier
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: TouEnMasm on June 09, 2013, 05:02:03 PM

I agree with you,1121_StackProbe.zip (archive 2) answer the question  :t
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: Antariy on June 09, 2013, 08:42:30 PM
Hi farrier, yes, your example is good and your solution is right - and is in the stack probing.
As for not crashing on other systems - that depends on much of things, and if that program will have more or less complex recursion - it may crash. As a recursion here maybe SendMessage from this dialog proc or any proc it calls, or other type of deep callback (like MessageBox displaying or creating the child dialog etc etc). So, the probing is the best solution to make robust code.

But the one of points of this thread is that the macroses set - the thing this thread is about - implements the stack probing automatically, if the size of locals is indicating need in this.

But Yves' messages here, especially after the one that is just above this post, looks just as pure paradox.


And, remember that the thread "main point" was not about stack probing, but about stack balancing - that's where it started from :biggrin: This macroses set, even in the state as it currently is, may be used as a simple tool to detect a stack imbalancing when program is developed. Besides of that the same feature may be used to detect buffer overruns. Though it all was described better in the first post of the thread.
Title: Re: More Advanced Prologue and Epilogue MACROses for PROCs
Post by: Gunther on June 09, 2013, 08:57:16 PM
Hi Alex,

Quote from: Antariy on June 09, 2013, 08:42:30 PM
And, remember that the thread "main point" was not about stack probing, but about stack balancing - that's where it started from :biggrin: This macroses set, even in the state as it currently is, may be used as a simple tool to detect a stack imbalancing when program is developed. Besides of that the same feature may be used to detect buffer overruns. Though it all was described better in the first post of the thread.

that's very clear and your goals are well described in the first post.  :t

Gunther