{"id":100685,"date":"2019-01-11T07:00:00","date_gmt":"2019-01-11T22:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=100685"},"modified":"2025-07-03T12:19:11","modified_gmt":"2025-07-03T19:19:11","slug":"20190111-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190111-00\/?p=100685","title":{"rendered":"Why do we even need to define a red zone? Can&#8217;t I just use my stack for anything?"},"content":{"rendered":"<p>On Windows, the stack grows downward from high addresses to low. This is sometimes architecturally defined, and sometimes it is merely convention. The value pointed-to by the stack pointer register is the value at the top of the stack, and values deeper on the stack reside at higher addresses. But what&#8217;s up with the data at addresses <i>less than<\/i> the stack pointer?<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td>&nbsp;<\/td>\n<td align=\"center\">\u22ee<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td valign=\"bottom\">top of stack<\/td>\n<td style=\"border: solid 1px currentcolor;\" align=\"center\" valign=\"bottom\">valid stack data<br \/>\nvalid stack data<br \/>\nvalid stack data<\/td>\n<td style=\"border-bottom: dotted 1px currentcolor;\" valign=\"bottom\"><span style=\"display: inline-block; width: 1.5em;\">\u2190<\/span>stack pointer<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" align=\"center\" valign=\"bottom\">below the stack<br \/>\nbelow the stack<br \/>\nbelow the stack<\/td>\n<td style=\"padding-left: 1.5em;\">land of mystery<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td align=\"center\">\u22ee<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The platform conventions for some but not all architectures define a <i>red zone<\/i>, which is a region of the stack below the stack pointer that is still valid for applications to use.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td>&nbsp;<\/td>\n<td align=\"center\">\u22ee<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td valign=\"bottom\">top of stack<\/td>\n<td style=\"border: solid 1px currentcolor;\" align=\"center\" valign=\"bottom\">valid stack data<br \/>\nvalid stack data<br \/>\nvalid stack data<\/td>\n<td style=\"border-bottom: dotted 1px currentcolor;\" valign=\"bottom\"><span style=\"display: inline-block; width: 1.5em;\">\u2190<\/span>stack pointer<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" align=\"center\" valign=\"bottom\">still valid<br \/>\nstill valid<\/td>\n<td style=\"border-bottom: dotted 1px currentcolor; padding-left: 1.5em;\">red zone<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" align=\"center\" valign=\"bottom\">here<br \/>\nbe<br \/>\ndragons<\/td>\n<td style=\"padding-left: 1.5em;\">off limits<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td align=\"center\">\u22ee<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>For Windows, the size of the red zone varies by architecture, and is often zero.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Architecture<\/th>\n<th>Red zone size<\/th>\n<\/tr>\n<tr>\n<td>x86<\/td>\n<td align=\"right\">0 bytes<\/td>\n<\/tr>\n<tr>\n<td>x64<\/td>\n<td align=\"right\">0 bytes<\/td>\n<\/tr>\n<tr>\n<td>Itanium<\/td>\n<td align=\"right\">16 bytes*<\/td>\n<\/tr>\n<tr>\n<td>Alpha AXP<\/td>\n<td align=\"right\">0 bytes<\/td>\n<\/tr>\n<tr>\n<td>MIPS32<\/td>\n<td align=\"right\">0 bytes<\/td>\n<\/tr>\n<tr>\n<td>PowerPC<\/td>\n<td align=\"right\">232 bytes<\/td>\n<\/tr>\n<tr>\n<td>ARM32<\/td>\n<td align=\"right\">8 bytes<\/td>\n<\/tr>\n<tr>\n<td>ARM64<\/td>\n<td align=\"right\">16 bytes<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>* The Itanium is unusual in that the red zone is placed <a href=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20040113-00\/?p=41073\"> <i>above<\/i> the stack pointer<\/a>, rather than below it.<\/p>\n<p>In the case of the PowerPC, the red zone is <a href=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20180817-00\/?p=99515\"> a side effect of the calling convention<\/a>.<\/p>\n<p>Any memory below the stack beyond the red zone is considered volatile and may be modified by the operating system at any time.<\/p>\n<p>But seriously, why does the operating system even care what I do with my stack? I mean, it&#8217;s <i>my<\/i> stack! The operating system doesn&#8217;t tell me what to do with memory I allocate via <code>Virtual\u00adAlloc<\/code>. What makes the stack any different from any other memory?<\/p>\n<p><a href=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20040113-00\/?p=41073#comment-135993\"> Consider the following sequence on x86<\/a>:<\/p>\n<pre>    MOV     [esp-4], eax       ; save eax below the stack pointer\r\n    MOV     ecx, [esp-4]       ; read it into ecx\r\n    CMP     ecx, eax           ; are they the same?\r\n    JNZ     panic              ; N: something crazy happened\u00b9\r\n<\/pre>\n<p>Can the jump be taken?<\/p>\n<p>Since there is no red zone on x86, the memory at negative offsets relative to the stack pointer may be overwritten at any time. Therefore, the above sequence is permitted to jump to <code>panic<\/code>.<\/p>\n<p>A debugger may use the memory beyond the red zone as a convenient place to store some data. For example, if you use <a href=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20070427-00\/?p=27083\"> the <code>.call<\/code> command<\/a>, the debugger will perform the nested call on the same stack, and likely use some of that stack space to preserve registers so that they can be restored after the <code>.call<\/code>ed function returns. Any data stored beyond the red zone will therefore be destroyed.<\/p>\n<p>Even during normal operation, it&#8217;s possible for the operating system to overwrite data beyond the red zone at any time. Here&#8217;s one scenario where it can happen:<\/p>\n<p>Suppose your thread gets pre-empted immediately after you store the data beyond the red zone. While your thread is waiting for a chance to resume execution, the memory manager pages out the code. Eventually, your thread resumes execution, and the memory manager tries to page it back in. Oh no, there&#8217;s an I\/O error during the page-in! The operating system pushes an exception frame onto the stack for the <code>STATUS_<\/code><code>IN_<\/code><code>PAGE_<\/code><code>ERROR<\/code>, clobbering the data you had been hiding beyond the red zone.<\/p>\n<p>The operating system then dispatches the exception. It goes to a vectored exception handler, which some other part of your program had installed specifically to handle this possibility, because your program might be run directly off a CD-ROM or unreliable network. The program displays a prompt to ask the user to reinsert the CD-ROM and offers an opportunity to retry. If the user says to retry, then the vectored exception handler returns <code>EXCEPTION_<\/code><code>CONTINUE_<\/code><code>EXECUTION<\/code>, and the operating system will restart the failed instruction.<\/p>\n<p>This time, the restart succeeds because the CD-ROM is present and the code can be paged back in. The next instruction runs, the one that loads the beyond-the-red-zone value into the <var>ecx<\/var> register, but it doesn&#8217;t load the value stored by the previous instruction because the <code>STATUS_<\/code><code>IN_<\/code><code>PAGE_<\/code><code>ERROR<\/code> exception overwrote it. The comparison fails, and we jump to the label <code>panic<\/code>.<\/p>\n<p>If you want to store data on the stack, push it properly: Decrement the stack pointer first, and then store the value onto the valid portion of the stack. Don&#8217;t hide it beyond the red zone. That memory is volatile and may vanish out from under you.<\/p>\n<p>\u00b9 The coding convention for assembly language\u00b2 says that comments for jump instructions should describe the result if the jump is taken. In the example above, the <code>CMP<\/code> instruction asks the question, &#8220;Are they the same?&#8221;, and the <code>JNZ<\/code> instruction jumps if they are not equal. The comment therefore begins with &#8220;N:&#8221; indicating that the jump is taken if the answer to the previous question is <i>No<\/i>, and the rest of the comment describe what it means when the jump is taken.<\/p>\n<p>\u00b2 Yes, we have a coding convention for assembly language.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I mean, it&#8217;s my stack, isn&#8217;t it?<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-100685","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>I mean, it&#8217;s my stack, isn&#8217;t it?<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/100685","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=100685"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/100685\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=100685"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=100685"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=100685"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}