{"id":41023,"date":"2004-01-16T08:07:00","date_gmt":"2004-01-16T08:07:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2004\/01\/16\/how-can-a-program-survive-a-corrupted-stack\/"},"modified":"2004-01-16T08:07:00","modified_gmt":"2004-01-16T08:07:00","slug":"how-can-a-program-survive-a-corrupted-stack","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20040116-00\/?p=41023","title":{"rendered":"How can a program survive a corrupted stack?"},"content":{"rendered":"<p>Continuing from\n<a HREF=\"\/oldnewthing\/archive\/2004\/01\/15\/58973.aspx\">\nyesterday<\/a>:<\/p>\n<p>\nThe x86 architecture traditionally uses the EBP register to\nestablish a stack frame.  A typical function prologue goes like this:\n<\/p>\n<pre>\n  push ebp       ; save old ebp\n  mov  ebp, esp  ; establish new ebp\n  sub  esp, nn*4 ; local variables\n  push ebx       ; must be preserved for caller\n  push esi       ; must be preserved for caller\n  push edi       ; must be preserved for caller\n<\/pre>\n<p>This establishes a stack frame that looks like this,\nfor, say, a __stdcall function that takes two parameters.<\/p>\n<table BORDER=\"0\">\n<col ALIGN=\"center\">\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow;border-top: none\">.. rest of stack ..<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">param2<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">param1<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">return address<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">saved EBP<\/td>\n<td>&lt;- EBP<\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">local1<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">local2<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">&#8230;<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">local-nn<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">saved EBX<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">saved ESI<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">saved EDI<\/td>\n<td>&lt;- ESP<\/td>\n<\/tr>\n<\/table>\n<p>\nParameters can be accessed with positive offsets from EBP;\nfor example, param1 is [ebp+8].  Local variables have negative\noffsets from EBP; for example, local2 is [ebp-8].\n<\/p>\n<p>\nNow suppose that a calling convention or function declaration\nmismatch occurs and extra garbage is left on the stack:<\/p>\n<table BORDER=\"0\">\n<col ALIGN=\"center\">\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow;border-top: none\">.. rest of stack ..<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">param2<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">param1<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">return address<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">saved EBP<\/td>\n<td>&lt;- EBP<\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">local1<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">local2<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">&#8230;<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">local-nn<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">saved EBX<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">saved ESI<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">saved EDI<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">garbage<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">garbage<\/td>\n<td>&lt;- ESP<\/td>\n<\/tr>\n<\/table>\n<p>\nThe function doesn&#8217;t really feel any damage yet. The parameters\nare still accessible at the same positive offsets and the local\nvariables are still accessible at the same negative offsets.\n<\/p>\n<p>\nThe real damage doesn&#8217;t occur until it&#8217;s time to clean up.\nLook at the function epilogue:<\/p>\n<pre>\n  pop  edi       ; restore for caller\n  pop  esi       ; restore for caller\n  pop  ebx       ; restore for caller\n  mov  esp, ebp  ; discard locals\n  pop  ebp       ; restore for caller\n  retd 8         ; return and clean stack\n<\/pre>\n<p>\nIn a normal stack, the three &#8220;pop&#8221; instructions match with the\nactual values on the stack and nobody gets hurt. But on the\ngarbage stack, the &#8220;pop edi&#8221; actually loads garbage into the EDI\nregister, as does the &#8220;pop esi&#8221;.  And the &#8220;pop ebx&#8221; &#8211; which thinks\nit&#8217;s restoring the original value of EBX &#8211; actually loads the\noriginal value of the EDI register into EBX.  But then the\n&#8220;mov esp, ebp&#8221; instruction fixes the stack back up, so the\n&#8220;pop ebp&#8221; and &#8220;retd&#8221; are executed with a repaired stack.\n<\/p>\n<p>\nWhat happened here?  Things sort of got put back on their feet.\nWell, except that the ESI, EDI, and EBX registers got corrupted.\nIf you&#8217;re lucky, the values in ESI, EDI and EBX weren&#8217;t important\nand could have survived corruption. Or all that was important was\nwhether the value was zero or not, and you were lucky and replaced\none nonzero value with another. For whatever reason, the corruption\nof those three registers is not immediately apparent, and you end up\nnever realizing what you did wrong.\n<\/p>\n<p>\nMaybe the corruption has a subtle effect (say, you changed a value\nfrom zero to nonzero, causing the caller to go down the wrong codepath),\nbut it&#8217;s subtle enough that you don&#8217;t notice, so you ship it,\nthrow a party, and start the next project.\n<\/p>\n<p>\nBut then a new compiler comes along, say one that does FPO optimization.\n<\/p>\n<p>\nFPO stands for &#8220;frame pointer omission&#8221;; the function dispenses with the\nEBP register as a frame register and instead just uses it like any other\nregister.  On the x86,\n<a HREF=\"\/oldnewthing\/archive\/2004\/01\/05\/47685.aspx\">\nwhich has comparatively few registers<\/a>, an extra\narithmetic register goes a long way.\n<\/p>\n<p>\nWith FPO, the function prologue goes like this:<\/p>\n<pre>\n  sub  esp, nn*4 ; local variables\n  push ebp       ; must be preserved for caller\n  push ebx       ; must be preserved for caller\n  push esi       ; must be preserved for caller\n  push edi       ; must be preserved for caller\n<\/pre>\n<p>The resulting stack frame looks like this:<\/p>\n<table BORDER=\"0\">\n<col ALIGN=\"center\">\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow;border-top: none\">.. rest of stack ..<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">param2<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">param1<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">return address<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">local1<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">local2<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">&#8230;<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">local-nn<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">saved EBP<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">saved EBX<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">saved ESI<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">saved EDI<\/td>\n<td>&lt;- ESP<\/td>\n<\/tr>\n<\/table>\n<p>\nEverything is now accessed relative to the ESP register.\nFor example, local-nn is [esp+0x10].\n<\/p>\n<p>\nUnder these conditions, garbage on the stack is much more fatal.\nThe function epilogue goes like this:<\/p>\n<pre>\n  pop  edi       ; restore for caller\n  pop  esi       ; restore for caller\n  pop  ebx       ; restore for caller\n  pop  ebp       ; restore for caller\n  add  esp, nn*4 ; discard locals\n  retd 8         ; return and clean stack\n<\/pre>\n<p>\nIf there is garbage on the stack, the four &#8220;pop&#8221; instructions will\nrestore the wrong values, as before, but this time, the cleanup of\nlocal variables won&#8217;t fix anything.\nThe &#8220;add esp, nn*4&#8221; will adjust the stack by what the function believes\nto be the correct amount, but since there was garbage on the stack,\nthe stack pointer will be off.<\/p>\n<table BORDER=\"0\">\n<col ALIGN=\"center\">\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow;border-top: none\">.. rest of stack ..<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">param2<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">param1<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">return address<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">local1<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">local2<\/td>\n<td>&lt;- ESP (oops)<\/td>\n<\/tr>\n<\/table>\n<p>\nThe &#8220;retd 8&#8221; instruction now attempts to return to the caller,\nbut instead it returns to whatever is in local2, which is probably\nnot valid code.\n<\/p>\n<p>\nSo this is an example of where optimizing your code reveals\nother people&#8217;s bugs.\n<\/p>\n<p>\nMonday, I&#8217;ll give a much more subtle example of something\nthat can go wrong if you use the wrong function signature for a\ncallback.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Continuing from yesterday: The x86 architecture traditionally uses the EBP register to establish a stack frame. A typical function prologue goes like this: push ebp ; save old ebp mov ebp, esp ; establish new ebp sub esp, nn*4 ; local variables push ebx ; must be preserved for caller push esi ; must be [&hellip;]<\/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-41023","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Continuing from yesterday: The x86 architecture traditionally uses the EBP register to establish a stack frame. A typical function prologue goes like this: push ebp ; save old ebp mov ebp, esp ; establish new ebp sub esp, nn*4 ; local variables push ebx ; must be preserved for caller push esi ; must be [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/41023","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=41023"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/41023\/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=41023"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=41023"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=41023"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}