{"id":16283,"date":"2009-10-23T07:00:00","date_gmt":"2009-10-23T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2009\/10\/23\/if-you-have-to-cast-you-cant-afford-it\/"},"modified":"2009-10-23T07:00:00","modified_gmt":"2009-10-23T07:00:00","slug":"if-you-have-to-cast-you-cant-afford-it","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20091023-00\/?p=16283","title":{"rendered":"If you have to cast, you can&#039;t afford it"},"content":{"rendered":"<p>\nA customer reported a crash inside a function we&#8217;ll call\n<code>XyzConnect<\/code>:\n<\/p>\n<pre>\nDWORD XyzConnect(\n    __in DWORD ConnectionType,\n    __in PCWSTR Server,\n    __in PCWSTR Target,\n    __out void **Handle);\n...\n\/\/ HACK - Create a dummy structure to pass to the XyzConnect\n\/\/ function to avoid AV within the function.\nint dummy = 0;\nif ( NO_ERROR != ( XyzConnect( 0, L\"\", L\"\", (PVOID*)&amp;dummy ) )\n{\n    TRACE( L\"XyzConnect failed.\" );\n    return FALSE;\n}\n...\n<\/pre>\n<p>\nThe title of today&#8217;s entry gives the answer away.\n(The title is also an exaggeration, but it&#8217;s a pun on\nthe saying\n<a HREF=\"http:\/\/www.phrases.org.uk\/bulletin_board\/53\/messages\/626.html\">\n<i>If you have to ask, you can&#8217;t afford it<\/i><\/a>.)\n<\/p>\n<p>\nThe last parameter to the <code>XyzConnect<\/code> function is\ndeclared as a <code>void**<\/code>: A pointer to a generic pointer.\nNote that it is not itself a generic pointer, however.\nA generic pointer can point to anything, possibly unaligned.\nBut this is an aligned pointer to a generic pointer.\nTherefore, the memory for the generic pointer must be aligned\nin a manner appropriate to its type.\n<\/p>\n<p>\nBut this caller didn&#8217;t pass a pointer to a pointer;\nthe caller passed a pointer to an <code>int<\/code>,\nand an <code>int<\/code> has different alignment requirements\nfrom a pointer on 64-bit systems.\n(You might conclude that this decision was the stupidest decision\non the face of the planet, but that&#8217;s a different argument for\na different time. For example, I can think of decisions far stupider.)\n<\/p>\n<p>\nWhen the <code>XyzConnect<\/code> function tries to dereference this\npurported <code>void **<\/code> pointer,\nit encounters an alignment fault, because it does not in fact\npoint to a <code>void *<\/code> as the type claims,\nbut rather points to a <code>DWORD<\/code>.\nA <code>DWORD<\/code> requires only 32-bit alignment,\nso you have a 50% chance that the <code>DWORD*<\/code>\nis not suitably aligned to be a <code>void*<\/code>.\n<\/p>\n<p>\nMind you, you also have a 100% chance of a buffer overflow,\nbecause a <code>DWORD<\/code> is only four bytes,\nwhereas a <code>void*<\/code> is eight bytes.\nThe function is going to write eight bytes\ninto your four-byte buffer.\n<\/p>\n<p>\nWhen this question was posed, one person suggested changing\nthe <code>DWORD<\/code> to a <code>__int64<\/code>,\nsince the <code>__int64<\/code> is an 8-byte value, which is\nbig enough to hold a pointer on both 32-bit and 64-bit Windows.\nThen again, it&#8217;s overkill on 32-bit systems, since you allocated\neight bytes when you only needed four.\nAnother suggestion was to use <code>DWORD_PTR<\/code>,\nsince that type changes in size to match\nthe size of a <code>void*<\/code>.\n<\/p>\n<p>\nWell, yeah, but here&#8217;s another type that matches the size\nof a <code>void*<\/code>: It&#8217;s called <code>void*<\/code>.\n<\/p>\n<p>\nJust declare <code>void *dummy<\/code> and get rid of the cast.\nAnd get rid of the comment while you&#8217;re at it.\nIf you do it right, you don&#8217;t need the cast or the hack.\n<\/p>\n<pre>\nvoid *handle = 0;\nif ( NO_ERROR != ( XyzConnect( 0, L\"\", L\"\", &amp;handle ) )\n{\n    TRACE( L\"XyzConnect failed.\" );\n    return FALSE;\n}\n<\/pre>\n<p>\nA large number of porting problems can be traced to incorrect casts.\nThe original author probably\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2004\/01\/15\/58973.aspx\">\ninserted the cast to &#8220;shut up the compiler&#8221;<\/a>\nbut the compiler was trying to tell you something.\n<\/p>\n<p>\nAny time you see a function cast or see a cast to\/from something\nother than <code>void*<\/code> or <code>BYTE*<\/code>,\nthen you should be suspicious,\nbecause there&#8217;s a chance somebody is simply trying to shut up\nthe compiler.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A customer reported a crash inside a function we&#8217;ll call XyzConnect: DWORD XyzConnect( __in DWORD ConnectionType, __in PCWSTR Server, __in PCWSTR Target, __out void **Handle); &#8230; \/\/ HACK &#8211; Create a dummy structure to pass to the XyzConnect \/\/ function to avoid AV within the function. int dummy = 0; if ( NO_ERROR != ( [&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-16283","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>A customer reported a crash inside a function we&#8217;ll call XyzConnect: DWORD XyzConnect( __in DWORD ConnectionType, __in PCWSTR Server, __in PCWSTR Target, __out void **Handle); &#8230; \/\/ HACK &#8211; Create a dummy structure to pass to the XyzConnect \/\/ function to avoid AV within the function. int dummy = 0; if ( NO_ERROR != ( [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/16283","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=16283"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/16283\/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=16283"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=16283"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=16283"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}