{"id":108009,"date":"2023-04-04T07:00:00","date_gmt":"2023-04-04T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=108009"},"modified":"2023-04-03T21:50:22","modified_gmt":"2023-04-04T04:50:22","slug":"20230404-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230404-00\/?p=108009","title":{"rendered":"What is the maximum size of a process environment block?"},"content":{"rendered":"<p>A customer was getting this error from their Web server:<\/p>\n<div style=\"border: solid 1px gray; padding: 1ex;\">\n<p style=\"font-size: 150%; color: red;\">Server Error in &#8216;\/&#8217; Application.<\/p>\n<hr \/>\n<p style=\"font-size: 130%; color: red;\">The environment block used to start a process cannot be longer than 65535 bytes. Your environment block is 70009 bytes long. Remove some environment variables and try again.<\/p>\n<p><b>Description<\/b>: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.<\/p>\n<p><b>Details<\/b>: System.InvalidOperationException: The environment block used to start a process cannot be longer than 65535 bytes. Your environment block is 70009 bytes long. Remove some environment variables and try again.<\/p>\n<\/div>\n<p>Windows imposes no hard-coded limit on the size of a Unicode environment block. Here&#8217;s a test program that shows that a 256KB environment block is no problem:<\/p>\n<pre>#include &lt;windows.h&gt;\r\n#include &lt;stdio.h&gt;\r\n\r\nint main()\r\n{\r\n    auto n = 65535*2;\r\n    auto p = new WCHAR[n];\r\n    for (int i = 0; i &lt; n; i++) {\r\n        p[i] = L'x';\r\n    }\r\n    p[1] = L'=';\r\n    p[n-1] = 0;\r\n    p[n-2] = 0;\r\n    STARTUPINFO si = { sizeof(si) };\r\n    PROCESS_INFORMATION pi;\r\n    wchar_t cmdline[] = L\"notepad.exe\";\r\n    printf(\"CreateProcess result is %d\\n\",\r\n        CreateProcessW(nullptr, cmdline, nullptr, nullptr, false,\r\n        CREATE_UNICODE_ENVIRONMENT, p, nullptr, &amp;si, &amp;pi));\r\n    return 0;\r\n}\r\n<\/pre>\n<p>This program creates an environment block that holds only one variable, named <code>x<\/code> whose value is 131,067 copies of the letter <code>x<\/code>. It&#8217;s not glamourous, and certainly not useful, but it does show that Windows is fine with it.<\/p>\n<p>This claimed 65535 byte limit must therefore be coming from somewhere else. After some investigation, the customer <a href=\"https:\/\/referencesource.microsoft.com\/#system\/services\/monitoring\/system\/diagnosticts\/Process.cs,2776\"> found it<\/a>:<\/p>\n<pre>namespace System.Diagnostics\r\n{\r\n    \/* ... *\/\r\n\r\n    internal static class EnvironmentBlock {\r\n        public static byte[] ToByteArray(StringDictionary sd, bool unicode) {\r\n            \/* ... *\/\r\n\r\n            if (unicode) {\r\n                envBlock = Encoding.Unicode.GetBytes(stringBuff.ToString());\r\n            } else {\r\n                envBlock = Encoding.Default.GetBytes(stringBuff.ToString());\r\n\r\n                <span style=\"color: #08f;\">if (envBlock.Length &gt; UInt16.MaxValue)\r\n                    throw new InvalidOperationException(\r\n                        SR.GetString(SR.EnvironmentBlockTooLong,\r\n                                     envBlock.Length));<\/span>\r\n            }\r\n\r\n            return envBlock;\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>The exception is coming from the C# base class library.<\/p>\n<p>Note that the check is inside the <code>else<\/code> branch, which means that somebody is passing an ANSI environment block to the CreateProcess function, and ANSI environment blocks are documented as supported up to 32,767 characters.<\/p>\n<p>Chasing back to the caller, the character set is selected <a href=\"https:\/\/referencesource.microsoft.com\/#system\/services\/monitoring\/system\/diagnosticts\/Process.cs,2040\"> here<\/a>:<\/p>\n<pre>    bool unicode = false;\r\n#if !FEATURE_PAL                    \r\n    if (ProcessManager.IsNt) {\r\n        creationFlags |= NativeMethods.CREATE_UNICODE_ENVIRONMENT;                \r\n        unicode = true;\r\n    }\r\n#endif \/\/ !FEATURE_PAL\r\n    \r\n    byte[] environmentBytes = EnvironmentBlock.ToByteArray(\r\n            startInfo.environmentVariables, unicode);\r\n<\/pre>\n<p>So it appears that if you are compiled as <code>FEATURE_PAL<\/code>, the environment block is limited to 32,767 characters and must be mappable to ANSI characters.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There&#8217;s no hard-coded limit in Windows, but maybe somebody else has a limit.<\/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-108009","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>There&#8217;s no hard-coded limit in Windows, but maybe somebody else has a limit.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108009","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=108009"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108009\/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=108009"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=108009"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=108009"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}