News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Self-Expanding Buffer

Started by MichaelW, April 04, 2011, 11:36:10 AM

Previous topic - Next topic

MichaelW

The attachment is a first attempt that appears to work OK.

Note that this will have the same problem with overstepping the guard page as the stack does. You must limit the increase in buffer size for any single access to the size of a page (normally 4096 bytes).
eschew obfuscation

Biterider

Hi Michael
Good approach but I think see a problem. What happens when you have more than 1 such a buffer? How does the exception filter know what buffer raised the exception?

Biterider

MichaelW

Hi Biterider,

Thanks, I had not considered supporting more than one buffer. I think this would a worthwhile feature, and I think I see a reasonable way to do.
eschew obfuscation

Biterider

Hi Michael
Did you make any progress on the exception code to identify the buffer that needs more memory?
If you have an idea, we can elaborate it...

Regards,

Biterider

MichaelW

Hi Biterider,

Yes, I did. I have what I think is a workable plan that will support multiple buffers in multiple threads. Every test I have run indicates that it will work, and while it is somewhat complex it should not be difficult to implement. The current problem is with finding the time to work on it.

eschew obfuscation

Biterider

#5
Hi Michael
I did some experiments this weekend to test some alternatives and finally found a good way to solve the exception handler problem.

There are additional information passed to the handler when a Page Guard is hit at the end of  the EXCEPTION_RECORD in the ExceptionInformation field. The second dword is a pointer to the memory location that generated the access fault.

The second trick is storing additional information on the guard page before the guard flag is set. This information can be read back by the handler since the OS resets this flag before the handler is executed.

One concern is multithreading. I put in the handler code a synchronisation mechanism to avoid the corruption of the buffer data.

Biterider

PS: new upload with stack checking for regular guard page exceptions.

MichaelW

Hi Biterider,

Thanks for the code. It made sense to me that the system would send the exception filter additional information on the exception, but when I searched I could not find any reference to this. Your solution is much simpler than mine was. Basically, since the exception filter is called in the context of the thread that caused the fault, I was going to maintain a list of active guard page addresses in TLS and on each exception get the guard page address by scanning the list for the guard page with the PAGE_GUARD modifier cleared.
eschew obfuscation

Biterider

Hi Michael
http://msdn.microsoft.com/en-us/library/aa363082(v=vs.85).aspx at the end of the page gives a short explanation for the ExceptionInformation field, in particular for the EXCEPTION_ACCESS_VIOLATION. Strange that the EXCEPTION_GUARD_PAGE isn't mentioned, but it behaves in the same way.

Biterider

MichaelW

Quotehttp://msdn.microsoft.com/en-us/library/aa363082(VS.85).aspx

Thanks, I actually looked at that page, but I was looking at the ExceptionAddress member and not at the details for EXCEPTION_ACCESS_VIOLATION.
eschew obfuscation

Biterider

Hi
Looking at the UnhandledExceptionHandler procedure, I'm unsure if the classic ebx,edi,esi,etc registers should be preserved or not. I know that callback procedures must do it, but in this particular case, the procedure is not defined as a callback. A simple test doesn't change the behaviour on WinXP, but I don't know what happens on different Windows versions. Any advice?

Biterider

MichaelW

To do any sort of conclusive test you would need to have access to a wide variety of Windows versions and builds.

It seems to me that the filter procedure is a callback in that the system is calling it. I can't see any reason why the register-preservation conventions would change for a filter procedure, or considering how seldom the procedure is called any significant performance advantage in not preserving the registers. And for what it's worth, Matt Pietrek refers to an exception handler as a "user-defined callback function" here.
eschew obfuscation

Biterider

Hi Michael
Right, I found it
QuoteMore specifically, when a thread faults, the operating system calls a user-defined callback function. This callback function can do pretty much whatever it wants.
Thanks!  :U

There is another issue a friend of mine (Obivan) told me yesterday. The main goal for this self expanding buffer is safety. What happens when we reach the end of our buffer, we commit the last guard page and the following page was committed before and contains data. We would write beyond the end of the buffer, corrupting other things.
A solution for this problem is to keep the last buffer page as a guard page and raise an exception when this is hit.

I'll modify the code to introduce this last change.

Regards,

Biterider

Biterider

Hi
I updated the code again with some improvements over the old one.

Biterider