{"id":32499,"date":"2023-06-29T15:06:12","date_gmt":"2023-06-29T15:06:12","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cppblog\/?p=32499"},"modified":"2023-07-13T08:04:44","modified_gmt":"2023-07-13T08:04:44","slug":"addresssanitizer-continue_on_error","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/addresssanitizer-continue_on_error\/","title":{"rendered":"AddressSanitizer continue_on_error"},"content":{"rendered":"<p>Visual Studio 17.6 comes with new functionality in the Address Sanitizer runtime which provides a new \u201cchecked build\u201d for C and C++. This new runtime mode diagnoses and reports hidden memory safety errors, with zero false positives, as your app runs.<\/p>\n<h2><span style=\"font-size: 18pt;\">Introduction<\/span><\/h2>\n<p>C++ <a href=\"https:\/\/learn.microsoft.com\/en-us\/cpp\/sanitizers\/asan?view=msvc-170#error-types\">memory safety errors<\/a> are a <a href=\"#post-32499-_Top_Concern_\u2013\">top concern<\/a> for the industry. In Visual Studio 17.6, we deliver a new experimental Address Sanitizer feature: continue_on_error (COE). We\u2019ll remove the experimental label in 17.8. You compile as before, by simply adding the compiler flag <code>-fsanitize=address<\/code>. With 17.6 you can enable the COE functionality by setting environment variables from the command line.<\/p>\n<p>To stream unique memory safety errors to stdout(1) or stderr(2):<\/p>\n<ul>\n<li>set ASAN_OPTIONS=continue_on_error=1<\/li>\n<li>set ASAN_OPTIONS=continue_on_error=2<\/li>\n<\/ul>\n<p>To stream to a log file of your choice:<\/p>\n<ul>\n<li>set COE_LOG_FILE=your.file.log<\/li>\n<\/ul>\n<p>When you opt into the new continue on error (COE) feature, your application automatically diagnoses and reports unique memory safety errors as it runs. At program exit, the runtime produces a <a href=\"#post-32499-_Example\">final summary<\/a> that follows the unique detailed reports normally produced by the Address Sanitizer.<\/p>\n<p>The compiler instruments your binaries to work with the address sanitizer runtime to diagnose hidden memory safety errors. You can add the <code>-fsanitize=address -Zi<\/code> compiler flags and set the <code>ASAN_OPTIONS<\/code> or <code>COE_LOG_FILE<\/code> environment variable with values shown previously. You can then build and run your existing tests to exercise your code to find hidden memory-safety errors.<\/p>\n<p>This new COE functionality provides a \u201cchecked build\u201d for C and C++ that finds hidden memory safety errors with zero false positives.<\/p>\n<p><span style=\"font-size: 18pt;\">Hidden memory safety errors<\/span><\/p>\n<p>The source code in Figure 1 which follows creates a buffer overflow due to the off-by-one error in the loop exit test. The code should check for <code>ii &lt; sz<\/code>, but instead checks for <code>ii &lt;= sz<\/code>. When the example runs, it is <strong>secure by coincidence<\/strong>. That\u2019s because of the over-allocation and alignment done by most C++ runtime implementations. When<code> sz % 16 == 0<\/code>, the final write to <code>local<\/code> corrupts data. In other cases only read\/write to the \u201cmalloc slop\u201d which is due to the C Runtime (CRT), padding allocations out to a <code>0 mod 16<\/code> aggregate boundary.<\/p>\n<p>Errors will only be observable if the following page is unmapped, or upon some subsequent use of corrupted data. All other cases are silent in the Figure 1 example that follows.<\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">#include &lt;stdlib.h&gt; \r\nchar* func(char* buf, size_t sz) { \r\n    char* local = (char*)malloc(sz); \r\n    for (auto ii = 0; ii &lt;= sz; ii++) { \/\/ bad loop exit test \r\n        local[ii] = ~buf[ii]; \/\/ Two memory safety errors \r\n    } \r\n    return local; \r\n} \r\n\r\nchar original[10] = { 0,1,2,3,4,5,6,7,8,9 }; \r\n\r\nvoid main() { \u00a0 \r\n    char* inverted_buf= func(original,10); \r\n}<\/code><\/pre>\n<p style=\"padding-left: 400px; text-align: left;\"><span style=\"font-size: 10pt;\"><strong>Figure 1<\/strong><\/span><\/p>\n<p>In this example, where the parameter <code>sz<\/code> is 10 and the original buffer is 10-bytes, there are two memory safety errors: one is an out-of-bounds load from <code>buf<\/code> and the other is an out-of-bounds store to <code>local<\/code>. With <code>continue_on_error<\/code>, you will see both errors in the summary, and the program will run to completion. Here\u2019s the summary:<\/p>\n<p><img decoding=\"async\" class=\"alignnone wp-image-32503\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/a-screenshot-of-a-computer-program-description-au-4.png\" alt=\"Terminal showing two memory safety issues being found\" width=\"1430\" height=\"397\" srcset=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/a-screenshot-of-a-computer-program-description-au-4.png 1430w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/a-screenshot-of-a-computer-program-description-au-4-300x83.png 300w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/a-screenshot-of-a-computer-program-description-au-4-1024x284.png 1024w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/a-screenshot-of-a-computer-program-description-au-4-768x213.png 768w\" sizes=\"(max-width: 1430px) 100vw, 1430px\" \/><\/p>\n<p style=\"text-align: center;\"><span style=\"font-size: 10pt;\"><strong>Figure 2<\/strong><\/span><\/p>\n<p>Note that <code>continue_on_error<\/code> reports two distinct errors that occur on the same source line. The first error reads memory at a global address in the <code>.data<\/code> section, and the other writes to memory allocated from the heap.<\/p>\n<p><span style=\"font-size: 18pt;\">Description<\/span><\/p>\n<p>The default Address Sanitizer runtime behavior terminates your application after reporting the first error encountered while running your program. It does not allow the \u201cbad\u201d machine instruction to execute. COE is a customer-requested change significantly different compared to the \u201cone-n-done\u201d behavior of the existing Address Sanitizer runtime. The new Address Sanitizer runtime diagnoses and reports errors, but then executes subsequent instructions.<\/p>\n<p>The new COE functionality allows an application to <strong>continue running while reporting<\/strong> unique memory safety errors to a log file or to the command line. When enabled, COE tries to automatically return control back to the application after reporting each memory safety error, except for an access violation (AV) or failed memory allocation. With COE, you can compile and deploy an existing application into limited production to find memory safety issues while running for days (albeit slower).<\/p>\n<p>By adding compiler flags and setting an environment variable, you can immediately improve correctness and security. Your existing tests will still pass but will <strong><em>also<\/em><\/strong> uncover hidden memory safety errors. The compiler option (<code>-fsanitizer=address<\/code>) and runtime environment flag can be used to introduce a new \u201cshipping gate.\u201d Subsequently COE can then be used with all your existing tests. The developer gets a simple, well-defined, pass\/fail for shipping any C or C++ app on Windows.<\/p>\n<p>Internally we have found that using this technology significantly reduces memory safety errors. If all your existing tests pass, <strong><em>but<\/em><\/strong> this new feature reports a memory safety error or a leak, don\u2019t ship your new code or integrate it into a parent branch.<\/p>\n<p><span style=\"font-size: 18pt;\"><strong>Example<\/strong><\/span><\/p>\n<pre style=\"padding-left: 160px;\">#include &lt;cstdio&gt;\r\n#include &lt;string&gt;\r\n\r\nstruct Base {\r\n    \/\/virtual ~Base() = default;\r\n};\r\n\r\nstruct Derived : public Base {\r\n    std::wstring Value = L\"Leaked if Base destructor is not virtual!\";\r\n};\r\n\r\nconstexpr size_t PointDims = 3;\r\ndouble pointsInGlobalData[PointDims] = { 1.0, 2.0, 3.0 };\r\n\r\nint main() {\r\n\r\n  pointsInGlobalData[3] = 3.0;\r\n\r\n  for (int i = 0; i &lt; 2; i++) {\r\n    double pointOnStack[PointDims] = { 1.0, 2.0, 3.0 };\r\n    pointOnStack[-1] = 3.0;\r\n    pointOnStack[PointDims] = 0.0;\r\n\r\n    double* pointOnHeap = new double[PointDims + 100000];\r\n    pointOnHeap[-1] = 4.0;\r\n    delete[] pointOnHeap;\r\n\r\n    double* pointDouble = new double[PointDims] { 1.0, 2.0, 3.0 };\r\n    pointDouble[PointDims] = 4.0; \/\/ overflow\r\n    delete[] pointDouble;         \/\/ we continue\r\n    Base* base = new Derived();\r\n    delete base; \/\/ missing virtual destructor\r\n\r\n    constexpr size_t buff_size = 128;\r\n    char* buffer = new char[buff_size];\r\n    std::memset(buffer, '\\0', buff_size);\r\n    std::memset(&amp;buffer[buff_size - 28], '=', 30);\r\n  }\r\n  wprintf_s(L\"Loop completed! \\r\\n\");\r\n}<\/pre>\n<p style=\"padding-left: 440px;\"><span style=\"font-size: 10pt;\"><strong>Figure 3<\/strong><\/span><\/p>\n<p>With <code>continue_on_error<\/code>, the program in Figure 3 above, produces the summary in Figure 4. That summary is printed<strong><em> after<\/em><\/strong> streaming all unique detailed error reports which are produced using the existing default mode of the Address Sanitizer. The existing default mode is \u201cone-n-done\u201d. The previous Address Sanitizer only prints one detailed error report, and then exits your process. With <code>continue_on_error<\/code>, we continue to execute after various memory safety errors. This summary illustrates continuing after many memory safety errors:<\/p>\n<p><img decoding=\"async\" class=\"alignnone wp-image-32504\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/a-screenshot-of-a-computer-description-automatica.png\" alt=\"Console showing 7 unique memory safety issues being found\" width=\"1685\" height=\"1072\" srcset=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/a-screenshot-of-a-computer-description-automatica.png 1685w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/a-screenshot-of-a-computer-description-automatica-300x191.png 300w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/a-screenshot-of-a-computer-description-automatica-1024x651.png 1024w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/a-screenshot-of-a-computer-description-automatica-768x489.png 768w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/a-screenshot-of-a-computer-description-automatica-1536x977.png 1536w\" sizes=\"(max-width: 1685px) 100vw, 1685px\" \/><\/p>\n<p style=\"text-align: center;\"><span style=\"font-size: 10pt;\"><strong>Figure 4<\/strong><\/span><\/p>\n<p>Beneath the first red box at the top of Figure 4, there are three files sorted by error. This is followed by the file, function, and line displayed beneath the second box. The third box calls out eight unique errors, where &#8220;unique&#8221; is defined in terms of a hash function which uses call stacks and error descriptions. Use of the term <a href=\"#post-32499-_Unique\">unique<\/a> is discussed in the next section.<\/p>\n<p>The detailed error reports (omitted in the screen capture in Figure 4) are printed before this summary and contain shadow bytes with all the details for each error in the summary.<\/p>\n<p><span style=\"font-size: 18pt;\">Unique<\/span><\/p>\n<p>The uniqueness of an error (to limit streaming duplicates) is determined by an internal <strong>hash function<\/strong> that uses the type of error and the call stack(s) at the time of error. A detailed individual error report includes stack trace(s). Here are the two detailed errors in the \u201csecure by coincidence\u201d example in Figure 1. The call stacks and types of errors are used to internally create an internal C++ error object, which is then hashed to a unique integer. The global-buffer-overflow in Figure 5 only has one call stack and is a different type of error object from the heap-buffer-overflow in Figure 6, which has two call stacks.<\/p>\n<p><img decoding=\"async\" width=\"2415\" height=\"500\" class=\"wp-image-32505\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-3.png\" srcset=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-3.png 2415w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-3-300x62.png 300w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-3-1024x212.png 1024w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-3-768x159.png 768w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-3-1536x318.png 1536w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-3-2048x424.png 2048w\" sizes=\"(max-width: 2415px) 100vw, 2415px\" \/><\/p>\n<p style=\"text-align: center;\"><span style=\"font-size: 10pt;\"><strong>Figure 5<\/strong><\/span><\/p>\n<p><img decoding=\"async\" width=\"2450\" height=\"770\" class=\"wp-image-32506\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-4.png\" srcset=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-4.png 2450w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-4-300x94.png 300w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-4-1024x322.png 1024w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-4-768x241.png 768w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-4-1536x483.png 1536w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-4-2048x644.png 2048w\" sizes=\"(max-width: 2450px) 100vw, 2450px\" \/><\/p>\n<p style=\"text-align: center;\"><span style=\"font-size: 10pt;\"><strong>Figure 6<\/strong><\/span><\/p>\n<p>The runtime will hash each occurrence of an error at runtime in order to prevent duplication. Consider a <a href=\"https:\/\/learn.microsoft.com\/en-us\/cpp\/sanitizers\/asan?view=msvc-170#error-types\">memory-safety<\/a> error that\u2019s executed 10000 times in a loop. The detailed error will be reported once, but its \u201chit count\u201d of 1000 will be reported in the summary.<\/p>\n<p><span style=\"font-size: 18pt;\">Not continuing.<\/span><\/p>\n<p>Two examples where the continue on error feature <strong><em>cannot continue<\/em><\/strong> are:<\/p>\n<ul>\n<li>Malloc is given an undefined argument, such as a negative number.<\/li>\n<li>There\u2019s an access violation while trying to read or write to memory that hasn\u2019t been allocated, or to which it doesn\u2019t have access.<\/li>\n<\/ul>\n<p>Consider the following program which has an access violation because it tries to <strong>read from location <code>0x13<\/code><\/strong>:<\/p>\n<pre style=\"padding-left: 160px;\">#include &lt;stdio.h&gt;\r\n\r\nvoid main()\r\n{\r\n    unsigned int* local_ptr = (unsigned int*) 0x13;\r\n    printf(\"use of undefined address %p [%x]\\n\", local_ptr, *local_ptr);\r\n}<\/pre>\n<p style=\"text-align: center;\"><span style=\"font-size: 10pt;\"><strong>Figure 7<\/strong><\/span><\/p>\n<p>On Windows 11, when the example in Figure 7 above, is compiled with <code>-fsanitize=address -Zi<\/code>, you\u2019ll see the following error message in Figure 8, below.<\/p>\n<p><img decoding=\"async\" class=\"alignnone wp-image-32507\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-5.png\" alt=\"CONTINUE CANCELLED - Deadly Signal. Shutting down.\" width=\"1531\" height=\"451\" srcset=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-5.png 1531w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-5-300x88.png 300w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-5-1024x302.png 1024w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/word-image-32499-5-768x226.png 768w\" sizes=\"(max-width: 1531px) 100vw, 1531px\" \/><\/p>\n<p style=\"text-align: center;\"><span style=\"font-size: 10pt;\"><strong>Figure 8<\/strong><\/span><\/p>\n<p>We choose to \u201cgracefully cancel\u201d the attempt to continue from access violations that are <strong>not<\/strong> caught with a user\u2019s structured exception handling.<\/p>\n<h2><span style=\"font-size: 18pt;\">Matching undefined behavior<\/span><\/h2>\n<p>We haven\u2019t been able to do a complete audit that would allow us to \u201cmatch\u201d undefined behaviors for C and C++. The following example in Figure 9, makes this tangible. At the commented line in the following code example, code generation from the compiler and the runtime implementation are both different for <code>_alloca <\/code>when compiling with <code>-fsanitize=address -Zi<\/code>:<\/p>\n<pre style=\"padding-left: 280px;\">#include &lt;cstdio&gt;\r\n#include &lt;cstring&gt;\r\n#include &lt;malloc.h&gt;\r\n#include &lt;excpt.h&gt;\r\n#include &lt;windows.h&gt;\r\n\r\n#define RET_FINISH 0\r\n#define RET_STACK_EXCEPTION 1\r\n#define RET_OTHER_EXCEPTION 2\r\n\r\nint foo_redundant(unsigned long arg_var) {\r\n\r\n  char *a;\r\n  int ret = -1;\r\n\r\n  __try\r\n  {\r\n    if ((arg_var+3) &gt; arg_var) {\r\n<strong>      \/\/ Call to alloca using parameter from main<\/strong>\r\n<strong>      a = (char *) _alloca(arg_var); <\/strong>\r\n      memset(a, 0, 10);\r\n    }\r\n    ret = RET_FINISH;\r\n  }\r\n  __except(1)\r\n  {\r\n    ret = RET_OTHER_EXCEPTION;\r\n    int i = GetExceptionCode();\r\n    if (i == EXCEPTION_STACK_OVERFLOW) {\r\n      ret = RET_STACK_EXCEPTION;\r\n    }\r\n  }  \r\n  return ret;\r\n}\r\n\r\nvoid main(){ \r\n  int cnt = 0;\r\n  if (foo_redundant(0xfffffff0) == RET_STACK_EXCEPTION)\r\n<b>    cnt++; \/\/increment count of <\/b><span style=\"font-size: 14.4px;\"><b>exceptions<\/b><\/span><b> handled.<\/b>\r\n\r\n  if (cnt == 1)\r\n    printf(\"pass\\n\");\r\n  else\r\n    printf(\"fail\\n\");\r\n}<\/pre>\n<p style=\"padding-left: 400px;\"><span style=\"font-size: 10pt;\"><strong>Figure 9<\/strong><\/span><\/p>\n<p>The previous example, in Figure 9, prints <strong>pass<\/strong> without <code>-fsanitize=address<\/code>. That\u2019s because<code> cnt==1 <\/code>due to an exception. It will fail when compiled with that flag and run with the Address Sanitizer runtime. In <code>main()<\/code> we pass a large number to <code>foo_redundant<\/code>, which is passed to <code>_alloca()<\/code>.<\/p>\n<p>With the Address Sanitizer in <code>continue_on_error<\/code> (COE) mode, this program runs to completion, but prints <strong>fail<\/strong>. The code generation from the compiler must match the ABI for the Address Sanitizer runtime. For the Address Sanitizer runtime, the compiler grows the allocation size and aligns it 0 mod 32 (a cache line). That math will cause an integer overflow (i.e., wrap around) creating a reasonable, small positive number as the parameter to <code>_alloca<\/code>.<\/p>\n<p><strong>There will be no stack overflow exception to process the <code>__except<\/code> handler.` <\/strong><\/p>\n<p>We have not had time to document or clearly define the subtle differences when a program has undefined behavior. This was a reason for releasing <code>continue_on_error<\/code> as experimental at first.<\/p>\n<p><strong>NOTE: The frequency with which this concern has become visible, has been rare with our testing infrastructure.<\/strong><\/p>\n<h2><a id=\"post-32499-_Top_Concern_\u2013\"><\/a><span style=\"font-size: 18pt;\">Top Concern \u2013 don\u2019t ship without it.<\/span><\/h2>\n<p>There were six categories of C++ <a href=\"https:\/\/learn.microsoft.com\/en-us\/cpp\/sanitizers\/asan?view=msvc-170#error-types\">memory safety<\/a> errors in the 2021 Common Weakness Enumeration (CWE) <a href=\"https:\/\/nam06.safelinks.protection.outlook.com\/?url=https%3A%2F%2Fcwe.mitre.org%2Ftop25%2Farchive%2F2021%2F2021_cwe_top25.html&amp;data=05%7C01%7Cjradigan%40microsoft.com%7C9962b611c58546f2df3308db4add742b%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C638186087241566753%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=ZWphesh6v9f2PKasnd2qxKrq26EebWpv8Tb6JK1RFXg%3D&amp;reserved=0\">Top 25 Most Dangerous Software Weaknesses<\/a>. The best <a href=\"https:\/\/nam06.safelinks.protection.outlook.com\/?url=https%3A%2F%2Fpwnies.com%2Fwinners%2F&amp;data=05%7C01%7Cjradigan%40microsoft.com%7C9962b611c58546f2df3308db4add742b%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C638186087241566753%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=%2BbYI%2FqxTAHAPZzkmdmnFgpaQ%2Bb4%2B1a953XrBDUVZ9OI%3D&amp;reserved=0\">Remote Code Execution Bug<\/a> was a 20 year old heap-buffer-overflow. This award in 2022 went to BugHunter010 at Cyber KunLun Lab. This engineer discovered a heap-buffer-overflow vulnerability in the RPC protocol with CVSS score 9.8. This bug has existed in the Windows system for more than 20 years. There are new C++ memory safety bugs introduced daily because traditional testing can\u2019t expose these types of bugs without compiler and runtime support.<\/p>\n<p>This new feature is designed to enable developers to implement a simple new gate for shipping C++ on Windows. Using this technology will significantly reduce memory safety errors. If your tests pass but continue_on_error reports any hidden memory safety errors, you should not ship or integrate new code into the development branch.<a id=\"post-32499-_Hidden_memory_safety\"><\/a><\/p>\n<p><strong>We intend that continue_on_error be used as pass\/fail gate, for all CI\/CD pipelines using C and C++.<\/strong><\/p>\n<h2><span style=\"font-size: 18pt;\">Call To Action<\/span><\/h2>\n<p>We invite you to install the 17.6 version of <a href=\"https:\/\/visualstudio.microsoft.com\/downloads\/\">Visual Studio<\/a> or later, try out the continue on error feature, and give us <a href=\"https:\/\/developercommunity.visualstudio.com\/home\">feedback<\/a><a id=\"post-32499-_Dynamic_vs._Static\"><\/a>.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Visual Studio 17.6 comes with new functionality in the Address Sanitizer runtime which provides a new \u201cchecked build\u201d for C and C++. This new runtime mode diagnoses and reports hidden memory safety errors, with zero false positives, as your app runs. Introduction C++ memory safety errors are a top concern for the industry. In Visual [&hellip;]<\/p>\n","protected":false},"author":37422,"featured_media":32506,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1,280,3929,277],"tags":[3893,3930,3938,3937,3934,3935,3931,3933,3932,3936],"class_list":["post-32499","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cplusplus","category-new-user","category-pure-virtual-c","category-writing-code","tag-address-sanitizer","tag-asan","tag-c-ci-cd","tag-c-memory-safety","tag-checked","tag-checked-builds","tag-continue","tag-continue-on-error","tag-continue_on_error","tag-memory-safety"],"acf":[],"blog_post_summary":"<p>Visual Studio 17.6 comes with new functionality in the Address Sanitizer runtime which provides a new \u201cchecked build\u201d for C and C++. This new runtime mode diagnoses and reports hidden memory safety errors, with zero false positives, as your app runs. Introduction C++ memory safety errors are a top concern for the industry. In Visual [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/32499","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/37422"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=32499"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/32499\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/32506"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=32499"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=32499"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=32499"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}