{"id":8353,"date":"2012-02-08T07:00:00","date_gmt":"2012-02-08T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2012\/02\/08\/the-path-searching-algorithm-is-not-a-backtracking-algorithm\/"},"modified":"2012-02-08T07:00:00","modified_gmt":"2012-02-08T07:00:00","slug":"the-path-searching-algorithm-is-not-a-backtracking-algorithm","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20120208-00\/?p=8353","title":{"rendered":"The path-searching algorithm is not a backtracking algorithm"},"content":{"rendered":"<p>\nSuppose your PATH environment variable looks like this:\n<\/p>\n<pre>\nC:\\dir1;\\\\server\\share;C:\\dir2\n<\/pre>\n<p>\nSuppose that you call <code>LoadLibrary(\"foo.dll\")<\/code>\nintending to load the library at\n<code>C:\\dir2\\foo.dll<\/code>.\nIf the network server is down, the <code>LoadLibrary<\/code> call\nwill fail.\nWhy doesn&#8217;t it just skip the bad directory in the PATH and\ncontinue searching?\n<\/p>\n<p>\nSuppose the <code>LoadLibrary<\/code> function skipped the bad\nnetwork directory and kept searching.\nSuppose that the code which called\n<code>LoadLibrary(\"foo.dll\")<\/code> was really after the file\n<code>\\\\server\\share\\foo.dll<\/code>.\nBy taking the server down, you have tricked the <code>LoadLibrary<\/code>\nfunction into loading <code>c:\\dir2\\foo.dll<\/code> instead.\n(And maybe that was your DLL planting attack:\nIf you can convince the system to reject all the versions on the\n<code>PATH<\/code> by some means, you can then get <code>Load&shy;Library<\/code>\nto look in the current directory, which is where you put your attack\nversion of <code>foo.dll<\/code>.)\n<\/p>\n<p>\nThis can manifest itself in very strange ways if the two\ncopies of <code>foo.dll<\/code> are not identical,\nbecause the program is now running with a version of <code>foo.dll<\/code>\nit was not designed to use.\n&#8220;My program works okay during the day, but it starts returning\nbad data when I try to run between midnight and 3am.&#8221;\nReason:\nThe server is taken down for maintenance every night,\nso the program ends up running with the version in\n<code>c:\\dir2\\foo.dll<\/code>, which happens to be an incompatible\nversion of the file.\n<\/p>\n<p>\nWhen the <code>LoadLibrary<\/code> function\nis unable to contact <code>\\\\server\\share\\foo.dll<\/code>,\nit doesn&#8217;t know whether it&#8217;s in the\n&#8220;don&#8217;t worry, I wasn&#8217;t expecting the file to be there anyway&#8221;\ncase or in the\n&#8220;I was hoping to get that version of the file,\ndon&#8217;t substitute any bogus ones&#8221;\ncase.\nSo it plays it safe and assumes it&#8217;s in the\n&#8220;don&#8217;t substitute any bogus ones&#8221; and fails the call.\nThe program can then perform whatever recovery it deems appropriate\nwhen it cannot load its precious <code>foo.dll<\/code> file.\n<\/p>\n<p>\nNow consider the case where there is also\na <code>c:\\dir1\\foo.dll<\/code> file,\nbut it&#8217;s corrupted.\nIf you do a <code>LoadLibrary(\"foo.dll\")<\/code>,\nthe call will fail with the error\n<code>ERROR_BAD_EXE_FORMAT<\/code>\nbecause it found the <code>C:\\dir1\\foo.dll<\/code> file,\ndetermined that it was corrupted, and gave up.\nIt doesn&#8217;t continue searching the path for a better version.\nThe path-searching algorithm is not a backtracking algorithm.\nOnce a file is found, the algorithm commits to trying to load\nthat file (a &#8220;cut&#8221; in logic programming parlance),\nand if it fails, it doesn&#8217;t backtrack and return\nto a previous state to try something else.\n<\/p>\n<p>\n<b>Discussion<\/b>:\nWhy does the <code>LoadLibrary<\/code> search algorithm\ncontinue if an invalid directory or drive letter is put on the PATH?\n<\/p>\n<p>\n<b>Vaguely related chatter<\/b>:\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/ericlippert\/archive\/2010\/10\/04\/no-backtracking-part-one.aspx\">\nNo backtracking, Part One<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Suppose your PATH environment variable looks like this: C:\\dir1;\\\\server\\share;C:\\dir2 Suppose that you call LoadLibrary(&#8220;foo.dll&#8221;) intending to load the library at C:\\dir2\\foo.dll. If the network server is down, the LoadLibrary call will fail. Why doesn&#8217;t it just skip the bad directory in the PATH and continue searching? Suppose the LoadLibrary function skipped the bad network directory [&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-8353","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Suppose your PATH environment variable looks like this: C:\\dir1;\\\\server\\share;C:\\dir2 Suppose that you call LoadLibrary(&#8220;foo.dll&#8221;) intending to load the library at C:\\dir2\\foo.dll. If the network server is down, the LoadLibrary call will fail. Why doesn&#8217;t it just skip the bad directory in the PATH and continue searching? Suppose the LoadLibrary function skipped the bad network directory [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/8353","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=8353"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/8353\/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=8353"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=8353"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=8353"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}