{"id":93975,"date":"2016-07-28T07:00:00","date_gmt":"2016-07-28T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=93975"},"modified":"2019-03-13T11:04:48","modified_gmt":"2019-03-13T18:04:48","slug":"20160728-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20160728-00\/?p=93975","title":{"rendered":"How can I check whether a parameter is a pointer to a stack variable?"},"content":{"rendered":"<p>A customer traced a bug in their program back to the fact that somebody passed a stack buffer to a function that operates asynchronously. Something like this: <\/p>\n<pre>\n\/\/ This function sends the buffer to the destination\n\/\/ asynchronously. When the send completes, the completion\n\/\/ handler is invoked.\nHRESULT SendDataAsync(void *buffer, size_t bufferSize,\n                      ITransferCompletion* completion);\n\nclass ColorSender : public ITransferCompletion\n{\n...\n};\n\n<i>\/\/ Code in italics is wrong\nHRESULT ColorSender::SendColor()\n{\n  COLORREF color = GetColorToSend();\n  return SendDataAsync(&amp;color, sizeof(color), this);\n}<\/i>\n<\/pre>\n<p>This bug led to the destination sometimes receiving corrupted data because it was a race between the stack variable being reused for something else and the data transport code copying the buffer into the transport channel. In this particular case, the customer fixed the problem by making the <code>color<\/code> local variable a member of the <code>Color&shy;Sender<\/code> class, because the <code>Color&shy;Sender<\/code> object itself must remain valid for the lifetime of the transfer seeing as it is the completion handler. (We&#8217;re using the principle that <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20070423-00\/?p=27163\">code is mostly correct<\/a>.) <\/p>\n<p>The customer wanted to add some debugging code to the <code>Send&shy;Data&shy;Async<\/code> function so that it can assert that the buffer is not on the stack. The customer understands that this may be overly restrictive, and would not be appropriate for a function with a broad audience, but this function is used only within their application, so being extra-restrictive is probably okay.&sup1; <\/p>\n<p>On Windows&nbsp;8 and higher, the customer can use the <code>Get&shy;Current&shy;Thread&shy;Stack&shy;Limits<\/code> function to get the bounds of the current thread&#8217;s stack and use that to verify that the buffer pointer is not in that range. (Since this is just for debugging purposes, they can skip the test if running on older versions of Windows, and hope that their testing on Windows&nbsp;8 will catch the problem.) <\/p>\n<p>&sup1; If it turns out that the check is too restrictive, they could create two functions. The first is called <code>Send&shy;Possibly&shy;Stack&shy;Data&shy;Async<\/code> that does no validation, and the second is <code>Send&shy;Data&shy;Async<\/code> which does the initial validation that the buffer is not on the stack, and then calls <code>Send&shy;Possibly&shy;Stack&shy;Data&shy;Async<\/code>. Most callers use <code>Send&shy;Data&shy;Async<\/code>, but if you&#8217;re in a special case where you are sending stack data and you know that you won&#8217;t return from the function until the completion occurs, then you can use <code>Send&shy;Possibly&shy;Stack&shy;Data&shy;Async<\/code>. The team could have a rule that equires all uses of <code>Send&shy;Possibly&shy;Stack&shy;Data&shy;Async<\/code> to undergo a special review. <\/p>\n<p><b>Update<\/b>: See <a HREF=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/\">follow-up discussion<\/a>. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Check it against the thread limits.<\/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-93975","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Check it against the thread limits.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/93975","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=93975"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/93975\/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=93975"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=93975"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=93975"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}