On Tue, 29 Sep 2026 03:44:27 GMT, Dean Long <[email protected]> wrote:

> But since these pages would still be PAGE_NOACCESS, when we resume and 
> reexecute the trapped instruction, shouldn't we get a 
> EXCEPTION_ACCESS_VIOLATION as desired?

Unfortunately, although this expectation is perfectly reasonable, Windows 
doesn't seem to behave this way.  I wrote a couple of standalone C programs to 
validate this (and additional exploration continues).  The first program 
doesn't call `SetThreadStackGuarantee()` and it creates the following layout:


Page 5: reserved (i.e. not committed)
Page 4: reserved (i.e. not committed)
Page 3: PAGE_NOACCESS, committed (mimics yellow page)
Page 2: PAGE_NOACCESS, committed (mimics yellow page)
Page 1: PAGE_NOACCESS, committed (mimics yellow page)
Page 0: PAGE_NOACCESS, committed (mimics red page)


After accessing pages from the current stack page (return value of `_alloca(1)` 
aligned to page boundary) one page at a time, the first exception that is 
delivered is `EXCEPTION_STACK_OVERFLOW` for access to page 3.  What's even more 
interesting (and my apologies if this adds to our list of problems) is that 
when I probe the page status upon receiving `EXCEPTION_STACK_OVERFLOW`, I see 
the following:


Page 5: PAGE_READWRITE, committed
Page 4: PAGE_READWRITE, committed
Page 3: PAGE_READWRITE, committed (page whose access raised the stack overflow 
exception)


So Windows seems to open up the pages that we had marked `PAGE_NOACCESS`.  This 
isn't _really_ a problem because the `handle_recoverable_stack_overflow()` 
function (in this patch) calls 
`overflow_state->disable_stack_yellow_reserved_zone()`, which opens up the 
yellow pages anyway.  Now, if there were more than one red pages, we might run 
into problems since some of the red pages would be made writeable.  Yet another 
reason to avoid `EXCEPTION_STACK_OVERFLOW`, like David suggested.

In any case, Windows raises the stack overflow exception for access to page 3.  
If I continue probing more pages, the next exception 
(`EXCEPTION_ACCESS_VIOLATION`) is at page 0 because the `PAGE_NOACCESS` 
attribute was retained.

In the second program, I call `SetThreadStackGuarantee()` with different sizes 
like 1, 4096, 8192, 12288, and 16384 and for each case, I query the size to see 
what it set it to.  On my machine, I see:


requested=1 current=8192
requested=4096 current=8192
requested=8192 current=8192
requested=12288 current=12288
requested=16384 current=16384


So it looks like no matter what, there are at least two pages that become the 
guarantee.  This is generally fine, since the minimum red page count + minimum 
yellow page count exceeds two, but it does mean that we can't set just one page 
as the stack guarantee.

I am consulting some folks who work on Windows and inspecting some source code 
to better understand the conditions behind the delivery of these exceptions.  
I'll report back soon, but I appreciate y'all patience.  This is indeed 
convoluted, but I think I have a much better understanding now, and I hope you 
do as well.

-------------

PR Comment: https://git.openjdk.org/jdk/pull/32365#issuecomment-5885482325

Reply via email to