{"id":24683,"date":"2007-10-26T10:00:00","date_gmt":"2007-10-26T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2007\/10\/26\/if-you-pass-enough-random-numbers-eventually-one-of-them-will-look-valid\/"},"modified":"2007-10-26T10:00:00","modified_gmt":"2007-10-26T10:00:00","slug":"if-you-pass-enough-random-numbers-eventually-one-of-them-will-look-valid","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20071026-00\/?p=24683","title":{"rendered":"If you pass enough random numbers, eventually one of them will look valid"},"content":{"rendered":"<p>\nOne customer traced a problem they were having to the way they\nwere calling a function similar in spirit to this one:\n<\/p>\n<pre>\nHGLOBAL CopyClipboardData(UINT cf)\n{\n HGLOBAL hglob = NULL;\n HANDLE h = GetClipboardData(cf);\n if (h) {\n  void *p = GlobalLock(h);\n  if (p) {\n   SIZE_T size = GlobalSize(h);\n   hglob = GlobalAlloc(GMEM_FIXED, size);\n   if (hglob) {\n    CopyMemory(hglob, p, size);\n   }\n   GlobalUnlock(h);\n  }\n }\n return hglob;\n}\n<\/pre>\n<p>\nThis function takes a clipboard format and\nlooks for it on the clipboard.\nIf found, it returns a copy of the data.\n<\/p>\n<p>\nLooks great, huh?\n<\/p>\n<p>\nThe problem is that the customer would sometimes call the function as\n<code>CopyClipboardData(CF_BITMAP)<\/code>.\nThe <code>CF_BITMAP<\/code> clipboard format stores its contents in\nthe form of a <code>HBITMAP<\/code>,\nnot an <code>HGLOBAL<\/code>.\n<\/p>\n<p>\nThe question from the customer:\n<\/p>\n<blockquote CLASS=\"q\"><p>\nThis code was written in 2002, and we are wondering why it works\n&#8220;most&#8221; of the time and crashes sporadically.\nWe expected that the call to <code>GlobalLock<\/code> would fail\nwith an invalid parameter error, but sometimes it succeeds,\nand then when we call\n<code>GlobalSize<\/code> we crash.\nWhy does it crash sometimes?\n<\/p><\/blockquote>\n<p>\nYou already know the answer to this.\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2004\/11\/09\/254441.aspx\">\n<code>GlobalAlloc<\/code> works closely with\n<code>GlobalLock<\/code> so that <code>GlobalLock<\/code> can be fast<\/a>.\nThe bitmap handle returned by <code>GetClipboardData<\/code>\nusually fails the quick tests performed by <code>GlobalLock<\/code>\nto see whether the parameter is a fixed memory block,\nin which case the <code>GlobalLock<\/code> must go down its slow code path,\nand it is in this slow code path that the function recognizes that the\nthe handle is downright invalid.\n<\/p>\n<p>\nBut once in a rare while, the bitmap handle happens to smell just\nenough like a fixed global handle that it passes the tests,\nand <code>GlobalLock<\/code> uses its highly optimized code path\nwhere it says,\n&#8220;Okay, this is one of those fixed global handles that\n<code>GlobalAlloc<\/code> created for me.\nI can just return the pointer back.&#8221;\nResult:\nThe call to <code>GlobalLock<\/code> succeeds\n(garbage in, garbage out),\nand then you crash in the <code>GlobalSize<\/code> function\nwhere it tries to use the <code>HBITMAP<\/code> as if it were\na <code>HGLOBAL<\/code> and access some of the memory block metadata,\nwhich isn&#8217;t there since the handle isn&#8217;t valid after all.\n<\/p>\n<p>\nThe bitmap handle is basically a random number from the global\nheap&#8217;s point of view, since it&#8217;s just some number that some other\ncomponent made up.\nIt&#8217;s not a global handle.\nIf you generate enough random numbers,\neventually one of them will look like a valid parameter.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One customer traced a problem they were having to the way they were calling a function similar in spirit to this one: HGLOBAL CopyClipboardData(UINT cf) { HGLOBAL hglob = NULL; HANDLE h = GetClipboardData(cf); if (h) { void *p = GlobalLock(h); if (p) { SIZE_T size = GlobalSize(h); hglob = GlobalAlloc(GMEM_FIXED, size); if (hglob) { [&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-24683","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>One customer traced a problem they were having to the way they were calling a function similar in spirit to this one: HGLOBAL CopyClipboardData(UINT cf) { HGLOBAL hglob = NULL; HANDLE h = GetClipboardData(cf); if (h) { void *p = GlobalLock(h); if (p) { SIZE_T size = GlobalSize(h); hglob = GlobalAlloc(GMEM_FIXED, size); if (hglob) { [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/24683","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=24683"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/24683\/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=24683"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=24683"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=24683"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}