{"id":25063,"date":"2007-09-19T10:00:00","date_gmt":"2007-09-19T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2007\/09\/19\/what-happens-if-you-pass-a-source-length-greater-than-the-actual-string-length\/"},"modified":"2007-09-19T10:00:00","modified_gmt":"2007-09-19T10:00:00","slug":"what-happens-if-you-pass-a-source-length-greater-than-the-actual-string-length","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20070919-00\/?p=25063","title":{"rendered":"What happens if you pass a source length greater than the actual string length?"},"content":{"rendered":"<p>\nMany functions accept a source string that consists of both a pointer\nand a length.\nAnd if you pass a length that is greater than the length of the string,\nthe result depends on the function itself.\n<\/p>\n<p>\nSome of those functions, when given a string and a length, will stop\neither when the length is exhausted or a null terminator is reached\n<i>whichever comes first<\/i>.\nFor example, if you pass a <code>cchSrc<\/code> greater than the\nlength of the string to the\n<code>StringCchCopyN<\/code> function, it will stop at the null\nterminator.\n<\/p>\n<p>\nOn the other hand, many other functions (particularly those in the\nNLS family)\n<i>will cheerfully operate past a null character if you\nask them to<\/i>.\nThe idea here is that since you passed an explicit size,\nyou&#8217;re consciously operating on a buffer which might\ncontain embedded null characters.\nBecause, after all, if you passed an explicit source size,\nyou really meant it, right?\n(Maybe you&#8217;re operating on a <code>BSTR<\/code>, which supports\nembedded nulls; to get the size of a <code>BSTR<\/code> you must\nuse a function like <code>SysStringLen<\/code>.)\nFor example, if you call\n<code>CharUpperBuff(psz, 20)<\/code>, then the function\nreally will convert to uppercase 20 <code>TCHAR<\/code>s\nstarting at <code>psz<\/code>.\nIf there happens to be a null character at <code>psz[10]<\/code>,\nthe function will convert the null to uppercase and continue\nconverting the next ten <code>TCHAR<\/code>s as well.\n<\/p>\n<p>\nI&#8217;ve seen programs crash because they thought that functions\nlike <code>CharUpperBuff<\/code> and\n<code>MultiByteToWideChar<\/code>\nstopped when they encountered a null.\nFor example, somebody might write\n<\/p>\n<pre>\n<i>\/\/ buggy code - see discussion\nvoid someFunction(char *pszFile)\n{\n CharUpperBuff(pszFile, MAX_PATH);\n ... do something with pszFile ...\n}\nvoid Caller()\n{\n char buffer[80];\n sprintf(buffer, \"file%d\", get_fileNumber());\n someFunction(buffer);\n}\n<\/i><\/pre>\n<p>\nThe intent here was for <code>someFunction<\/code>\nto convert the string to uppercase\nbefore operating on it, up to <code>MAX_PATH<\/code> characters&#8217; worth,\nbut instead what happens is that the <code>MAX_PATH<\/code> characters\nstarting at <code>pszFile<\/code> are converted, even though the\nactual buffer is shorter!\nAs a result, <code>MAX_PATH<\/code> &#x2212; 80 = 220\ncharacters beyond the end of <code>buffer<\/code> are also converted.\nAnd since that&#8217;s a stack buffer,\nthose bytes are likely to include the return address.\nResult: Crash-o-rama.\nThings get even more interesting if the short buffer had been allocated\non the heap instead.\nThen instead of corrupting your return address (which you would\nprobably notice as soon as the function returned),\nyou corrupt the heap,\nwhich typically doesn&#8217;t manifest itself in a crash until long after\nthe offending function has left the scene of the crime.\n<\/p>\n<p>\nCritique, then, this replacement function:\n<\/p>\n<pre>\n<i>\/\/  buggy code - do not use\nint invariant_strnicmp(char *s1, char *s2, size_t n)\n{\n \/\/ [Update: 9:30am - typo fixed]\n return CompareStringA(LOCALE_INVARIANT, NORM_IGNORECASE,\n                       s1, n, s2, n) - CSTR_EQUAL;\n}<\/i>\n<\/pre>\n<p>\n(<a HREF=\"http:\/\/blogs.msdn.com\/michkap\/archive\/2006\/07\/09\/658454.aspx\">Michael Kaplan has one answer<\/a>\ndifferent from the one I was looking for.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Many functions accept a source string that consists of both a pointer and a length. And if you pass a length that is greater than the length of the string, the result depends on the function itself. Some of those functions, when given a string and a length, will stop either when the length is [&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-25063","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Many functions accept a source string that consists of both a pointer and a length. And if you pass a length that is greater than the length of the string, the result depends on the function itself. Some of those functions, when given a string and a length, will stop either when the length is [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/25063","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=25063"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/25063\/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=25063"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=25063"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=25063"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}