{"id":2031,"date":"2023-05-05T10:48:07","date_gmt":"2023-05-05T02:48:07","guid":{"rendered":"\/?p=2031"},"modified":"2023-05-05T10:48:07","modified_gmt":"2023-05-05T02:48:07","slug":"cc%e5%ae%89%e5%85%a8%e6%8c%87%e5%8d%97","status":"publish","type":"post","link":"\/?p=2031","title":{"rendered":"C,C++\u5b89\u5168\u6307\u5357"},"content":{"rendered":"<p><a id=\"1\"><\/a><\/p>\n<h2>\u901a\u7528\u5b89\u5168\u6307\u5357<\/h2>\n<p><a id=\"1.1\"><\/a><\/p>\n<h3>1 C\/C++\u4f7f\u7528\u9519\u8bef<\/h3>\n<p><a id=\"1.1.1\"><\/a><\/p>\n<h4>1.1  \u3010\u5fc5\u987b\u3011\u4e0d\u5f97\u76f4\u63a5\u4f7f\u7528\u65e0\u957f\u5ea6\u9650\u5236\u7684\u5b57\u7b26\u62f7\u8d1d\u51fd\u6570<\/h4>\n<p>\u4e0d\u5e94\u76f4\u63a5\u4f7f\u7528legacy\u7684\u5b57\u7b26\u4e32\u62f7\u8d1d\u3001\u8f93\u5165\u51fd\u6570\uff0c\u5982strcpy\u3001strcat\u3001sprintf\u3001wcscpy\u3001mbscpy\u7b49\uff0c\u8fd9\u4e9b\u51fd\u6570\u7684\u7279\u5f81\u662f\uff1a\u53ef\u4ee5\u8f93\u51fa\u4e00\u957f\u4e32\u5b57\u7b26\u4e32\uff0c\u800c\u4e0d\u9650\u5236\u957f\u5ea6\u3002\u5982\u679c\u73af\u5883\u5141\u8bb8\uff0c\u5e94\u5f53\u4f7f\u7528\u5176_s\u5b89\u5168\u7248\u672c\u66ff\u4ee3\uff0c\u6216\u8005\u4f7f\u7528n\u7248\u672c\u51fd\u6570\uff08\u5982\uff1asnprintf\uff0cvsnprintf\uff09\u3002<\/p>\n<p>\u82e5\u4f7f\u7528\u5f62\u5982sscanf\u4e4b\u7c7b\u7684\u51fd\u6570\u65f6\uff0c\u5728\u5904\u7406\u5b57\u7b26\u4e32\u8f93\u5165\u65f6\u5e94\u5f53\u901a\u8fc7%10s\u8fd9\u6837\u7684\u65b9\u5f0f\u6765\u4e25\u683c\u9650\u5236\u5b57\u7b26\u4e32\u957f\u5ea6\uff0c\u540c\u65f6\u786e\u4fdd\u5b57\u7b26\u4e32\u672b\u5c3e\u6709\\0\u3002\u5982\u679c\u73af\u5883\u5141\u8bb8\uff0c\u5e94\u5f53\u4f7f\u7528_s\u5b89\u5168\u7248\u672c\u3002<\/p>\n<p>\u4f46\u662f\u6ce8\u610f\uff0c\u867d\u7136MSVC 2015\u65f6\u9ed8\u8ba4\u5f15\u5165\u7ed3\u5c3e\u4e3a0\u7248\u672c\u7684<code>snprintf<\/code>\uff08\u884c\u4e3a\u7b49\u540c\u4e8eC99\u5b9a\u4e49\u7684<code>snprintf<\/code>\uff09\u3002\u4f46\u66f4\u65e9\u671f\u7684\u7248\u672c\u4e2d\uff0cMSVC\u7684<code>snprintf<\/code>\u53ef\u80fd\u662f<code>_snprintf<\/code>\u7684\u5b8f\u3002\u800c<code>_snprintf<\/code>\u662f\u4e0d\u4fdd\u8bc1\\0\u7ed3\u5c3e\u7684\uff08\u89c1\u672c\u8282\u540e\u534a\u90e8\u5206\uff09\u3002<\/p>\n<pre><code class=\"language-c++\">\uff08MSVC\uff09\nBeginning with the UCRT in Visual Studio 2015 and Windows 10, snprintf is no longer identical to _snprintf. The snprintf function behavior is now C99 standard compliant.\n\n\u4eceVisual Studio 2015\u548cWindows 10\u4e2d\u7684UCRT\u5f00\u59cb\uff0csnprintf\u4e0d\u518d\u4e0e_snprintf\u76f8\u540c\u3002snprintf\u51fd\u6570\u884c\u4e3a\u73b0\u5728\u7b26\u5408C99\u6807\u51c6\u3002\n\n\u8bf7\u53c2\u8003\uff1ahttps:\/\/docs.microsoft.com\/en-us\/cpp\/c-runtime-library\/reference\/snprintf-snprintf-snprintf-l-snwprintf-snwprintf-l?redirectedfrom=MSDN&amp;view=vs-2019<\/code><\/pre>\n<p>\u56e0\u6b64\uff0c\u5728\u4f7f\u7528n\u7cfb\u5217\u62f7\u8d1d\u51fd\u6570\u65f6\uff0c\u8981\u786e\u4fdd\u6b63\u786e\u8ba1\u7b97\u7f13\u51b2\u533a\u957f\u5ea6\uff0c\u540c\u65f6\uff0c\u5982\u679c\u4f60\u4e0d\u786e\u5b9a\u662f\u5426\u4ee3\u7801\u5728\u5404\u4e2a\u7f16\u8bd1\u5668\u4e0b\u90fd\u80fd\u786e\u4fdd\u672b\u5c3e\u67090\u65f6\uff0c\u5efa\u8bae\u53ef\u4ee5\u9002\u5f53\u589e\u52a01\u5b57\u8282\u8f93\u5165\u7f13\u51b2\u533a\uff0c\u5e76\u5c06\u5176\u7f6e\u4e3a\\0\uff0c\u4ee5\u4fdd\u8bc1\u8f93\u51fa\u7684\u5b57\u7b26\u4e32\u7ed3\u5c3e\u4e00\u5b9a\u6709\\0\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nchar buf[101] = {0};\nsnprintf(buf, sizeof(buf) - 1, &quot;foobar ...&quot;, ...);<\/code><\/pre>\n<p>\u4e00\u4e9b\u9700\u8981\u6ce8\u610f\u7684\u51fd\u6570\uff0c\u4f8b\u5982<code>strncpy<\/code>\u548c<code>_snprintf<\/code>\u662f\u4e0d\u5b89\u5168\u7684\u3002 <code>strncpy<\/code>\u4e0d\u5e94\u5f53\u88ab\u89c6\u4e3a<code>strcpy<\/code>\u7684n\u7cfb\u5217\u51fd\u6570\uff0c\u5b83\u53ea\u662f\u6070\u5de7\u4e0e\u5176\u4ed6n\u7cfb\u5217\u51fd\u6570\u540d\u5b57\u5f88\u50cf\u800c\u5df2\u3002<code>strncpy<\/code>\u5728\u590d\u5236\u65f6\uff0c\u5982\u679c\u590d\u5236\u7684\u957f\u5ea6\u8d85\u8fc7n\uff0c\u4e0d\u4f1a\u5728\u7ed3\u5c3e\u8865\\0\u3002<\/p>\n<p>\u540c\u6837\uff0cMSVC <code>_snprintf<\/code>\u7cfb\u5217\u51fd\u6570\u5728\u8d85\u8fc7\u6216\u7b49\u4e8en\u65f6\u4e5f\u4e0d\u4f1a\u4ee50\u7ed3\u5c3e\u3002\u5982\u679c\u540e\u7eed\u4f7f\u7528\u975e0\u7ed3\u5c3e\u7684\u5b57\u7b26\u4e32\uff0c\u53ef\u80fd\u6cc4\u9732\u76f8\u90bb\u7684\u5185\u5bb9\u6216\u8005\u5bfc\u81f4\u7a0b\u5e8f\u5d29\u6e83\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nchar a[4] = {0};\n_snprintf(a, 4, &quot;%s&quot;, &quot;AAAA&quot;);\nfoo = strlen(a);<\/code><\/pre>\n<p>\u4e0a\u8ff0\u4ee3\u7801\u5728MSVC\u4e2d\u6267\u884c\u540e\uff0c a[4] == 'A'\uff0c\u56e0\u6b64\u5b57\u7b26\u4e32\u672a\u4ee50\u7ed3\u5c3e\u3002a\u7684\u5185\u5bb9\u662f&quot;AAAA&quot;\uff0c\u8c03\u7528<code>strlen(a)<\/code>\u5219\u4f1a\u8d8a\u754c\u8bbf\u95ee\u3002\u56e0\u6b64\uff0c\u6b63\u786e\u7684\u64cd\u4f5c\u4e3e\u4f8b\u5982\u4e0b\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nchar a[4] = {0};\n_snprintf(a, sizeof(a), &quot;%s&quot;, &quot;AAAA&quot;);\na[sizeof(a) - 1] = &#039;\\0&#039;;\nfoo = strlen(a);<\/code><\/pre>\n<p>\u5728 C++ \u4e2d\uff0c\u5f3a\u70c8\u5efa\u8bae\u7528 <code>string<\/code>\u3001<code>vector<\/code> \u7b49\u66f4\u9ad8\u5c01\u88c5\u5c42\u6b21\u7684\u57fa\u7840\u7ec4\u4ef6\u4ee3\u66ff\u539f\u59cb\u6307\u9488\u548c\u52a8\u6001\u6570\u7ec4\uff0c\u5bf9\u63d0\u9ad8\u4ee3\u7801\u7684\u53ef\u8bfb\u6027\u548c\u5b89\u5168\u6027\u90fd\u6709\u5f88\u5927\u7684\u5e2e\u52a9\u3002<\/p>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u4fe1\u606f\u6cc4\u9732<\/code><\/p>\n<p><code>\u4f4e\u98ce\u9669-\u62d2\u7edd\u670d\u52a1<\/code><\/p>\n<p><code>\u9ad8\u98ce\u9669-\u7f13\u51b2\u533a\u6ea2\u51fa<\/code><\/p>\n<p><a id=\"1.1.2\"><\/a><\/p>\n<h4>1.2  \u3010\u5fc5\u987b\u3011\u521b\u5efa\u8fdb\u7a0b\u7c7b\u7684\u51fd\u6570\u7684\u5b89\u5168\u89c4\u8303<\/h4>\n<p>system\u3001WinExec\u3001CreateProcess\u3001ShellExecute\u7b49\u542f\u52a8\u8fdb\u7a0b\u7c7b\u7684\u51fd\u6570\uff0c\u9700\u8981\u4e25\u683c\u68c0\u67e5\u5176\u53c2\u6570\u3002<\/p>\n<p>\u542f\u52a8\u8fdb\u7a0b\u9700\u8981\u52a0\u4e0a\u53cc\u5f15\u53f7\uff0c\u9519\u8bef\u4f8b\u5b50\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nWinExec(&quot;D:\\\\program files\\\\my folder\\\\foobar.exe&quot;, SW_SHOW);<\/code><\/pre>\n<p>\u5f53\u5b58\u5728<code>D:\\program files\\my.exe<\/code>\u7684\u65f6\u5019\uff0cmy.exe\u4f1a\u88ab\u542f\u52a8\u3002\u800cfoobar.exe\u4e0d\u4f1a\u542f\u52a8\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nWinExec(&quot;\\&quot;D:\\\\program files\\\\my folder\\\\foobar.exe\\&quot;&quot;, SW_SHOW);<\/code><\/pre>\n<p>\u53e6\u5916\uff0c\u5982\u679c\u542f\u52a8\u65f6\u4ece\u7528\u6237\u8f93\u5165\u3001\u73af\u5883\u53d8\u91cf\u8bfb\u53d6\u7ec4\u5408\u547d\u4ee4\u884c\u65f6\uff0c\u8fd8\u9700\u8981\u6ce8\u610f\u662f\u5426\u53ef\u80fd\u5b58\u5728\u547d\u4ee4\u6ce8\u5165\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nstd::string cmdline = &quot;calc &quot;;\ncmdline += user_input;\nsystem(cmdline.c_str());<\/code><\/pre>\n<p>\u6bd4\u5982\uff0c\u5f53\u7528\u6237\u8f93\u5165<code>1+1 &amp;&amp; ls<\/code>\u65f6\uff0c\u6267\u884c\u7684\u5b9e\u9645\u4e0a\u662fcalc 1+1\u548cls \u4e24\u4e2a\u547d\u4ee4\uff0c\u5bfc\u81f4\u547d\u4ee4\u6ce8\u5165\u3002<\/p>\n<p>\u9700\u8981\u68c0\u67e5\u7528\u6237\u8f93\u5165\u662f\u5426\u542b\u6709\u975e\u6cd5\u6570\u636e\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nstd::string cmdline = &quot;ls &quot;;\ncmdline += user_input;\n\nif(cmdline.find_first_not_of(&quot;1234567890.+-*\/e &quot;) == std::string::npos)\n  system(cmdline.c_str());\nelse\n  warning(...);<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u4ee3\u7801\u6267\u884c<\/code><\/p>\n<p><code>\u9ad8\u98ce\u9669-\u6743\u9650\u63d0\u5347<\/code><\/p>\n<p><a id=\"1.1.3\"><\/a><\/p>\n<h4>1.3  \u3010\u5fc5\u987b\u3011\u5c3d\u91cf\u51cf\u5c11\u4f7f\u7528 _alloca \u548c\u53ef\u53d8\u957f\u5ea6\u6570\u7ec4<\/h4>\n<p>_alloca \u548c<a href=\"https:\/\/zh.wikipedia.org\/wiki\/%E5%8F%AF%E5%8F%98%E9%95%BF%E6%95%B0%E7%BB%84\">\u53ef\u53d8\u957f\u5ea6\u6570\u7ec4<\/a>\u4f7f\u7528\u7684\u5185\u5b58\u91cf\u5728\u7f16\u8bd1\u671f\u95f4\u4e0d\u53ef\u77e5\u3002\u5c24\u5176\u662f\u5728\u5faa\u73af\u4e2d\u4f7f\u7528\u65f6\uff0c\u6839\u636e\u7f16\u8bd1\u5668\u7684\u5b9e\u73b0\u4e0d\u540c\uff0c\u53ef\u80fd\u4f1a\u5bfc\u81f4\uff1a\uff081\uff09\u6808\u6ea2\u51fa\uff0c\u5373\u62d2\u7edd\u670d\u52a1\uff1b \uff082\uff09\u7f3a\u5c11\u6808\u5185\u5b58\u6d4b\u8bd5\u7684\u7f16\u8bd1\u5668\u5b9e\u73b0\u53ef\u80fd\u5bfc\u81f4\u7533\u8bf7\u5230\u975e\u6808\u5185\u5b58\uff0c\u5e76\u5bfc\u81f4\u5185\u5b58\u635f\u574f\u3002\u8fd9\u5728\u6808\u6bd4\u8f83\u5c0f\u7684\u7a0b\u5e8f\u4e0a\uff0c\u4f8b\u5982IoT\u8bbe\u5907\u56fa\u4ef6\u4e0a\u5f71\u54cd\u5c24\u4e3a\u5927\u3002\u5bf9\u4e8e C++\uff0c\u53ef\u53d8\u957f\u5ea6\u6570\u7ec4\u4e5f\u5c5e\u4e8e\u975e\u6807\u51c6\u6269\u5c55\uff0c\u5728\u4ee3\u7801\u89c4\u8303\u4e2d\u7981\u6b62\u4f7f\u7528\u3002<\/p>\n<p>\u9519\u8bef\u793a\u4f8b\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nfor (int i = 0; i &lt; 100000; i++) {\n  char* foo = (char *)_alloca(0x10000);\n  ..do something with foo ..;\n}\n\nvoid Foo(int size) {\n  char msg[size]; \/\/ \u4e0d\u53ef\u63a7\u7684\u6808\u6ea2\u51fa\u98ce\u9669\uff01\n}<\/code><\/pre>\n<p>\u6b63\u786e\u793a\u4f8b\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\n\/\/ \u6539\u7528\u52a8\u6001\u5206\u914d\u7684\u5806\u5185\u5b58\nfor (int i = 0; i &lt; 100000; i++) {\n  char * foo = (char *)malloc(0x10000);\n  ..do something with foo ..;\n  if (foo_is_no_longer_needed) {\n    free(foo);\n    foo = NULL;\n  }\n}\n\nvoid Foo(int size) {\n  std::string msg(size, &#039;\\0&#039;);  \/\/ C++\n  char* msg = malloc(size);  \/\/ C\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4f4e\u98ce\u9669-\u62d2\u7edd\u670d\u52a1<\/code><\/p>\n<p><code>\u9ad8\u98ce\u9669-\u5185\u5b58\u7834\u574f<\/code><\/p>\n<p><a id=\"1.1.4\"><\/a><\/p>\n<h4>1.4  \u3010\u5fc5\u987b\u3011printf\u7cfb\u5217\u53c2\u6570\u5fc5\u987b\u5bf9\u5e94<\/h4>\n<p>\u6240\u6709printf\u7cfb\u5217\u51fd\u6570\uff0c\u5982sprintf\uff0csnprintf\uff0cvprintf\u7b49\u5fc5\u987b\u5bf9\u5e94\u63a7\u5236\u7b26\u53f7\u548c\u53c2\u6570\u3002<\/p>\n<p>\u9519\u8bef\u793a\u4f8b\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nconst int buf_size = 1000;\nchar buffer_send_to_remote_client[buf_size] = {0};\n\nsnprintf(buffer_send_to_remote_client, buf_size, &quot;%d: %p&quot;, id, some_string);  \/\/ %p \u5e94\u4e3a %s\n\nbuffer_send_to_remote_client[buf_size - 1] = &#039;\\0&#039;;\nsend_to_remote(buffer_send_to_remote_client);<\/code><\/pre>\n<p>\u6b63\u786e\u793a\u4f8b\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nconst int buf_size = 1000;\nchar buffer_send_to_remote_client[buf_size] = {0};\n\nsnprintf(buffer_send_to_remote_client, buf_size, &quot;%d: %s&quot;, id, some_string);\n\nbuffer_send_to_remote_client[buf_size - 1] = &#039;\\0&#039;;\nsend_to_remote(buffer_send_to_remote_client);<\/code><\/pre>\n<p>\u524d\u8005\u53ef\u80fd\u4f1a\u8ba9client\u7684\u653b\u51fb\u8005\u83b7\u53d6\u90e8\u5206\u670d\u52a1\u5668\u7684\u539f\u59cb\u6307\u9488\u5730\u5740\uff0c\u53ef\u4ee5\u7528\u4e8e\u7834\u574fASLR\u4fdd\u62a4\u3002<\/p>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u4fe1\u606f\u6cc4\u9732<\/code><\/p>\n<p><a id=\"1.1.5\"><\/a><\/p>\n<h4>1.5  \u3010\u5fc5\u987b\u3011\u9632\u6b62\u6cc4\u9732\u6307\u9488\uff08\u5305\u62ec%p\uff09\u7684\u503c<\/h4>\n<p>\u6240\u6709printf\u7cfb\u5217\u51fd\u6570\uff0c\u8981\u9632\u6b62\u683c\u5f0f\u5316\u5b8c\u7684\u5b57\u7b26\u4e32\u6cc4\u9732\u7a0b\u5e8f\u5e03\u5c40\u4fe1\u606f\u3002\u4f8b\u5982\uff0c\u5982\u679c\u5c06\u5e26\u6709%p\u7684\u5b57\u7b26\u4e32\u6cc4\u9732\u7ed9\u7a0b\u5e8f\uff0c\u5219\u53ef\u80fd\u4f1a\u7834\u574fASLR\u7684\u9632\u62a4\u6548\u679c\u3002\u4f7f\u5f97\u653b\u51fb\u8005\u66f4\u5bb9\u6613\u653b\u7834\u7a0b\u5e8f\u3002<\/p>\n<p>%p\u7684\u503c\u53ea\u5e94\u5f53\u5728\u7a0b\u5e8f\u5185\u4f7f\u7528\uff0c\u800c\u4e0d\u5e94\u5f53\u8f93\u51fa\u5230\u5916\u90e8\u6216\u88ab\u5916\u90e8\u4ee5\u67d0\u79cd\u65b9\u5f0f\u83b7\u53d6\u3002<\/p>\n<p>\u9519\u8bef\u793a\u4f8b\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\n\/\/ \u5982\u679c\u8fd9\u662f\u66b4\u9732\u7ed9\u5ba2\u6237\u7684\u4e00\u4e2aAPI\uff1a\nuint64_t GetUniqueObjectId(const Foo* pobject) {\n  return (uint64_t)pobject;\n}<\/code><\/pre>\n<p>\u6b63\u786e\u793a\u4f8b\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nuint64_t g_object_id = 0;\n\nvoid Foo::Foo() {\n  this-&gt;object_id_ = g_object_id++;\n}\n\n\/\/ \u5982\u679c\u8fd9\u662f\u66b4\u9732\u7ed9\u5ba2\u6237\u7684\u4e00\u4e2aAPI\uff1a\nuint64_t GetUniqueObjectId(const Foo* object) {\n  if (object)\n    return object-&gt;object_id_;\n  else\n    error(...);\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u4fe1\u606f\u6cc4\u9732<\/code><\/p>\n<p><a id=\"1.1.6\"><\/a><\/p>\n<h4>1.6  \u3010\u5fc5\u987b\u3011\u4e0d\u5e94\u5f53\u628a\u7528\u6237\u53ef\u4fee\u6539\u7684\u5b57\u7b26\u4e32\u4f5c\u4e3aprintf\u7cfb\u5217\u51fd\u6570\u7684\u201cformat\u201d\u53c2\u6570<\/h4>\n<p>\u5982\u679c\u7528\u6237\u53ef\u4ee5\u63a7\u5236\u5b57\u7b26\u4e32\uff0c\u5219\u901a\u8fc7 %n %p \u7b49\u5185\u5bb9\uff0c\u6700\u574f\u60c5\u51b5\u4e0b\u53ef\u4ee5\u76f4\u63a5\u6267\u884c\u4efb\u610f\u6076\u610f\u4ee3\u7801\u3002<\/p>\n<p>\u5728\u4ee5\u4e0b\u60c5\u51b5\u5c24\u5176\u9700\u8981\u6ce8\u610f\uff1a WIFI\u540d\uff0c\u8bbe\u5907\u540d\u2026\u2026<\/p>\n<p>\u9519\u8bef\uff1a<\/p>\n<pre><code class=\"language-c++\">snprintf(buf, sizeof(buf), wifi_name);<\/code><\/pre>\n<p>\u6b63\u786e\uff1a<\/p>\n<pre><code class=\"language-c++\">snprinf(buf, sizeof(buf), &quot;%s&quot;, wifi_name);<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u4ee3\u7801\u6267\u884c<\/code><\/p>\n<p><code>\u9ad8\u98ce\u9669-\u5185\u5b58\u7834\u574f<\/code><\/p>\n<p><code>\u4e2d\u98ce\u9669-\u4fe1\u606f\u6cc4\u9732<\/code><\/p>\n<p><code>\u4f4e\u98ce\u9669-\u62d2\u7edd\u670d\u52a1<\/code><\/p>\n<p><a id=\"1.1.7\"><\/a><\/p>\n<h4>1.7 \u3010\u5fc5\u987b\u3011\u5bf9\u6570\u7ec4delete\u65f6\u9700\u8981\u4f7f\u7528delete[]<\/h4>\n<p>delete []\u64cd\u4f5c\u7b26\u7528\u4e8e\u5220\u9664\u6570\u7ec4\u3002delete\u64cd\u4f5c\u7b26\u7528\u4e8e\u5220\u9664\u975e\u6570\u7ec4\u5bf9\u8c61\u3002\u5b83\u4eec\u5206\u522b\u8c03\u7528operator delete[]\u548coperator delete\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nFoo* b = new Foo[5];\ndelete b;  \/\/ trigger assert in DEBUG mode<\/code><\/pre>\n<p>\u5728new[]\u8fd4\u56de\u7684\u6307\u9488\u4e0a\u8c03\u7528delete\u5c06\u662f\u53d6\u51b3\u4e8e\u7f16\u8bd1\u5668\u7684\u672a\u5b9a\u4e49\u884c\u4e3a\u3002\u4ee3\u7801\u4e2d\u5b58\u5728\u5bf9\u672a\u5b9a\u4e49\u884c\u4e3a\u7684\u4f9d\u8d56\u662f\u9519\u8bef\u7684\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nFoo* b = new Foo[5];\ndelete[] b;<\/code><\/pre>\n<p>\u5728 C++ \u4ee3\u7801\u4e2d\uff0c\u4f7f\u7528 <code>string<\/code>\u3001<code>vector<\/code>\u3001\u667a\u80fd\u6307\u9488\uff08\u6bd4\u5982<a href=\"https:\/\/zh.cppreference.com\/w\/cpp\/memory\/unique_ptr\">std::unique_ptr&lt;T[]&gt;<\/a>\uff09\u7b49\u53ef\u4ee5\u6d88\u9664\u7edd\u5927\u591a\u6570 <code>delete[]<\/code> \u7684\u4f7f\u7528\u573a\u666f\uff0c\u5e76\u4e14\u4ee3\u7801\u66f4\u6e05\u6670\u3002<\/p>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u5185\u5b58\u7834\u574f<\/code><\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u6f0f\u6d1e<\/code><\/p>\n<p><code>\u4f4e\u98ce\u9669-\u5185\u5b58\u6cc4\u6f0f<\/code><\/p>\n<p><code>\u4f4e\u98ce\u9669-\u62d2\u7edd\u670d\u52a1<\/code><\/p>\n<p><a id=\"1.1.8\"><\/a><\/p>\n<h4>1.8\u3010\u5fc5\u987b\u3011\u6ce8\u610f\u9690\u5f0f\u7b26\u53f7\u8f6c\u6362<\/h4>\n<p>\u4e24\u4e2a\u65e0\u7b26\u53f7\u6570\u76f8\u51cf\u4e3a\u8d1f\u6570\u65f6\uff0c\u7ed3\u679c\u5e94\u5f53\u4e3a\u4e00\u4e2a\u5f88\u5927\u7684\u65e0\u7b26\u53f7\u6570\uff0c\u4f46\u662f\u5c0f\u4e8eint\u7684\u65e0\u7b26\u53f7\u6570\u5728\u8fd0\u7b97\u65f6\u53ef\u80fd\u4f1a\u6709\u9884\u671f\u5916\u7684\u9690\u5f0f\u7b26\u53f7\u8f6c\u6362\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ 1\nunsigned char a = 1;\nunsigned char b = 2;\n\nif (a - b &lt; 0)  \/\/ a - b = -1 (signed int)\n  a = 6;\nelse\n  a = 8;\n\n\/\/ 2\nunsigned char a = 1;\nunsigned short b = 2;\n\nif (a - b &lt; 0)  \/\/ a - b = -1 (signed int)\n  a = 6;\nelse\n  a = 8;<\/code><\/pre>\n<p>\u4e0a\u8ff0\u7ed3\u679c\u5747\u4e3aa=6<\/p>\n<pre><code class=\"language-c++\">\/\/ 3\nunsigned int a = 1;\nunsigned short b = 2;\n\nif (a - b &lt; 0)  \/\/ a - b = 0xffffffff (unsigned int)\n  a = 6;\nelse\n  a = 8;\n\n\/\/ 4\nunsigned int a = 1;\nunsigned int b = 2;\n\nif (a - b &lt; 0)  \/\/ a - b = 0xffffffff (unsigned int)\n  a = 6;\nelse\n  a = 8;<\/code><\/pre>\n<p>\u4e0a\u8ff0\u7ed3\u679c\u5747\u4e3aa=8<\/p>\n<p>\u5982\u679c\u9884\u671f\u4e3a8\uff0c\u5219\u9519\u8bef\u4ee3\u7801\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nunsigned short a = 1;\nunsigned short b = 2;\n\nif (a - b &lt; 0)  \/\/ a - b = -1 (signed int)\n  a = 6;\nelse\n  a = 8;<\/code><\/pre>\n<p>\u6b63\u786e\u4ee3\u7801\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nunsigned short a = 1;\nunsigned short b = 2;\n\nif ((unsigned int)a - (unsigned int)b &lt; 0)  \/\/ a - b = 0xffff (unsigned short)\n  a = 6;\nelse\n  a = 8;<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u6f0f\u6d1e<\/code><\/p>\n<p><a id=\"1.1.9\"><\/a><\/p>\n<h4>1.9\u3010\u5fc5\u987b\u3011\u6ce8\u610f\u516b\u8fdb\u5236\u95ee\u9898<\/h4>\n<p>\u4ee3\u7801\u5bf9\u9f50\u65f6\u5e94\u5f53\u4f7f\u7528\u7a7a\u683c\u6216\u8005\u7f16\u8f91\u5668\u81ea\u5e26\u7684\u5bf9\u9f50\u529f\u80fd\uff0c\u8c28\u614e\u5728\u6570\u5b57\u524d\u4f7f\u75280\u6765\u5bf9\u9f50\u4ee3\u7801\uff0c\u4ee5\u514d\u4e0d\u5f53\u5c06\u67d0\u4e9b\u5185\u5bb9\u8f6c\u6362\u4e3a\u516b\u8fdb\u5236\u3002<\/p>\n<p>\u4f8b\u5982\uff0c\u5982\u679c\u9884\u671f\u4e3a20\u5b57\u8282\u957f\u5ea6\u7684\u7f13\u51b2\u533a\uff0c\u5219\u4e0b\u5217\u4ee3\u7801\u5b58\u5728\u9519\u8bef\u3002buf2\u4e3a020\uff08OCT\uff09\u957f\u5ea6\uff0c\u5b9e\u9645\u53ea\u670916\uff08DEC\uff09\u957f\u5ea6\uff0c\u5728memcpy\u540e\u8d8a\u754c\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nchar buf1[1024] = {0};\nchar buf2[0020] = {0};\n\nmemcpy(buf2, somebuf, 19);<\/code><\/pre>\n<p>\u5e94\u5f53\u5728\u4f7f\u75288\u8fdb\u5236\u65f6\u660e\u786e\u6ce8\u660e\u8fd9\u662f\u516b\u8fdb\u5236\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nint access_mask = 0777;  \/\/ oct, rwxrwxrwx<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u6f0f\u6d1e<\/code><\/p>\n<p><a id=\"1.2\"><\/a><\/p>\n<h3>2 \u4e0d\u63a8\u8350\u7684\u7f16\u7a0b\u4e60\u60ef<\/h3>\n<p><a id=\"1.2.1\"><\/a><\/p>\n<h4>2.1 \u3010\u5fc5\u987b\u3011switch\u4e2d\u5e94\u6709default<\/h4>\n<p>switch\u4e2d\u5e94\u8be5\u6709default\uff0c\u4ee5\u5904\u7406\u5404\u79cd\u9884\u671f\u5916\u7684\u60c5\u51b5\u3002\u8fd9\u53ef\u4ee5\u786e\u4fddswitch\u63a5\u53d7\u7528\u6237\u8f93\u5165\uff0c\u6216\u8005\u540e\u671f\u5728\u5176\u4ed6\u5f00\u53d1\u8005\u4fee\u6539\u51fd\u6570\u540e\u786e\u4fddswitch\u4ecd\u53ef\u4ee5\u8986\u76d6\u5230\u6240\u6709\u60c5\u51b5\uff0c\u5e76\u786e\u4fdd\u903b\u8f91\u6b63\u5e38\u8fd0\u884c\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nint Foo(int bar) {\n  switch (bar &amp; 7) {\n    case 0:\n      return Foobar(bar);\n      break;\n    case 1:\n      return Foobar(bar * 2);\n      break;\n  }\n}<\/code><\/pre>\n<p>\u4f8b\u5982\u4e0a\u8ff0\u4ee3\u7801switch\u7684\u53d6\u503c\u53ef\u80fd\u4ece0\uff5e7\uff0c\u6240\u4ee5\u5e94\u5f53\u6709default\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nint Foo(int bar) {\n  switch (bar &amp; 7) {\n    case 0:\n      return Foobar(bar);\n      break;\n    case 1:\n      return Foobar(bar * 2);\n      break;\n    default:\n      return -1;\n  }\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u6f0f\u6d1e<\/code><\/p>\n<p><code>\u4e2d\u98ce\u9669-\u5185\u5b58\u6cc4\u6f0f<\/code><\/p>\n<p><a id=\"1.2.2\"><\/a><\/p>\n<h4>2.2 \u3010\u5fc5\u987b\u3011\u4e0d\u5e94\u5f53\u5728Debug\u6216\u9519\u8bef\u4fe1\u606f\u4e2d\u63d0\u4f9b\u8fc7\u591a\u5185\u5bb9<\/h4>\n<p>\u5305\u542b\u8fc7\u591a\u4fe1\u606f\u7684Debug\u6d88\u606f\u4e0d\u5e94\u5f53\u88ab\u7528\u6237\u83b7\u53d6\u5230\u3002Debug\u4fe1\u606f\u53ef\u80fd\u4f1a\u6cc4\u9732\u4e00\u4e9b\u503c\uff0c\u4f8b\u5982\u5185\u5b58\u6570\u636e\u3001\u5185\u5b58\u5730\u5740\u7b49\u5185\u5bb9\uff0c\u8fd9\u4e9b\u5185\u5bb9\u53ef\u4ee5\u5e2e\u52a9\u653b\u51fb\u8005\u5728\u521d\u6b65\u63a7\u5236\u7a0b\u5e8f\u540e\uff0c\u66f4\u5bb9\u6613\u5730\u653b\u51fb\u7a0b\u5e8f\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nint Foo(int* bar) {\n  if (bar &amp;&amp; *bar == 5) {\n    OutputDebugInfoToUser(&quot;Wrong value for bar %p = %d\\n&quot;, bar, *bar);\n  }\n}<\/code><\/pre>\n<p>\u800c\u5e94\u8be5\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nint foo(int* bar) {\n\n#ifdef DEBUG\n  if (bar &amp;&amp; *bar == 5) {\n    OutputDebugInfo(&quot;Wrong value for bar.\\n&quot;);\n  }\n#endif\n\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u4fe1\u606f\u6cc4\u6f0f<\/code><\/p>\n<p><a id=\"1.2.3\"><\/a><\/p>\n<h4>2.3 \u3010\u5fc5\u987b\u3011\u4e0d\u5e94\u8be5\u5728\u5ba2\u6237\u7aef\u4ee3\u7801\u4e2d\u786c\u7f16\u7801\u5bf9\u79f0\u52a0\u5bc6\u79d8\u94a5<\/h4>\n<p>\u4e0d\u5e94\u8be5\u5728\u5ba2\u6237\u7aef\u4ee3\u7801\u4e2d\u786c\u7f16\u7801\u5bf9\u79f0\u52a0\u5bc6\u79d8\u94a5\u3002\u4f8b\u5982\uff1a\u4e0d\u5e94\u5728\u5ba2\u6237\u7aef\u4ee3\u7801\u4f7f\u7528\u786c\u7f16\u7801\u7684 AES\/ChaCha20-Poly1305\/SM1 \u5bc6\u94a5\uff0c\u4f7f\u7528\u56fa\u5b9a\u5bc6\u94a5\u7684\u7a0b\u5e8f\u57fa\u672c\u548c\u6ca1\u6709\u52a0\u5bc6\u4e00\u6837\u3002<\/p>\n<p>\u5982\u679c\u4e1a\u52a1\u9700\u6c42\u662f\u8ba4\u8bc1\u52a0\u5bc6\u6570\u636e\u4f20\u8f93\uff0c\u5e94\u4f18\u5148\u8003\u8651\u76f4\u63a5\u7528 HTTPS \u534f\u8bae\u3002<\/p>\n<p>\u5982\u679c\u662f\u5176\u5b83\u4e1a\u52a1\u9700\u6c42\uff0c\u53ef\u8003\u8651\u7531\u670d\u52a1\u5668\u7aef\u751f\u6210\u5bf9\u79f0\u79d8\u94a5\uff0c\u5ba2\u6237\u7aef\u901a\u8fc7 HTTPS \u7b49\u8ba4\u8bc1\u52a0\u5bc6\u901a\u4fe1\u6e20\u9053\u4ece\u670d\u52a1\u5668\u62c9\u53d6\u3002<\/p>\n<p>\u6216\u8005\u6839\u636e\u7528\u6237\u7279\u5b9a\u7684\u4f1a\u8bdd\u4fe1\u606f\uff0c\u6bd4\u5982\u767b\u5f55\u8ba4\u8bc1\u8fc7\u7a0b\u53ef\u4ee5\u6839\u636e\u7528\u6237\u540d\u7528\u6237\u5bc6\u7801\u4e1a\u52a1\u4e0a\u4e0b\u6587\u7b49\u4fe1\u606f\uff0c\u4f7f\u7528 HKDF \u7b49\u7b97\u6cd5\u884d\u751f\u51fa\u5bf9\u79f0\u79d8\u94a5\u3002<\/p>\n<p>\u53c8\u6216\u8005\u4f7f\u7528 RSA\/ECDSA + ECDHE \u7b49\u8fdb\u884c\u8ba4\u8bc1\u79d8\u94a5\u534f\u5546\uff0c\u751f\u6210\u5bf9\u79f0\u79d8\u94a5\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nchar g_aes_key[] = {...};\n\nvoid Foo() {\n  ....\n  AES_func(g_aes_key, input_data, output_data);\n}<\/code><\/pre>\n<p>\u53ef\u4ee5\u8003\u8651\u5728\u7ebf\u4e3a\u6bcf\u4e2a\u7528\u6237\u83b7\u53d6\u4e0d\u540c\u7684\u5bc6\u94a5\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nchar* g_aes_key;\n\nvoid Foo() {\n  ....\n  AES_encrypt(g_aes_key, input_data, output_data);\n}\n\nvoid Init() {\n  g_aes_key = get_key_from_https(user_id, ...);\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u4fe1\u606f\u6cc4\u9732<\/code><\/p>\n<p><a id=\"1.2.4\"><\/a><\/p>\n<h4>2.4 \u3010\u5fc5\u987b\u3011\u8fd4\u56de\u6808\u4e0a\u53d8\u91cf\u7684\u5730\u5740<\/h4>\n<p>\u51fd\u6570\u4e0d\u53ef\u4ee5\u8fd4\u56de\u6808\u4e0a\u7684\u53d8\u91cf\u7684\u5730\u5740\uff0c\u5176\u5185\u5bb9\u5728\u51fd\u6570\u8fd4\u56de\u540e\u5c31\u4f1a\u5931\u6548\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nchar* Foo(char* sz, int len){\n  char a[300] = {0};\n  if (len &gt; 100) {\n    memcpy(a, sz, 100);\n  }\n  a[len] = &#039;\\0&#039;;\n  return a;  \/\/ WRONG\n}<\/code><\/pre>\n<p>\u800c\u5e94\u5f53\u4f7f\u7528\u5806\u6765\u4f20\u9012\u975e\u7b80\u5355\u7c7b\u578b\u53d8\u91cf\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nchar* Foo(char* sz, int len) {\n    char* a = new char[300];\n    if (len &gt; 100) {\n        memcpy(a, sz, 100);\n    }\n    a[len] = &#039;\\0&#039;;\n    return a;  \/\/ OK\n}<\/code><\/pre>\n<p>\u5bf9\u4e8e C++ \u7a0b\u5e8f\u6765\u8bf4\uff0c\u5f3a\u70c8\u5efa\u8bae\u8fd4\u56de <code>string<\/code>\u3001<code>vector<\/code> \u7b49\u7c7b\u578b\uff0c\u4f1a\u8ba9\u4ee3\u7801\u66f4\u52a0\u7b80\u5355\u548c\u5b89\u5168\u3002<\/p>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u5185\u5b58\u7834\u574f<\/code><\/p>\n<p><a id=\"1.2.5\"><\/a><\/p>\n<h4>2.5 \u3010\u5fc5\u987b\u3011\u6709\u903b\u8f91\u8054\u7cfb\u7684\u6570\u7ec4\u5fc5\u987b\u4ed4\u7ec6\u68c0\u67e5<\/h4>\n<p>\u4f8b\u5982\u4e0b\u5217\u7a0b\u5e8f\u5c06\u5b57\u7b26\u4e32\u8f6c\u6362\u4e3aweek day\uff0c\u4f46\u662f\u4e24\u4e2a\u6570\u7ec4\u5e76\u4e0d\u4e00\u6837\u957f\uff0c\u5bfc\u81f4\u7a0b\u5e8f\u53ef\u80fd\u4f1a\u8d8a\u754c\u8bfb\u4e00\u4e2aint\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nint nWeekdays[] = {1, 2, 3, 4, 5, 6};\nconst char* sWeekdays[] = {&quot;Mon&quot;, &quot;Tue&quot;, &quot;Wed&quot;, &quot;Thu&quot;, &quot;Fri&quot;, &quot;Sat&quot;, &quot;Sun&quot;};\nfor (int x = 0; x &lt; ARRAY_SIZE(sWeekdays); x++) {\n  if (strcmp(sWeekdays[x], input) == 0)\n    return nWeekdays[x];\n}<\/code><\/pre>\n<p>\u5e94\u5f53\u786e\u4fdd\u6709\u5173\u8054\u7684nWeekdays\u548csWeekdays\u6570\u636e\u7edf\u4e00\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nconst int nWeekdays[] = {1, 2, 3, 4, 5, 6, 7};\nconst char* sWeekdays[] = {&quot;Mon&quot;, &quot;Tue&quot;, &quot;Wed&quot;, &quot;Thu&quot;, &quot;Fri&quot;, &quot;Sat&quot;, &quot;Sun&quot;};\nassert(ARRAY_SIZE(nWeekdays) == ARRAY_SIZE(sWeekdays));\nfor (int x = 0; x &lt; ARRAY_SIZE(sWeekdays); x++) {\n  if (strcmp(sWeekdays[x], input) == 0) {\n    return nWeekdays[x];\n  }\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u5185\u5b58\u7834\u574f<\/code><\/p>\n<p><a id=\"1.2.6\"><\/a><\/p>\n<h4>2.6 \u3010\u5fc5\u987b\u3011\u907f\u514d\u51fd\u6570\u7684\u58f0\u660e\u548c\u5b9e\u73b0\u4e0d\u540c<\/h4>\n<p>\u5728\u5934\u6587\u4ef6\u3001\u6e90\u4ee3\u7801\u3001\u6587\u6863\u4e2d\u5217\u4e3e\u7684\u51fd\u6570\u58f0\u660e\u5e94\u5f53\u4e00\u81f4\uff0c\u4e0d\u5e94\u5f53\u51fa\u73b0\u5b9a\u4e49\u5185\u5bb9\u9519\u4f4d\u7684\u60c5\u51b5\u3002<\/p>\n<p>\u9519\u8bef\uff1a<\/p>\n<p>foo.h<\/p>\n<pre><code class=\"language-c++\">int CalcArea(int width, int height);<\/code><\/pre>\n<p>foo.cc<\/p>\n<pre><code class=\"language-c++\">int CalcArea(int height, int width) {  \/\/ Different from foo.h\n  if (height &gt; real_height) {\n    return 0;\n  }\n  return height * width;\n}<\/code><\/pre>\n<p>\u6b63\u786e\uff1a<br \/>\nfoo.h<\/p>\n<pre><code class=\"language-c++\">int CalcArea(int height, int width);<\/code><\/pre>\n<p>foo.cc<\/p>\n<pre><code class=\"language-c++\">int CalcArea (int height, int width) {\n  if (height &gt; real_height) {\n    return 0;\n  }\n  return height * width;\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u95ee\u9898<\/code><\/p>\n<p><a id=\"1.2.7\"><\/a><\/p>\n<h4>2.7 \u3010\u5fc5\u987b\u3011\u68c0\u67e5\u590d\u5236\u7c98\u8d34\u7684\u91cd\u590d\u4ee3\u7801\uff08\u76f8\u540c\u4ee3\u7801\u901a\u5e38\u4ee3\u8868\u9519\u8bef\uff09<\/h4>\n<p>\u5f53\u5f00\u53d1\u4e2d\u9047\u5230\u8f83\u957f\u7684\u53e5\u5b50\u65f6\uff0c\u5982\u679c\u4f60\u9009\u62e9\u4e86\u590d\u5236\u7c98\u8d34\u8bed\u53e5\uff0c\u8bf7\u8bb0\u5f97\u68c0\u67e5\u6bcf\u4e00\u884c\u4ee3\u7801\uff0c\u4e0d\u8981\u51fa\u73b0\u4e0a\u4e0b\u4e24\u53e5\u4e00\u6a21\u4e00\u6837\u7684\u60c5\u51b5\uff0c\u8fd9\u901a\u5e38\u4ee3\u8868\u4ee3\u7801\u54ea\u91cc\u51fa\u73b0\u4e86\u9519\u8bef\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nvoid Foobar(SomeStruct&amp; foobase, SomeStruct&amp; foo1, SomeStruct&amp; foo2) {\n  foo1.bar = (foo1.bar &amp; 0xffff) | (foobase.base &amp; 0xffff0000);\n  foo1.bar = (foo1.bar &amp; 0xffff) | (foobase.base &amp; 0xffff0000);\n}<\/code><\/pre>\n<p>\u5982\u4e0a\u4f8b\uff0c\u901a\u5e38\u53ef\u80fd\u662f\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nvoid Foobar(SomeStruct&amp; foobase, SomeStruct&amp; foo1, SomeStruct&amp; foo2) {\n  foo1.bar = (foo1.bar &amp; 0xffff) | (foobase.base &amp; 0xffff0000);\n  foo2.bar = (foo2.bar &amp; 0xffff) | (foobase.base &amp; 0xffff0000);\n}\n<\/code><\/pre>\n<p>\u6700\u597d\u662f\u628a\u91cd\u590d\u7684\u4ee3\u7801\u7247\u6bb5\u63d0\u53d6\u6210\u51fd\u6570\uff0c\u5982\u679c\u51fd\u6570\u6bd4\u8f83\u77ed\uff0c\u53ef\u4ee5\u8003\u8651\u5b9a\u4e49\u4e3a <code>inline<\/code> \u51fd\u6570\uff0c\u5728\u51cf\u5c11\u5197\u4f59\u7684\u540c\u65f6\u4e5f\u80fd\u786e\u4fdd\u4e0d\u4f1a\u5f71\u54cd\u6027\u80fd\u3002<\/p>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u95ee\u9898<\/code><\/p>\n<p><a id=\"1.2.8\"><\/a><\/p>\n<h4>2.8  \u3010\u5fc5\u987b\u3011\u5de6\u53f3\u4e00\u81f4\u7684\u91cd\u590d\u5224\u65ad\/\u6c38\u8fdc\u4e3a\u771f\u6216\u5047\u7684\u5224\u65ad\uff08\u901a\u5e38\u4ee3\u8868\u9519\u8bef\uff09<\/h4>\n<p>\u8fd9\u901a\u5e38\u662f\u7531\u4e8e\u81ea\u52a8\u5b8c\u6210\u6216\u4f8b\u5982Visual Assistant X\u4e4b\u7c7b\u7684\u8865\u5168\u63d2\u4ef6\u5bfc\u81f4\u7684\u95ee\u9898\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nif (foo1.bar == foo1.bar) {\n  \u2026\n}<\/code><\/pre>\n<p>\u53ef\u80fd\u662f\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nif (foo1.bar == foo2.bar) {\n  \u2026\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u95ee\u9898<\/code><\/p>\n<p><a id=\"1.2.9\"><\/a><\/p>\n<h4>2.9 \u3010\u5fc5\u987b\u3011\u51fd\u6570\u6bcf\u4e2a\u5206\u652f\u90fd\u5e94\u6709\u8fd4\u56de\u503c<\/h4>\n<p>\u51fd\u6570\u7684\u6bcf\u4e2a\u5206\u652f\u90fd\u5e94\u8be5\u6709\u8fd4\u56de\u503c\uff0c\u5426\u5219\u5982\u679c\u51fd\u6570\u8d70\u5230\u65e0\u8fd4\u56de\u503c\u7684\u5206\u652f\uff0c\u5176\u7ed3\u679c\u662f\u672a\u77e5\u7684\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nint Foo(int bar) {\n  if (bar &gt; 100) {\n    return 10;\n  } else if (bar &gt; 10) {\n    return 1;\n  }\n}<\/code><\/pre>\n<p>\u4e0a\u8ff0\u4f8b\u5b50\u5f53bar&lt;10\u65f6\uff0c\u5176\u7ed3\u679c\u662f\u672a\u77e5\u7684\u503c\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nint Foo(int bar) {\n  if (bar &gt; 100) {\n    return 10;\n  } else if (bar &gt; 10) {\n    return 1;\n  }\n  return 0;\n}<\/code><\/pre>\n<p>\u5f00\u542f\u9002\u5f53\u7ea7\u522b\u7684\u8b66\u544a\uff08GCC \u4e2d\u4e3a <code>-Wreturn-type<\/code> \u5e76\u5df2\u5305\u542b\u5728 <code>-Wall<\/code> \u4e2d\uff09\u5e76\u8bbe\u7f6e\u4e3a\u9519\u8bef\uff0c\u53ef\u4ee5\u5728\u7f16\u8bd1\u9636\u6bb5\u53d1\u73b0\u8fd9\u7c7b\u9519\u8bef\u3002<\/p>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u95ee\u9898<\/code><\/p>\n<p><code>\u4e2d\u98ce\u9669-\u4fe1\u606f\u6cc4\u6f0f<\/code><\/p>\n<p><a id=\"1.2.10\"><\/a><\/p>\n<h4>2.10 \u3010\u5fc5\u987b\u3011\u4e0d\u5f97\u4f7f\u7528\u6808\u4e0a\u672a\u521d\u59cb\u5316\u7684\u53d8\u91cf<\/h4>\n<p>\u5728\u6808\u4e0a\u58f0\u660e\u7684\u53d8\u91cf\u8981\u6ce8\u610f\u662f\u5426\u5728\u4f7f\u7528\u5b83\u4e4b\u524d\u5df2\u7ecf\u521d\u59cb\u5316\u4e86<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nvoid Foo() {\n  int foo;\n  if (Bar()) {\n    foo = 1;\n  }\n  Foobar(foo); \/\/ foo\u53ef\u80fd\u6ca1\u6709\u521d\u59cb\u5316\n}<\/code><\/pre>\n<p>\u6700\u597d\u5728\u58f0\u660e\u7684\u65f6\u5019\u5c31\u7acb\u523b\u521d\u59cb\u5316\u53d8\u91cf\uff0c\u6216\u8005\u786e\u4fdd\u6bcf\u4e2a\u5206\u652f\u90fd\u521d\u59cb\u5316\u5b83\u3002\u5f00\u542f\u76f8\u5e94\u7684\u7f16\u8bd1\u5668\u8b66\u544a\uff08GCC \u4e2d\u4e3a <code>-Wuninitialized<\/code>\uff09\uff0c\u5e76\u628a\u8bbe\u7f6e\u4e3a\u9519\u8bef\u7ea7\u522b\uff0c\u53ef\u4ee5\u5728\u7f16\u8bd1\u9636\u6bb5\u53d1\u73b0\u8fd9\u7c7b\u9519\u8bef\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nvoid Foo() {\n  int foo = 0;\n  if (Bar()) {\n    foo = 1;\n  }\n  Foobar(foo);\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u95ee\u9898<\/code><\/p>\n<p><code>\u4e2d\u98ce\u9669-\u4fe1\u606f\u6cc4\u6f0f<\/code><\/p>\n<p><a id=\"1.2.11\"><\/a><\/p>\n<h4>2.11  \u3010\u5efa\u8bae\u3011\u4e0d\u5f97\u76f4\u63a5\u4f7f\u7528\u521a\u5206\u914d\u7684\u672a\u521d\u59cb\u5316\u7684\u5185\u5b58\uff08\u5982realloc\uff09<\/h4>\n<p>\u4e00\u4e9b\u521a\u7533\u8bf7\u7684\u5185\u5b58\u901a\u5e38\u662f\u76f4\u63a5\u4ece\u5806\u4e0a\u5206\u914d\u7684\uff0c\u53ef\u80fd\u5305\u542b\u6709\u65e7\u6570\u636e\u7684\uff0c\u76f4\u63a5\u4f7f\u7528\u5b83\u4eec\u800c\u4e0d\u521d\u59cb\u5316\uff0c\u53ef\u80fd\u4f1a\u5bfc\u81f4\u5b89\u5168\u95ee\u9898\u3002\u4f8b\u5982\uff0cCVE-2019-13751\u3002\u5e94\u786e\u4fdd\u521d\u59cb\u5316\u53d8\u91cf\uff0c\u6216\u8005\u786e\u4fdd\u672a\u521d\u59cb\u5316\u7684\u503c\u4e0d\u4f1a\u6cc4\u9732\u7ed9\u7528\u6237\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nchar* Foo() {\n  char* a = new char[100];\n  a[99] = &#039;\\0&#039;;\n  memcpy(a, &quot;char&quot;, 4);\n  return a;\n}<\/code><\/pre>\n<pre><code class=\"language-c++\">\/\/ Good\nchar* Foo() {\n  char* a = new char[100];\n  memcpy(a, &quot;char&quot;, 4);\n  a[4] = &#039;\\0&#039;;\n  return a;\n}<\/code><\/pre>\n<p>\u5728 C++ \u4e2d\uff0c\u518d\u6b21\u5f3a\u70c8\u63a8\u8350\u7528 <code>string<\/code>\u3001<code>vector<\/code> \u4ee3\u66ff\u624b\u52a8\u5185\u5b58\u5206\u914d\u3002<\/p>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u95ee\u9898<\/code><\/p>\n<p><code>\u4e2d\u98ce\u9669-\u4fe1\u606f\u6cc4\u6f0f<\/code><\/p>\n<p><a id=\"1.2.12\"><\/a><\/p>\n<h4>2.12 \u3010\u5fc5\u987b\u3011\u6821\u9a8c\u5185\u5b58\u76f8\u5173\u51fd\u6570\u7684\u8fd4\u56de\u503c<\/h4>\n<p>\u4e0e\u5185\u5b58\u5206\u914d\u76f8\u5173\u7684\u51fd\u6570\u9700\u8981\u68c0\u67e5\u5176\u8fd4\u56de\u503c\u662f\u5426\u6b63\u786e\uff0c\u4ee5\u9632\u5bfc\u81f4\u7a0b\u5e8f\u5d29\u6e83\u6216\u903b\u8f91\u9519\u8bef\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nvoid Foo() {\n  char* bar = mmap(0, 0x800000, .....);\n  *(bar + 0x400000) = &#039;\\x88&#039;; \/\/ Wrong\n}\n<\/code><\/pre>\n<p>\u5982\u4e0a\u4f8bmmap\u5982\u679c\u5931\u8d25\uff0cbar\u7684\u503c\u5c06\u662f0xffffffff (ffffffff)\uff0c\u7b2c\u4e8c\u884c\u5c06\u4f1a\u5f800x3ffffff\u5199\u5165\u5b57\u7b26\uff0c\u5bfc\u81f4\u8d8a\u754c\u5199\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nvoid Foo() {\n  char* bar = mmap(0, 0x800000, .....);\n  if(bar == MAP_FAILED) {\n    return;\n  }\n\n  *(bar + 0x400000) = &#039;\\x88&#039;;\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u95ee\u9898<\/code><\/p>\n<p><code>\u9ad8\u98ce\u9669-\u8d8a\u754c\u64cd\u4f5c<\/code><\/p>\n<p><a id=\"1.2.13\"><\/a><\/p>\n<h4>2.13 \u3010\u5fc5\u987b\u3011\u4e0d\u8981\u5728if\u91cc\u9762\u8d4b\u503c<\/h4>\n<p>if\u91cc\u8d4b\u503c\u901a\u5e38\u4ee3\u8868\u4ee3\u7801\u5b58\u5728\u9519\u8bef\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nvoid Foo() {\n  if (bar = 0x99) ...\n}<\/code><\/pre>\n<p>\u901a\u5e38\u5e94\u8be5\u662f\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nvoid Foo() {\n  if (bar == 0x99) ...\n}<\/code><\/pre>\n<p>\u5efa\u8bae\u5728\u6784\u5efa\u7cfb\u7edf\u4e2d\u5f00\u542f\u8db3\u591f\u7684\u7f16\u8bd1\u5668\u8b66\u544a\uff08GCC \u4e2d\u4e3a <code>-Wparentheses<\/code> \u5e76\u5df2\u5305\u542b\u5728 <code>-Wall<\/code> \u4e2d\uff09\uff0c\u5e76\u628a\u8be5\u8b66\u544a\u8bbe\u7f6e\u4e3a\u9519\u8bef\u3002<\/p>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u95ee\u9898<\/code><\/p>\n<p><a id=\"1.2.14\"><\/a><\/p>\n<h4>2.14 \u3010\u5efa\u8bae\u3011\u786e\u8ba4if\u91cc\u9762\u7684\u6309\u4f4d\u64cd\u4f5c<\/h4>\n<p>if\u91cc\uff0c\u975ebool\u7c7b\u578b\u548c\u975ebool\u7c7b\u578b\u7684\u6309\u4f4d\u64cd\u4f5c\u53ef\u80fd\u4ee3\u8868\u4ee3\u7801\u5b58\u5728\u9519\u8bef\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nvoid Foo() {\n  int bar = 0x1;     \/\/ binary 01\n  int foobar = 0x2;    \/\/ binary 10\n\n  if (foobar &amp; bar)     \/\/ result = 00, false\n    ...\n}<\/code><\/pre>\n<p>\u4e0a\u8ff0\u4ee3\u7801\u53ef\u80fd\u5e94\u8be5\u662f\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nvoid foo() {\n  int   bar = 0x1;\n  int foobar = 0x2;\n\n  if (foobar &amp;&amp; bar)  \/\/ result : true\n    ...\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u95ee\u9898<\/code><\/p>\n<p><a id=\"1.3\"><\/a><\/p>\n<h3>3    \u591a\u7ebf\u7a0b<\/h3>\n<p><a id=\"1.3.1\"><\/a><\/p>\n<h4>3.1  \u3010\u5fc5\u987b\u3011\u53d8\u91cf\u5e94\u786e\u4fdd\u7ebf\u7a0b\u5b89\u5168\u6027<\/h4>\n<p>\u5f53\u4e00\u4e2a\u53d8\u91cf\u53ef\u80fd\u88ab\u591a\u4e2a\u7ebf\u7a0b\u4f7f\u7528\u65f6\uff0c\u5e94\u5f53\u4f7f\u7528\u539f\u5b50\u64cd\u4f5c\u6216\u52a0\u9501\u64cd\u4f5c\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nchar  g_somechar;\nvoid foo_thread1() {\n  g_somechar += 3;\n}\n\nvoid foo_thread2() {\n  g_somechar += 1;\n}<\/code><\/pre>\n<p>\u5bf9\u4e8e\u53ef\u4ee5\u4f7f\u7528\u539f\u5b50\u64cd\u4f5c\u7684\uff0c\u5e94\u5f53\u4f7f\u7528\u4e00\u4e9b\u53ef\u4ee5\u786e\u4fdd\u5185\u5b58\u5b89\u5168\u7684\u64cd\u4f5c\uff0c\u5982\uff1a<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nvolatile char g_somechar;\nvoid foo_thread1() {\n  __sync_fetch_and_add(&amp;g_somechar, 3);\n}\n\nvoid foo_thread2() {\n  __sync_fetch_and_add(&amp;g_somechar, 1);\n}<\/code><\/pre>\n<p>\u5bf9\u4e8e C \u4ee3\u7801\uff0c<code>C11<\/code> \u540e\u63a8\u8350\u4f7f\u7528 <a href=\"https:\/\/en.cppreference.com\/w\/c\/atomic\">atomic<\/a> \u6807\u51c6\u5e93\u3002<br \/>\n\u5bf9\u4e8e C++\u4ee3\u7801\uff0c<code>C++11<\/code> \u540e\uff0c\u63a8\u8350\u4f7f\u7528 <a href=\"https:\/\/zh.cppreference.com\/w\/cpp\/atomic\/atomic\"><code>std::atomic<\/code><\/a>\u3002<\/p>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u5185\u5b58\u7834\u574f<\/code><\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u95ee\u9898<\/code><\/p>\n<p><a id=\"1.3.2\"><\/a><\/p>\n<h4>3.2 \u3010\u5fc5\u987b\u3011\u6ce8\u610fsignal handler\u5bfc\u81f4\u7684\u6761\u4ef6\u7ade\u4e89<\/h4>\n<p>\u7ade\u4e89\u6761\u4ef6\u7ecf\u5e38\u51fa\u73b0\u5728\u4fe1\u53f7\u5904\u7406\u7a0b\u5e8f\u4e2d\uff0c\u56e0\u4e3a\u4fe1\u53f7\u5904\u7406\u7a0b\u5e8f\u652f\u6301\u5f02\u6b65\u64cd\u4f5c\u3002\u653b\u51fb\u8005\u80fd\u591f\u5229\u7528\u4fe1\u53f7\u5904\u7406\u7a0b\u5e8f\u4e89\u7528\u6761\u4ef6\u5bfc\u81f4\u8f6f\u4ef6\u72b6\u6001\u635f\u574f\uff0c\u4ece\u800c\u53ef\u80fd\u5bfc\u81f4\u62d2\u7edd\u670d\u52a1\u751a\u81f3\u4ee3\u7801\u6267\u884c\u3002<\/p>\n<ol>\n<li>\u5f53\u4fe1\u53f7\u5904\u7406\u7a0b\u5e8f\u4e2d\u53d1\u751f\u4e0d\u53ef\u91cd\u5165\u51fd\u6570\u6216\u72b6\u6001\u654f\u611f\u64cd\u4f5c\u65f6\uff0c\u5c31\u4f1a\u51fa\u73b0\u8fd9\u4e9b\u95ee\u9898\u3002\u56e0\u4e3a\u4fe1\u53f7\u5904\u7406\u7a0b\u5e8f\u4e2d\u968f\u65f6\u53ef\u4ee5\u88ab\u8c03\u7528\u3002\u6bd4\u5982\uff0c\u5f53\u5728\u4fe1\u53f7\u5904\u7406\u7a0b\u5e8f\u4e2d\u8c03\u7528<code>free<\/code>\u65f6\uff0c\u901a\u5e38\u4f1a\u51fa\u73b0\u53e6\u4e00\u4e2a\u4fe1\u53f7\u4e89\u7528\u6761\u4ef6\uff0c\u4ece\u800c\u5bfc\u81f4\u53cc\u91cd\u91ca\u653e\u3002\u5373\u4f7f\u7ed9\u5b9a\u6307\u9488\u5728\u91ca\u653e\u540e\u8bbe\u7f6e\u4e3a<code>NULL<\/code>\uff0c\u5728\u91ca\u653e\u5185\u5b58\u548c\u5c06\u6307\u9488\u8bbe\u7f6e\u4e3a<code>NULL<\/code>\u4e4b\u95f4\u4ecd\u7136\u5b58\u5728\u7ade\u4e89\u7684\u53ef\u80fd\u3002<\/li>\n<li>\u4e3a\u591a\u4e2a\u4fe1\u53f7\u8bbe\u7f6e\u4e86\u76f8\u540c\u7684\u4fe1\u53f7\u5904\u7406\u7a0b\u5e8f\uff0c\u8fd9\u5c24\u5176\u6709\u95ee\u9898\u2014\u2014\u56e0\u4e3a\u8fd9\u610f\u5473\u7740\u4fe1\u53f7\u5904\u7406\u7a0b\u5e8f\u672c\u8eab\u53ef\u80fd\u4f1a\u91cd\u65b0\u8fdb\u5165\u3002\u4f8b\u5982\uff0cmalloc()\u548cfree()\u662f\u4e0d\u53ef\u91cd\u5165\u7684\uff0c\u56e0\u4e3a\u5b83\u4eec\u53ef\u80fd\u4f7f\u7528\u5168\u5c40\u6216\u9759\u6001\u6570\u636e\u7ed3\u6784\u6765\u7ba1\u7406\u5185\u5b58\uff0c\u5e76\u4e14\u5b83\u4eec\u88absyslog()\u7b49\u770b\u4f3c\u65e0\u5bb3\u7684\u51fd\u6570\u95f4\u63a5\u4f7f\u7528\uff1b\u8fd9\u4e9b\u51fd\u6570\u53ef\u80fd\u4f1a\u5bfc\u81f4\u5185\u5b58\u635f\u574f\u548c\u4ee3\u7801\u6267\u884c\u3002<\/li>\n<\/ol>\n<pre><code class=\"language-c++\">\/\/ Bad\nchar *log_message;\n\nvoid Handler(int signum) {\n  syslog(LOG_NOTICE, &quot;%s\\n&quot;, log_m_essage);\n  free(log_message);\n  sleep(10);\n  exit(0);\n}\n\nint main (int argc, char* argv[]) {\n  log_message = strdup(argv[1]);\n  signal(SIGHUP, Handler);\n  signal(SIGTERM, Handler);\n  sleep(10);\n}<\/code><\/pre>\n<p>\u53ef\u4ee5\u501f\u7531\u4e0b\u5217\u64cd\u4f5c\u89c4\u907f\u95ee\u9898\uff1a<\/p>\n<ol>\n<li>\u907f\u514d\u5728\u591a\u4e2a\u5904\u7406\u51fd\u6570\u4e2d\u5171\u4eab\u67d0\u4e9b\u53d8\u91cf\u3002<\/li>\n<li>\u5728\u4fe1\u53f7\u5904\u7406\u7a0b\u5e8f\u4e2d\u4f7f\u7528\u540c\u6b65\u64cd\u4f5c\u3002<\/li>\n<li>\u5c4f\u853d\u4e0d\u76f8\u5173\u7684\u4fe1\u53f7\uff0c\u4ece\u800c\u63d0\u4f9b\u539f\u5b50\u6027\u3002<\/li>\n<li>\u907f\u514d\u5728\u4fe1\u53f7\u5904\u7406\u51fd\u6570\u4e2d\u8c03\u7528\u4e0d\u6ee1\u8db3<a href=\"https:\/\/www.man7.org\/linux\/man-pages\/man7\/signal-safety.7.html\">\u5f02\u6b65\u4fe1\u53f7\u5b89\u5168<\/a>\u7684\u51fd\u6570\u3002<\/li>\n<\/ol>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u5185\u5b58\u7834\u574f<\/code><\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u95ee\u9898<\/code><\/p>\n<p><a id=\"1.3.3\"><\/a><\/p>\n<h4>3.3 \u3010\u5efa\u8bae\u3011\u6ce8\u610fTime-of-check Time-of-use (TOCTOU) \u6761\u4ef6\u7ade\u4e89<\/h4>\n<p>TOCTOU\uff1a \u8f6f\u4ef6\u5728\u4f7f\u7528\u67d0\u4e2a\u8d44\u6e90\u4e4b\u524d\u68c0\u67e5\u8be5\u8d44\u6e90\u7684\u72b6\u6001\uff0c\u4f46\u662f\u8be5\u8d44\u6e90\u7684\u72b6\u6001\u53ef\u4ee5\u5728\u68c0\u67e5\u548c\u4f7f\u7528\u4e4b\u95f4\u66f4\u6539\uff0c\u4ece\u800c\u4f7f\u68c0\u67e5\u7ed3\u679c\u65e0\u6548\u3002\u5f53\u8d44\u6e90\u5904\u4e8e\u8fd9\u79cd\u610f\u5916\u72b6\u6001\u65f6\uff0c\u8fd9\u53ef\u80fd\u4f1a\u5bfc\u81f4\u8f6f\u4ef6\u6267\u884c\u9519\u8bef\u64cd\u4f5c\u3002<\/p>\n<p>\u5f53\u653b\u51fb\u8005\u53ef\u4ee5\u5f71\u54cd\u68c0\u67e5\u548c\u4f7f\u7528\u4e4b\u95f4\u7684\u8d44\u6e90\u72b6\u6001\u65f6\uff0c\u6b64\u95ee\u9898\u53ef\u80fd\u4e0e\u5b89\u5168\u76f8\u5173\u3002\u8fd9\u53ef\u80fd\u53d1\u751f\u5728\u5171\u4eab\u8d44\u6e90(\u5982<strong>\u6587\u4ef6\u3001\u5185\u5b58<\/strong>\uff0c\u751a\u81f3\u591a\u7ebf\u7a0b\u7a0b\u5e8f\u4e2d\u7684<strong>\u53d8\u91cf<\/strong>)\u4e0a\u3002\u5728\u7f16\u7a0b\u65f6\u9700\u8981\u6ce8\u610f\u907f\u514d\u51fa\u73b0TOCTOU\u95ee\u9898\u3002<\/p>\n<p>\u4f8b\u5982\uff0c\u4e0b\u9762\u7684\u4f8b\u5b50\u4e2d\uff0c\u8be5\u6587\u4ef6\u53ef\u80fd\u5df2\u7ecf\u5728\u68c0\u67e5\u548clstat\u4e4b\u95f4\u8fdb\u884c\u4e86\u66f4\u65b0\uff0c\u7279\u522b\u662f\u56e0\u4e3aprintf\u6709\u5ef6\u8fdf\u3002<\/p>\n<pre><code class=\"language-c++\">struct stat *st;\n\nlstat(&quot;...&quot;, st);\n\nprintf(&quot;foo&quot;);\n\nif (st-&gt;st_mtimespec == ...) {\n  printf(&quot;Now updating things\\n&quot;);\n  UpdateThings();\n}<\/code><\/pre>\n<p>TOCTOU\u96be\u4ee5\u4fee\u590d\uff0c\u4f46\u662f\u6709\u4ee5\u4e0b\u7f13\u89e3\u65b9\u6848\uff1a<\/p>\n<ol>\n<li>\u9650\u5236\u5bf9\u6765\u81ea\u591a\u4e2a\u8fdb\u7a0b\u7684\u6587\u4ef6\u7684\u4ea4\u53c9\u64cd\u4f5c\u3002<\/li>\n<li>\u5982\u679c\u5fc5\u987b\u5728\u591a\u4e2a\u8fdb\u7a0b\u6216\u7ebf\u7a0b\u4e4b\u95f4\u5171\u4eab\u5bf9\u8d44\u6e90\u7684\u8bbf\u95ee\uff0c\u90a3\u4e48\u8bf7\u5c1d\u8bd5\u9650\u5236\u201d\u68c0\u67e5\u201c\uff08CHECK\uff09\u548c\u201d\u4f7f\u7528\u201c\uff08USE\uff09\u8d44\u6e90\u4e4b\u95f4\u7684\u65f6\u95f4\u91cf\uff0c\u4f7f\u4ed6\u4eec\u76f8\u8ddd\u5c3d\u91cf\u4e0d\u8981\u592a\u8fdc\u3002\u8fd9\u4e0d\u4f1a\u4ece\u6839\u672c\u4e0a\u89e3\u51b3\u95ee\u9898\uff0c\u4f46\u53ef\u80fd\u4f1a\u4f7f\u653b\u51fb\u66f4\u96be\u6210\u529f\u3002<\/li>\n<li>\u5728Use\u8c03\u7528\u4e4b\u540e\u91cd\u65b0\u68c0\u67e5\u8d44\u6e90\uff0c\u4ee5\u9a8c\u8bc1\u662f\u5426\u6b63\u786e\u6267\u884c\u4e86\u64cd\u4f5c\u3002<\/li>\n<li>\u786e\u4fdd\u4e00\u4e9b\u73af\u5883\u9501\u5b9a\u673a\u5236\u80fd\u591f\u88ab\u7528\u6765\u6709\u6548\u4fdd\u62a4\u8d44\u6e90\u3002\u4f46\u8981\u786e\u4fdd\u9501\u5b9a\u662f\u68c0\u67e5\u4e4b\u524d\u8fdb\u884c\u7684\uff0c\u800c\u4e0d\u662f\u5728\u68c0\u67e5\u4e4b\u540e\u8fdb\u884c\u7684\uff0c\u4ee5\u4fbf\u68c0\u67e5\u65f6\u7684\u8d44\u6e90\u4e0e\u4f7f\u7528\u65f6\u7684\u8d44\u6e90\u76f8\u540c\u3002<\/li>\n<\/ol>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u5185\u5b58\u7834\u574f<\/code><\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u95ee\u9898<\/code><\/p>\n<p><a id=\"1.4\"><\/a><\/p>\n<h3>4    \u52a0\u5bc6\u89e3\u5bc6<\/h3>\n<p><a id=\"1.4.1\"><\/a><\/p>\n<h4>4.1  \u3010\u5fc5\u987b\u3011\u4e0d\u5f97\u660e\u6587\u5b58\u50a8\u7528\u6237\u5bc6\u7801\u7b49\u654f\u611f\u6570\u636e<\/h4>\n<p>\u7528\u6237\u5bc6\u7801\u5e94\u8be5\u4f7f\u7528 Argon2, scrypt, bcrypt, pbkdf2 \u7b49\u7b97\u6cd5\u505a\u54c8\u5e0c\u4e4b\u540e\u518d\u5b58\u5165\u5b58\u50a8\u7cfb\u7edf, <a href=\"https:\/\/password-hashing.net\/\">https:\/\/password-hashing.net\/<\/a><\/p>\n<p><a href=\"https:\/\/libsodium.gitbook.io\/doc\/password_hashing\/default_phf#example-2-password-storage\">https:\/\/libsodium.gitbook.io\/doc\/password_hashing\/default_phf#example-2-password-storage<\/a><\/p>\n<p>\u7528\u6237\u654f\u611f\u6570\u636e\uff0c\u5e94\u8be5\u505a\u5230\u4f20\u8f93\u8fc7\u7a0b\u4e2d\u52a0\u5bc6\uff0c\u5b58\u50a8\u72b6\u6001\u4e0b\u52a0\u5bc6<br \/>\n\u4f20\u8f93\u8fc7\u7a0b\u4e2d\u52a0\u5bc6\uff0c\u53ef\u4ee5\u4f7f\u7528 HTTPS \u7b49\u8ba4\u8bc1\u52a0\u5bc6\u901a\u4fe1\u534f\u8bae<\/p>\n<p>\u5b58\u50a8\u72b6\u6001\u4e0b\u52a0\u5bc6\uff0c\u53ef\u4ee5\u4f7f\u7528 SQLCipher \u7b49\u7c7b\u4f3c\u65b9\u6848\u3002<\/p>\n<p><a id=\"1.4.2\"><\/a><\/p>\n<h4>4.2  \u3010\u5fc5\u987b\u3011\u5185\u5b58\u4e2d\u7684\u7528\u6237\u5bc6\u7801\u7b49\u654f\u611f\u6570\u636e\u5e94\u8be5\u5b89\u5168\u62b9\u9664<\/h4>\n<p>\u4f8b\u5982\u7528\u6237\u5bc6\u7801\u7b49\uff0c\u5373\u4f7f\u662f\u4e34\u65f6\u4f7f\u7528\uff0c\u4e5f\u5e94\u5728\u4f7f\u7528\u5b8c\u6210\u540e\u5e94\u5f53\u5c06\u5185\u5bb9\u5f7b\u5e95\u6e05\u7a7a\u3002<\/p>\n<p>\u9519\u8bef\uff1a<\/p>\n<pre><code class=\"language-c++\">#include &lt;openssl\/crypto.h&gt;\n#include &lt;unistd.h&gt;\n\n    {\n        ...\n        string user_password(100, &#039;\\0&#039;);\n        snprintf(&amp;user_password, &quot;password: %s&quot;, user_password.size(), password_from_input);\n        ...\n    }<\/code><\/pre>\n<p>\u6b63\u786e\uff1a<\/p>\n<pre><code class=\"language-c++\">    {\n        ...\n        string user_password(100, &#039;\\0&#039;);\n        snprintf(&amp;user_password, &quot;password: %s&quot;, user_password.size(), password_from_input);\n        ...\n        OPENSSL_cleanse(&amp;user_password[0], user_password.size());\n    }\n<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u654f\u611f\u4fe1\u606f\u6cc4\u9732<\/code><\/p>\n<p><a id=\"1.4.3\"><\/a><\/p>\n<h4>4.3  \u3010\u5fc5\u987b\u3011rand() \u7c7b\u51fd\u6570\u5e94\u6b63\u786e\u521d\u59cb\u5316<\/h4>\n<p>rand\u7c7b\u51fd\u6570\u7684\u968f\u673a\u6027\u5e76\u4e0d\u9ad8\u3002\u800c\u4e14\u5728\u4f7f\u7528\u524d\u9700\u8981\u4f7f\u7528srand()\u6765\u521d\u59cb\u5316\u3002\u672a\u521d\u59cb\u5316\u7684\u968f\u673a\u6570\u53ef\u80fd\u5bfc\u81f4\u67d0\u4e9b\u5185\u5bb9\u53ef\u9884\u6d4b\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nint main() {\n  int foo = rand();\n  return 0;\n}<\/code><\/pre>\n<p>\u4e0a\u8ff0\u4ee3\u7801\u6267\u884c\u5b8c\u6210\u540e\uff0cfoo\u7684\u503c\u662f\u56fa\u5b9a\u7684\u3002\u5b83\u7b49\u6548\u4e8e <code>srand(1); rand();<\/code>\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\n\nint main() {\n  srand(time(0));\n  int foo = rand();\n  return 0;\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u903b\u8f91\u6f0f\u6d1e<\/code><\/p>\n<p><a id=\"1.4.4\"><\/a><\/p>\n<h4>4.4  \u3010\u5fc5\u987b\u3011\u5728\u9700\u8981\u9ad8\u5f3a\u5ea6\u5b89\u5168\u52a0\u5bc6\u65f6\u4e0d\u5e94\u4f7f\u7528\u5f31PRNG\u51fd\u6570<\/h4>\n<p>\u5728\u9700\u8981\u751f\u6210 AES\/SM1\/HMAC \u7b49\u7b97\u6cd5\u7684\u5bc6\u94a5\/IV\/Nonce\uff0c RSA\/ECDSA\/ECDH \u7b49\u7b97\u6cd5\u7684\u79c1\u94a5\uff0c\u8fd9\u7c7b\u9700\u8981\u9ad8\u5b89\u5168\u6027\u7684\u4e1a\u52a1\u573a\u666f\uff0c\u5fc5\u987b\u4f7f\u7528\u5bc6\u7801\u5b66\u5b89\u5168\u7684\u968f\u673a\u6570\u751f\u6210\u5668 (Cryptographically Secure PseudoRandom Number Generator (CSPRNG) ), \u4e0d\u5f97\u4f7f\u7528 <code>rand()<\/code> \u7b49\u65e0\u5bc6\u7801\u5b66\u5b89\u5168\u6027\u4fdd\u8bc1\u7684\u666e\u901a\u968f\u673a\u6570\u751f\u6210\u5668\u3002<\/p>\n<p>\u63a8\u8350\u4f7f\u7528\u7684 CSPRNG \u6709\uff1a<\/p>\n<ol>\n<li>\n<p>OpenSSL \u4e2d\u7684 <code>RAND_bytes()<\/code> \u51fd\u6570, <a href=\"https:\/\/www.openssl.org\/docs\/man1.1.1\/man3\/RAND_bytes.html\">https:\/\/www.openssl.org\/docs\/man1.1.1\/man3\/RAND_bytes.html<\/a><\/p>\n<\/li>\n<li>\n<p>libsodium \u4e2d\u7684 <code>randombytes_buf()<\/code> \u51fd\u6570<\/p>\n<\/li>\n<li>\n<p>Linux kernel \u7684 <code>getrandom()<\/code> \u7cfb\u7edf\u8c03\u7528, <a href=\"https:\/\/man7.org\/linux\/man-pages\/man2\/getrandom.2.html\">https:\/\/man7.org\/linux\/man-pages\/man2\/getrandom.2.html<\/a> .<br \/>\n\u6216\u8005\u8bfb \/dev\/urandom \u6587\u4ef6, \u6216\u8005 \/dev\/random \u6587\u4ef6\u3002<\/p>\n<\/li>\n<li>\n<p>Apple IOS \u7684 <code>SecRandomCopyBytes()<\/code>, <a href=\"https:\/\/developer.apple.com\/documentation\/security\/1399291-secrandomcopybytes\">https:\/\/developer.apple.com\/documentation\/security\/1399291-secrandomcopybytes<\/a><\/p>\n<\/li>\n<li>\n<p>Windows \u4e0b\u7684 <code>BCryptGenRandom()<\/code>, <code>CryptGenRandom()<\/code>, <code>RtlGenRandom()<\/code><\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"language-c++\">#include &lt;openssl\/aes.h&gt;\n#include &lt;openssl\/crypto.h&gt;\n#include &lt;openssl\/rand.h&gt;\n#include &lt;unistd.h&gt;\n\n    {\n        unsigned char key[16];\n        if (1 != RAND_bytes(&amp;key[0], sizeof(key))) {  \/\/... \u9519\u8bef\u5904\u7406\n            return -1;\n        }\n\n        AES_KEY aes_key;\n        if (0 != AES_set_encrypt_key(&amp;key[0], sizeof(key) * 8, &amp;aes_key)) {\n            \/\/ ... \u9519\u8bef\u5904\u7406\n            return -1;\n        }\n\n        ...\n\n        OPENSSL_cleanse(&amp;key[0], sizeof(key));\n    }\n<\/code><\/pre>\n<p><code>rand()<\/code>\u7c7b\u51fd\u6570\u7684\u968f\u673a\u6027\u5e76\u4e0d\u9ad8\u3002\u654f\u611f\u64cd\u4f5c\u65f6\uff0c\u5982\u8bbe\u8ba1\u52a0\u5bc6\u7b97\u6cd5\u65f6\uff0c\u4e0d\u5f97\u4f7f\u7528rand()\u6216\u8005\u7c7b\u4f3c\u7684\u7b80\u5355\u7ebf\u6027\u540c\u4f59\u4f2a\u968f\u673a\u6570\u751f\u6210\u5668\u6765\u4f5c\u4e3a\u968f\u673a\u6570\u53d1\u751f\u5668\u3002\u7b26\u5408\u8be5\u5b9a\u4e49\u7684\u6bd4\u7279\u5e8f\u5217\u7684\u7279\u70b9\u662f\uff0c\u5e8f\u5217\u4e2d\u201c1\u201d\u7684\u6570\u91cf\u7ea6\u7b49\u4e8e\u201c0\u201d\u7684\u6570\u91cf\uff1b\u540c\u7406\uff0c\u201c01\u201d\u3001\u201c00\u201d\u3001\u201c10\u201d\u3001\u201c11\u201d\u7684\u6570\u91cf\u5927\u81f4\u76f8\u540c\uff0c\u4ee5\u6b64\u7c7b\u63a8\u3002<\/p>\n<p>\u4f8b\u5982 C \u6807\u51c6\u5e93\u4e2d\u7684 <code>rand()<\/code> \u7684\u5b9e\u73b0\u53ea\u662f\u7b80\u5355\u7684<a href=\"https:\/\/sourceware.org\/git\/?p=glibc.git;a=blob;f=stdlib\/random_r.c;hb=glibc-2.28#l353\">\u7ebf\u6027\u540c\u4f59\u7b97\u6cd5<\/a>\uff0c\u751f\u6210\u7684\u4f2a\u968f\u673a\u6570\u5177\u6709\u8f83\u5f3a\u7684\u53ef\u9884\u6d4b\u6027\u3002<\/p>\n<p>\u5f53\u9700\u8981\u5b9e\u73b0\u9ad8\u5f3a\u5ea6\u52a0\u5bc6\uff0c\u4f8b\u5982\u6d89\u53ca\u901a\u4fe1\u5b89\u5168\u65f6\uff0c\u4e0d\u5e94\u5f53\u4f7f\u7528 <code>rand()<\/code> \u4f5c\u4e3a\u968f\u673a\u6570\u53d1\u751f\u5668\u3002<\/p>\n<p>\u5b9e\u9645\u5e94\u7528\u4e2d\uff0c<a href=\"https:\/\/docs.microsoft.com\/en-us\/cpp\/standard-library\/random-device-class?redirectedfrom=MSDN&amp;view=vs-2019#remarks\"> C++11 \u6807\u51c6\u63d0\u4f9b\u7684<code>random_device<\/code>\u4fdd\u8bc1\u52a0\u5bc6\u7684\u5b89\u5168\u6027\u548c\u968f\u673a\u6027<\/a><br \/>\n\u4f46\u662f <a href=\"https:\/\/stackoverflow.com\/questions\/44867500\/is-stdrandom-device-cryptographic-secure\">C++ \u6807\u51c6\u5e76\u4e0d\u4fdd\u8bc1\u8fd9\u4e00\u70b9<\/a>\u3002\u8de8\u5e73\u53f0\u7684\u4ee3\u7801\u53ef\u4ee5\u8003\u8651\u7528 <a href=\"https:\/\/wiki.openssl.org\/index.php\/Random_Numbers\">OpenSSL<\/a> \u7b49\u4fdd\u8bc1\u5bc6\u7801\u5b66\u5b89\u5168\u7684\u5e93\u91cc\u7684\u968f\u673a\u6570\u53d1\u751f\u5668\u3002<\/p>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u654f\u611f\u6570\u636e\u6cc4\u9732<\/code><\/p>\n<p><a id=\"1.4.5\"><\/a><\/p>\n<h4>4.5  \u3010\u5fc5\u987b\u3011\u81ea\u5df1\u5b9e\u73b0\u7684rand\u8303\u56f4\u4e0d\u5e94\u8fc7\u5c0f<\/h4>\n<p>\u5982\u679c\u5728\u5f31\u5b89\u5168\u573a\u666f\u76f8\u5173\u7684\u7b97\u6cd5\u4e2d\u81ea\u5df1\u5b9e\u73b0\u4e86PRNG\uff0c\u8bf7\u786e\u4fddrand\u51fa\u6765\u7684\u968f\u673a\u6570\u4e0d\u4f1a\u5f88\u5c0f\u6216\u53ef\u9884\u6d4b\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Bad\nint32_t val = ((state[0] * 1103515245U) + 12345U) &amp; 999999;<\/code><\/pre>\n<p>\u4e0a\u8ff0\u4f8b\u5b50\u53ef\u80fd\u60f3\u751f\u62100~999999\u5171100\u4e07\u79cd\u53ef\u80fd\u7684\u968f\u673a\u6570\uff0c\u4f46\u662f999999\u7684\u4e8c\u8fdb\u5236\u662f11110100001000111111\uff0c\u4e0e&amp;\u8fd0\u7b97\u540e\uff0c0\u4f4d\u4e00\u76f4\u662f0\uff0c\u6240\u4ee5\u751f\u6210\u51fa\u7684\u8303\u56f4\u660e\u663e\u4f1a\u5c0f\u4e8e100\u4e07\u79cd\u3002<\/p>\n<pre><code class=\"language-c++\">\/\/ Good\nint32_t val = ((state[0] * 1103515245U) + 12345U) % 1000000;\n\n\/\/ Good\nint32_t val = ((state[0] * 1103515245U) + 12345U) &amp; 0x7fffffff;<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u903b\u8f91\u6f0f\u6d1e<\/code><\/p>\n<p><a id=\"1.5\"><\/a><\/p>\n<h3>5    \u6587\u4ef6\u64cd\u4f5c<\/h3>\n<p><a id=\"1.5.1\"><\/a><\/p>\n<h4>5.1  \u3010\u5fc5\u987b\u3011\u907f\u514d\u8def\u5f84\u7a7f\u8d8a\u95ee\u9898<\/h4>\n<p>\u5728\u8fdb\u884c\u6587\u4ef6\u64cd\u4f5c\u65f6\uff0c\u9700\u8981\u5224\u65ad\u5916\u90e8\u4f20\u5165\u7684\u6587\u4ef6\u540d\u662f\u5426\u5408\u6cd5\uff0c\u5982\u679c\u6587\u4ef6\u540d\u4e2d\u5305\u542b <code>..\/<\/code> \u7b49\u7279\u6b8a\u5b57\u7b26\uff0c\u5219\u4f1a\u9020\u6210\u8def\u5f84\u7a7f\u8d8a\uff0c\u5bfc\u81f4\u4efb\u610f\u6587\u4ef6\u7684\u8bfb\u5199\u3002<\/p>\n<p>\u9519\u8bef\uff1a<\/p>\n<pre><code class=\"language-c++\">void Foo() {\n  char file_path[PATH_MAX] = &quot;\/home\/user\/code\/&quot;;\n  \/\/ \u5982\u679c\u4f20\u5165\u7684\u6587\u4ef6\u540d\u5305\u542b..\/\u53ef\u5bfc\u81f4\u8def\u5f84\u7a7f\u8d8a\n  \/\/ \u4f8b\u5982&quot;..\/file.txt&quot;\uff0c\u5219\u53ef\u4ee5\u8bfb\u53d6\u5230\u4e0a\u5c42\u76ee\u5f55\u7684file.txt\u6587\u4ef6\n  char name[20] = &quot;..\/file.txt&quot;;\n  memcpy(file_path + strlen(file_path), name, sizeof(name));\n  int fd = open(file_path, O_RDONLY);\n  if (fd != -1) {\n    char data[100] = {0};\n    int num = 0;\n    memset(data, 0, sizeof(data));\n    num = read(fd, data, sizeof(data));\n    if (num &gt; 0) {\n      write(STDOUT_FILENO, data, num);\n    }\n    close(fd);\n  }\n}<\/code><\/pre>\n<p>\u6b63\u786e\uff1a<\/p>\n<pre><code class=\"language-c++\">void Foo() {\n  char file_path[PATH_MAX] = &quot;\/home\/user\/code\/&quot;;\n  char name[20] = &quot;..\/file.txt&quot;;\n  \/\/ \u5224\u65ad\u4f20\u5165\u7684\u6587\u4ef6\u540d\u662f\u5426\u975e\u6cd5\uff0c\u4f8b\u5982&quot;..\/file.txt&quot;\u4e2d\u5305\u542b\u975e\u6cd5\u5b57\u7b26..\/\uff0c\u76f4\u63a5\u8fd4\u56de\n  if (strstr(name, &quot;..&quot;) != NULL){\n    \/\/ \u5305\u542b\u975e\u6cd5\u5b57\u7b26\n    return;\n  }\n  memcpy(file_path + strlen(file_path), name, sizeof(name));\n  int fd = open(file_path, O_RDONLY);\n  if (fd != -1) {\n    char data[100] = {0};\n    int num = 0;\n    memset(data, 0, sizeof(data));\n    num = read(fd, data, sizeof(data));\n    if (num &gt; 0) {\n      write(STDOUT_FILENO, data, num);\n    }\n    close(fd);\n   }\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u903b\u8f91\u6f0f\u6d1e<\/code>  <\/p>\n<p><a id=\"1.5.2\"><\/a><\/p>\n<h4>5.2  \u3010\u5fc5\u987b\u3011\u907f\u514d\u76f8\u5bf9\u8def\u5f84\u5bfc\u81f4\u7684\u5b89\u5168\u95ee\u9898\uff08DLL\u3001EXE\u52ab\u6301\u7b49\u95ee\u9898\uff09<\/h4>\n<p>\u5728\u7a0b\u5e8f\u4e2d\uff0c\u4f7f\u7528\u76f8\u5bf9\u8def\u5f84\u53ef\u80fd\u5bfc\u81f4\u4e00\u4e9b\u5b89\u5168\u98ce\u9669\uff0c\u4f8b\u5982DLL\u3001EXE\u52ab\u6301\u7b49\u95ee\u9898\u3002<\/p>\n<p>\u4f8b\u5982\u4ee5\u4e0b\u4ee3\u7801\uff0c\u53ef\u80fd\u5b58\u5728\u52ab\u6301\u95ee\u9898\uff1a<\/p>\n<pre><code class=\"language-c++\">int Foo() {\n  \/\/ \u4f20\u5165\u7684\u662fdll\u6587\u4ef6\u540d\uff0c\u5982\u679c\u5f53\u524d\u76ee\u5f55\u4e0b\u88ab\u5199\u5165\u4e86\u6076\u610f\u7684\u540c\u540ddll\uff0c\u5219\u53ef\u80fd\u5bfc\u81f4dll\u52ab\u6301\n  HINSTANCE hinst = ::LoadLibrary(&quot;dll_nolib.dll&quot;);\n  if (hinst != NULL) {\n    cout&lt;&lt;&quot;dll loaded!&quot; &lt;&lt; endl;\n  }\n  return 0;\n}<\/code><\/pre>\n<p>\u9488\u5bf9DLL\u52ab\u6301\u7684\u5b89\u5168\u7f16\u7801\u7684\u89c4\u8303\uff1a<\/p>\n<p>1\uff09\u8c03\u7528LoadLibrary\uff0cLoadLibraryEx\uff0cCreateProcess\uff0cShellExecute\u7b49\u8fdb\u884c\u6a21\u5757\u52a0\u8f7d\u7684\u51fd\u6570\u65f6\uff0c\u6307\u660e\u6a21\u5757\u7684\u5b8c\u6574\uff08\u5168\uff09\u8def\u5f84\uff0c\u7981\u6b62\u4f7f\u7528\u76f8\u5bf9\u8def\u5f84\uff0c\u8fd9\u6837\u5c31\u53ef\u907f\u514d\u4ece\u5176\u5b83\u76ee\u5f55\u52a0\u8f7dDLL\u3002<br \/>\n2\uff09\u5728\u5e94\u7528\u7a0b\u5e8f\u7684\u5f00\u5934\u8c03\u7528SetDllDirectory(TEXT(&quot;&quot;)); \u4ece\u800c\u5c06\u5f53\u524d\u76ee\u5f55\u4eceDLL\u7684\u641c\u7d22\u5217\u8868\u4e2d\u5220\u9664\u3002\u7ed3\u5408SetDefaultDllDirectories\uff0cAddDllDirectory\uff0cRemoveDllDirectory\u8fd9\u51e0\u4e2aAPI\u914d\u5408\u4f7f\u7528\uff0c\u53ef\u4ee5\u6709\u6548\u7684\u89c4\u907fDLL\u52ab\u6301\u95ee\u9898\u3002\u8fd9\u4e9bAPI\u53ea\u80fd\u5728\u6253\u4e86KB2533623\u8865\u4e01\u7684Windows7\uff0c2008\u4e0a\u4f7f\u7528\u3002<\/p>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u6f0f\u6d1e<\/code><\/p>\n<p><a id=\"1.5.3\"><\/a><\/p>\n<h4>5.3  \u3010\u5fc5\u987b\u3011\u6587\u4ef6\u6743\u9650\u63a7\u5236<\/h4>\n<p>\u5728\u521b\u5efa\u6587\u4ef6\u65f6\uff0c\u9700\u8981\u6839\u636e\u6587\u4ef6\u7684\u654f\u611f\u7ea7\u522b\u8bbe\u7f6e\u4e0d\u540c\u7684\u8bbf\u95ee\u6743\u9650\uff0c\u4ee5\u9632\u6b62\u654f\u611f\u6570\u636e\u88ab\u5176\u4ed6\u6076\u610f\u7a0b\u5e8f\u8bfb\u53d6\u6216\u5199\u5165\u3002<\/p>\n<p>\u9519\u8bef\uff1a<\/p>\n<pre><code class=\"language-c++\">int Foo() {\n  \/\/ \u4e0d\u8981\u8bbe\u7f6e\u4e3a777\u6743\u9650\uff0c\u4ee5\u9632\u6b62\u88ab\u5176\u4ed6\u6076\u610f\u7a0b\u5e8f\u64cd\u4f5c\n  if (creat(&quot;file.txt&quot;, 0777) &lt; 0) {\n    printf(&quot;\u6587\u4ef6\u521b\u5efa\u5931\u8d25\uff01\\n&quot;);\n  } else {\n    printf(&quot;\u6587\u4ef6\u521b\u5efa\u6210\u529f\uff01\\n&quot;);\n  }\n  return 0;\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u6f0f\u6d1e<\/code>  <\/p>\n<p><a id=\"1.6\"><\/a><\/p>\n<h3>6 \u5185\u5b58\u64cd\u4f5c<\/h3>\n<p><a id=\"1.6.1\"><\/a><\/p>\n<h4>6.1 \u3010\u5fc5\u987b\u3011\u9632\u6b62\u5404\u79cd\u8d8a\u754c\u5199\uff08\u5411\u524d\/\u5411\u540e\uff09<\/h4>\n<p>\u9519\u8bef1\uff1a<\/p>\n<pre><code class=\"language-c++\">int a[5];\na[5] = 0;<\/code><\/pre>\n<p>\u9519\u8bef2\uff1a<\/p>\n<pre><code class=\"language-c++\">int a[5];\nint b = user_controlled_value;\na[b] = 3;<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u5185\u5b58\u7834\u574f<\/code><\/p>\n<p><a id=\"1.6.2\"><\/a><\/p>\n<h4>6.2 \u3010\u5fc5\u987b\u3011\u9632\u6b62\u4efb\u610f\u5730\u5740\u5199<\/h4>\n<p>\u4efb\u610f\u5730\u5740\u5199\u4f1a\u5bfc\u81f4\u4e25\u91cd\u7684\u5b89\u5168\u9690\u60a3\uff0c\u53ef\u80fd\u5bfc\u81f4\u4ee3\u7801\u6267\u884c\u3002\u56e0\u6b64\uff0c\u5728\u7f16\u7801\u65f6\u5fc5\u987b\u6821\u9a8c\u5199\u5165\u7684\u5730\u5740\u3002<\/p>\n<p>\u9519\u8bef\uff1a<\/p>\n<pre><code class=\"language-c++\">void Write(MyStruct dst_struct) {\n  char payload[10] = { 0 };\n  memcpy(dst_struct.buf, payload, sizeof(payload));\n}\n\nint main() {\n  MyStruct dst_stuct;\n  dst_stuct.buf = (char*)user_controlled_value;\n  Write(dst_stuct);\n  return 0;\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u5185\u5b58\u7834\u574f<\/code><\/p>\n<p><a id=\"1.7\"><\/a><\/p>\n<h3>7 \u6570\u5b57\u64cd\u4f5c<\/h3>\n<p><a id=\"1.7.1\"><\/a><\/p>\n<h4>7.1 \u3010\u5fc5\u987b\u3011\u9632\u6b62\u6574\u6570\u6ea2\u51fa<\/h4>\n<p>\u5728\u8ba1\u7b97\u65f6\u9700\u8981\u8003\u8651\u6574\u6570\u6ea2\u51fa\u7684\u53ef\u80fd\uff0c\u5c24\u5176\u5728\u8fdb\u884c\u5185\u5b58\u64cd\u4f5c\u65f6\uff0c\u9700\u8981\u5bf9\u5206\u914d\u3001\u62f7\u8d1d\u7b49\u5927\u5c0f\u8fdb\u884c\u5408\u6cd5\u6821\u9a8c\uff0c\u9632\u6b62\u6574\u6570\u6ea2\u51fa\u5bfc\u81f4\u7684\u6f0f\u6d1e\u3002<\/p>\n<p>\u9519\u8bef\uff08\u8be5\u4f8b\u5b50\u5728\u8ba1\u7b97\u65f6\u4ea7\u751f\u6574\u6570\u6ea2\u51fa\uff09<\/p>\n<pre><code class=\"language-c++\">const int kMicLen = 4;\n\/\/ \u6574\u6570\u6ea2\u51fa\nvoid Foo() {\n  int len = 1;\n  char payload[10] = { 0 };\n  char dst[10] = { 0 };\n  \/\/ Bad, \u7531\u4e8elen\u5c0f\u4e8e4\uff0c\u5bfc\u81f4\u8ba1\u7b97\u62f7\u8d1d\u957f\u5ea6\u65f6\uff0c\u6574\u6570\u6ea2\u51fa\n  \/\/ len - kMicLen == 0xfffffffd\n  memcpy(dst, payload, len - kMicLen);\n}<\/code><\/pre>\n<p>\u6b63\u786e\u4f8b\u5b50<\/p>\n<pre><code class=\"language-c++\">void Foo() {\n  int len = 1;\n  char payload[10] = { 0 };\n  char dst[10] = { 0 };\n  int size = len - kMicLen;\n  \/\/ \u62f7\u8d1d\u524d\u5bf9\u957f\u5ea6\u8fdb\u884c\u5224\u65ad\n  if (size &gt; 0 &amp;&amp; size &lt; 10) {\n    memcpy(dst, payload, size);\n    printf(&quot;memcpy good\\n&quot;);\n  }\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u5185\u5b58\u7834\u574f<\/code><\/p>\n<p><a id=\"1.7.2\"><\/a><\/p>\n<h4>7.2 \u3010\u5fc5\u987b\u3011\u9632\u6b62Off-By-One<\/h4>\n<p>\u5728\u8fdb\u884c\u8ba1\u7b97\u6216\u8005\u64cd\u4f5c\u65f6\uff0c\u5982\u679c\u4f7f\u7528\u7684\u6700\u5927\u503c\u6216\u6700\u5c0f\u503c\u4e0d\u6b63\u786e\uff0c\u4f7f\u5f97\u8be5\u503c\u6bd4\u6b63\u786e\u503c\u591a1\u6216\u5c111\uff0c\u53ef\u80fd\u5bfc\u81f4\u5b89\u5168\u98ce\u9669\u3002<\/p>\n<p>\u9519\u8bef\uff1a<\/p>\n<pre><code class=\"language-c++\">char firstname[20];\nchar lastname[20];\nchar fullname[40];\n\nfullname[0] = &#039;\\0&#039;;\n\nstrncat(fullname, firstname, 20);\n\/\/ \u7b2c\u4e8c\u6b21\u8c03\u7528strncat()\u53ef\u80fd\u4f1a\u8ffd\u52a0\u53e6\u591620\u4e2a\u5b57\u7b26\u3002\u5982\u679c\u8fd920\u4e2a\u5b57\u7b26\u6ca1\u6709\u7ec8\u6b62\u7a7a\u5b57\u7b26\uff0c\u5219\u5b58\u5728\u5b89\u5168\u95ee\u9898\nstrncat(fullname, lastname, 20);<\/code><\/pre>\n<p>\u6b63\u786e\uff1a<\/p>\n<pre><code class=\"language-c++\">char firstname[20];\nchar lastname[20];\nchar fullname[40];\n\nfullname[0] = &#039;\\0&#039;;\n\n\/\/ \u5f53\u4f7f\u7528\u50cfstrncat()\u51fd\u6570\u65f6\uff0c\u5fc5\u987b\u5728\u7f13\u51b2\u533a\u7684\u672b\u5c3e\u4e3a\u7ec8\u6b62\u7a7a\u5b57\u7b26\u7559\u4e0b\u4e00\u4e2a\u7a7a\u5b57\u8282\uff0c\u907f\u514doff-by-one\nstrncat(fullname, firstname, sizeof(fullname) - strlen(fullname) - 1);\nstrncat(fullname, lastname, sizeof(fullname) - strlen(fullname) - 1);<\/code><\/pre>\n<p>\u5bf9\u4e8e C++ \u4ee3\u7801\uff0c\u518d\u6b21\u5f3a\u70c8\u5efa\u8bae\u4f7f\u7528 <code>string<\/code>\u3001<code>vector<\/code> \u7b49\u7ec4\u4ef6\u4ee3\u66ff\u539f\u59cb\u6307\u9488\u548c\u6570\u7ec4\u64cd\u4f5c\u3002<\/p>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u5185\u5b58\u7834\u574f<\/code><\/p>\n<p><a id=\"1.7.3\"><\/a><\/p>\n<h4>7.3 \u3010\u5fc5\u987b\u3011\u907f\u514d\u5927\u5c0f\u7aef\u9519\u8bef<\/h4>\n<p>\u5728\u4e00\u4e9b\u6d89\u53ca\u5927\u5c0f\u7aef\u6570\u636e\u5904\u7406\u7684\u573a\u666f\uff0c\u9700\u8981\u8fdb\u884c\u5927\u5c0f\u7aef\u5224\u65ad\uff0c\u4f8b\u5982\u4ece\u5927\u7aef\u8bbe\u5907\u53d6\u51fa\u7684\u503c\uff0c\u8981\u4ee5\u5927\u7aef\u8fdb\u884c\u5904\u7406\uff0c\u907f\u514d\u7aef\u5e8f\u9519\u8bef\u4f7f\u7528\u3002<\/p>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u6f0f\u6d1e<\/code><\/p>\n<p><a id=\"1.7.4\"><\/a><\/p>\n<h4>7.4 \u3010\u5fc5\u987b\u3011\u68c0\u67e5\u9664\u4ee5\u96f6\u5f02\u5e38<\/h4>\n<p>\u5728\u8fdb\u884c\u9664\u6cd5\u8fd0\u7b97\u65f6\uff0c\u9700\u8981\u5224\u65ad\u88ab\u9664\u6570\u662f\u5426\u4e3a\u96f6\uff0c\u4ee5\u9632\u5bfc\u81f4\u7a0b\u5e8f\u4e0d\u7b26\u5408\u9884\u671f\u6216\u8005\u5d29\u6e83\u3002<\/p>\n<p>\u9519\u8bef\uff1a<\/p>\n<pre><code class=\"language-c++\">int divide(int x, int y) {\n  return x \/ y;\n}<\/code><\/pre>\n<p>\u6b63\u786e\uff1a<\/p>\n<pre><code class=\"language-c++\">int divide(int x, int y) {\n  if (y == 0) {\n    throw DivideByZero;\n  }\n  return x \/ y;\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4f4e\u98ce\u9669-\u62d2\u7edd\u670d\u52a1<\/code><\/p>\n<p><a id=\"1.7.5\"><\/a><\/p>\n<h4>7.5 \u3010\u5fc5\u987b\u3011\u9632\u6b62\u6570\u5b57\u7c7b\u578b\u7684\u9519\u8bef\u5f3a\u8f6c<\/h4>\n<p>\u5728\u6709\u7b26\u53f7\u548c\u65e0\u7b26\u53f7\u6570\u5b57\u53c2\u4e0e\u7684\u8fd0\u7b97\u4e2d\uff0c\u9700\u8981\u6ce8\u610f\u7c7b\u578b\u5f3a\u8f6c\u53ef\u80fd\u5bfc\u81f4\u7684\u903b\u8f91\u9519\u8bef\uff0c\u5efa\u8bae\u6307\u5b9a\u53c2\u4e0e\u8ba1\u7b97\u65f6\u6570\u5b57\u7684\u7c7b\u578b\u6216\u8005\u7edf\u4e00\u7c7b\u578b\u53c2\u4e0e\u8ba1\u7b97\u3002<\/p>\n<p>\u9519\u8bef\u4f8b\u5b50<\/p>\n<pre><code class=\"language-c++\">int Foo() {\n  int len = 1;\n  unsigned int size = 9;\n  \/\/ 1 &lt; 9 - 10 ? \u7531\u4e8e\u8fd0\u7b97\u4e2d\u65e0\u7b26\u53f7\u548c\u6709\u7b26\u53f7\u6df7\u7528\uff0c\u5bfc\u81f4\u8ba1\u7b97\u7ed3\u679c\u4ee5\u65e0\u7b26\u53f7\u8ba1\u7b97\n  if (len &lt; size - 10) {\n    printf(&quot;Bad\\n&quot;);\n  } else {\n    printf(&quot;Good\\n&quot;);\n  }\n}<\/code><\/pre>\n<p>\u6b63\u786e\u4f8b\u5b50<\/p>\n<pre><code class=\"language-c++\">void Foo() {\n  \/\/ \u7edf\u4e00\u4e24\u8005\u8ba1\u7b97\u7c7b\u578b\u4e3a\u6709\u7b26\u53f7\n  int len = 1;\n  int size = 9;\n  if (len &lt; size - 10) {\n    printf(&quot;Bad\\n&quot;);\n  } else {\n    printf(&quot;Good\\n&quot;);\n  }\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u5185\u5b58\u7834\u574f<\/code><\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u6f0f\u6d1e<\/code><\/p>\n<p><a id=\"1.7.6\"><\/a><\/p>\n<h4>7.6 \u3010\u5fc5\u987b\u3011\u6bd4\u8f83\u6570\u636e\u5927\u5c0f\u65f6\u52a0\u4e0a\u6700\u5c0f\/\u6700\u5927\u503c\u7684\u6821\u9a8c<\/h4>\n<p>\u5728\u8fdb\u884c\u6570\u636e\u5927\u5c0f\u6bd4\u8f83\u65f6\uff0c\u8981\u5408\u7406\u5730\u6821\u9a8c\u6570\u636e\u7684\u533a\u95f4\u8303\u56f4\uff0c\u5efa\u8bae\u6839\u636e\u6570\u5b57\u7c7b\u578b\uff0c\u5bf9\u5176\u8fdb\u884c\u6700\u5927\u548c\u6700\u5c0f\u503c\u7684\u5224\u65ad\uff0c\u4ee5\u9632\u6b62\u975e\u9884\u671f\u9519\u8bef\u3002<\/p>\n<p>\u9519\u8bef\uff1a<\/p>\n<pre><code class=\"language-c++\">void Foo(int index) {\n  int a[30] = {0};\n  \/\/ \u6b64\u5904index\u662fint\u578b\uff0c\u53ea\u8003\u8651\u4e86index\u5c0f\u4e8e\u6570\u7ec4\u5927\u5c0f\uff0c\u4f46\u662f\u5e76\u672a\u5224\u65ad\u662f\u5426\u5927\u4e8e\u7b49\u4e8e0\n  if (index &lt; 30) {\n    \/\/ \u5982\u679cindex\u4e3a\u8d1f\u6570\uff0c\u5219\u8d8a\u754c\n    a[index] = 1;\n  }\n}<\/code><\/pre>\n<p>\u6b63\u786e\uff1a<\/p>\n<pre><code class=\"language-c++\">void Foo(int index) {\n  int a[30] = {0};\n  \/\/ \u5224\u65adindex\u7684\u6700\u5927\u6700\u5c0f\u503c\n  if (index &gt;= 0 &amp;&amp; index &lt; 30) {\n    a[index] = 1;\n  }\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u5185\u5b58\u7834\u574f<\/code><\/p>\n<p><a id=\"1.8\"><\/a><\/p>\n<h3>8    \u6307\u9488\u64cd\u4f5c<\/h3>\n<p><a id=\"1.8.1\"><\/a><\/p>\n<h4>8.1 \u3010\u5efa\u8bae\u3011\u68c0\u67e5\u5728pointer\u4e0a\u4f7f\u7528sizeof<\/h4>\n<p>\u9664\u4e86\u6d4b\u8bd5\u5f53\u524d\u6307\u9488\u957f\u5ea6\uff0c\u5426\u5219\u4e00\u822c\u4e0d\u4f1a\u5728pointer\u4e0a\u4f7f\u7528sizeof\u3002<\/p>\n<p>\u6b63\u786e\uff1a<\/p>\n<pre><code class=\"language-c++\">size_t pointer_length = sizeof(void*);<\/code><\/pre>\n<p>\u53ef\u80fd\u9519\u8bef\uff1a<\/p>\n<pre><code class=\"language-c++\">size_t structure_length = sizeof(Foo*);<\/code><\/pre>\n<p>\u53ef\u80fd\u662f\uff1a<\/p>\n<pre><code class=\"language-c++\">size_t structure_length = sizeof(Foo);<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u6f0f\u6d1e<\/code><\/p>\n<p><a id=\"1.8.2\"><\/a><\/p>\n<h4>8.2 \u3010\u5fc5\u987b\u3011\u68c0\u67e5\u76f4\u63a5\u5c06\u6570\u7ec4\u548c0\u6bd4\u8f83\u7684\u4ee3\u7801<\/h4>\n<p>\u9519\u8bef\uff1a<\/p>\n<pre><code class=\"language-c++\">int a[3];\n...;\n\nif (a &gt; 0)\n  ...;<\/code><\/pre>\n<p>\u8be5\u5224\u65ad\u6c38\u8fdc\u4e3a\u771f\uff0c\u7b49\u4ef7\u4e8e:<\/p>\n<pre><code class=\"language-c++\">int a[3];\n...;\n\nif (&amp;a[0])\n  ...;<\/code><\/pre>\n<p>\u53ef\u80fd\u662f\uff1a<\/p>\n<pre><code class=\"language-c++\">int a[3];\n...;\n\nif(a[0] &gt; 0)\n  ...;<\/code><\/pre>\n<p>\u5f00\u542f\u8db3\u591f\u7684\u7f16\u8bd1\u5668\u8b66\u544a\uff08GCC \u4e2d\u4e3a <code>-Waddress<\/code>\uff0c\u5e76\u5df2\u5305\u542b\u5728 <code>-Wall<\/code> \u4e2d\uff09\uff0c\u5e76\u8bbe\u7f6e\u4e3a\u9519\u8bef\uff0c\u53ef\u4ee5\u5728\u7f16\u8bd1\u671f\u95f4\u53d1\u73b0\u8be5\u95ee\u9898\u3002<\/p>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4e2d\u98ce\u9669-\u903b\u8f91\u6f0f\u6d1e<\/code><\/p>\n<p><a id=\"1.8.3\"><\/a><\/p>\n<h4>8.3 \u3010\u5fc5\u987b\u3011\u4e0d\u5e94\u5f53\u5411\u6307\u9488\u8d4b\u4e88\u5199\u6b7b\u7684\u5730\u5740<\/h4>\n<p>\u7279\u6b8a\u60c5\u51b5\u9700\u8981\u7279\u6b8a\u5bf9\u5f85\uff08\u6bd4\u5982\u5f00\u53d1\u786c\u4ef6\u56fa\u4ef6\u65f6\u53ef\u80fd\u9700\u8981\u5199\u6b7b\uff09<\/p>\n<p>\u4f46\u662f\u5982\u679c\u662f\u7cfb\u7edf\u9a71\u52a8\u5f00\u53d1\u4e4b\u7c7b\u7684\uff0c\u5199\u6b7b\u53ef\u80fd\u4f1a\u5bfc\u81f4\u540e\u7eed\u7684\u95ee\u9898\u3002<\/p>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u5185\u5b58\u7834\u574f<\/code><\/p>\n<p><a id=\"1.8.4\"><\/a><\/p>\n<h4>8.4 \u3010\u5fc5\u987b\u3011\u68c0\u67e5\u7a7a\u6307\u9488<\/h4>\n<p>\u9519\u8bef\uff1a<\/p>\n<pre><code class=\"language-c++\">*foo = 100;\n\nif (!foo) {\n  ERROR(&quot;foobar&quot;);\n}<\/code><\/pre>\n<p>\u6b63\u786e\uff1a<\/p>\n<pre><code class=\"language-c++\">if (!foo) {\n  ERROR(&quot;foobar&quot;);\n}\n\n*foo = 100;<\/code><\/pre>\n<p>\u9519\u8bef\uff1a<\/p>\n<pre><code class=\"language-c++\">void Foo(char* bar) {\n  *bar = &#039;\\0&#039;;\n}<\/code><\/pre>\n<p>\u6b63\u786e\uff1a<\/p>\n<pre><code class=\"language-c++\">void Foo(char* bar) {\n  if(bar)\n    *bar = &#039;\\0&#039;;\n  else\n    ...;\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u4f4e\u98ce\u9669-\u62d2\u7edd\u670d\u52a1<\/code><\/p>\n<p><a id=\"1.8.5\"><\/a><\/p>\n<h4>8.5 \u3010\u5fc5\u987b\u3011\u91ca\u653e\u5b8c\u540e\u7f6e\u7a7a\u6307\u9488<\/h4>\n<p>\u5728\u5bf9\u6307\u9488\u8fdb\u884c\u91ca\u653e\u540e\uff0c\u9700\u8981\u5c06\u8be5\u6307\u9488\u8bbe\u7f6e\u4e3aNULL\uff0c\u4ee5\u9632\u6b62\u540e\u7eedfree\u6307\u9488\u7684\u8bef\u7528\uff0c\u5bfc\u81f4UAF\u7b49\u5176\u4ed6\u5185\u5b58\u7834\u574f\u95ee\u9898\u3002\u5c24\u5176\u662f\u5728\u7ed3\u6784\u4f53\u3001\u7c7b\u91cc\u9762\u5b58\u50a8\u7684\u539f\u59cb\u6307\u9488\u3002<\/p>\n<p>\u9519\u8bef\uff1a<\/p>\n<pre><code class=\"language-c++\">void foo() {\n  char* p = (char*)malloc(100);\n  memcpy(p, &quot;hello&quot;, 6);\n  printf(&quot;%s\\n&quot;, p);\n  free(p); \/\/ \u6b64\u65f6p\u6240\u6307\u5411\u7684\u5185\u5b58\u5df2\u88ab\u91ca\u653e\uff0c\u4f46\u662fp\u6240\u6307\u7684\u5730\u5740\u4ecd\u7136\u4e0d\u53d8\n  \/\/ \u672a\u8bbe\u7f6e\u4e3aNULL\uff0c\u53ef\u80fd\u5bfc\u81f4UAF\u7b49\u5185\u5b58\u9519\u8bef\n\n  if (p != NULL) {  \/\/ \u6ca1\u6709\u8d77\u5230\u9632\u9519\u4f5c\u7528\n    printf(&quot;%s\\n&quot;, p); \/\/ \u9519\u8bef\u4f7f\u7528\u5df2\u7ecf\u91ca\u653e\u7684\u5185\u5b58\n  }\n}<\/code><\/pre>\n<p>\u6b63\u786e\uff1a<\/p>\n<pre><code class=\"language-c++\">void foo() {\n  char* p = (char*)malloc(100);\n  memcpy(p, &quot;hello&quot;, 6);\n  \/\/ \u6b64\u65f6p\u6240\u6307\u5411\u7684\u5185\u5b58\u5df2\u88ab\u91ca\u653e\uff0c\u4f46\u662fp\u6240\u6307\u7684\u5730\u5740\u4ecd\u7136\u4e0d\u53d8\n  printf(&quot;%s\\n&quot;, p);\n  free(p);\n  \/\/\u91ca\u653e\u540e\u5c06\u6307\u9488\u8d4b\u503c\u4e3a\u7a7a\n  p = NULL;\n  if (p != NULL)  { \/\/ \u6ca1\u6709\u8d77\u5230\u9632\u9519\u4f5c\u7528\n    printf(&quot;%s\\n&quot;, p); \/\/ \u9519\u8bef\u4f7f\u7528\u5df2\u7ecf\u91ca\u653e\u7684\u5185\u5b58\n  }\n}<\/code><\/pre>\n<p>\u5bf9\u4e8e C++ \u4ee3\u7801\uff0c\u4f7f\u7528 string\u3001vector\u3001\u667a\u80fd\u6307\u9488\u7b49\u4ee3\u66ff\u539f\u59cb\u5185\u5b58\u7ba1\u7406\u673a\u5236\uff0c\u53ef\u4ee5\u5927\u91cf\u51cf\u5c11\u8fd9\u7c7b\u9519\u8bef\u3002<\/p>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u5185\u5b58\u7834\u574f<\/code><\/p>\n<p><a id=\"1.8.6\"><\/a><\/p>\n<h4>8.6 \u3010\u5fc5\u987b\u3011\u9632\u6b62\u9519\u8bef\u7684\u7c7b\u578b\u8f6c\u6362\uff08type confusion\uff09<\/h4>\n<p>\u5728\u5bf9\u6307\u9488\u3001\u5bf9\u8c61\u6216\u53d8\u91cf\u8fdb\u884c\u64cd\u4f5c\u65f6\uff0c\u9700\u8981\u80fd\u591f\u6b63\u786e\u5224\u65ad\u6240\u64cd\u4f5c\u5bf9\u8c61\u7684\u539f\u59cb\u7c7b\u578b\u3002\u5982\u679c\u4f7f\u7528\u4e86\u4e0e\u539f\u59cb\u7c7b\u578b\u4e0d\u517c\u5bb9\u7684\u7c7b\u578b\u8fdb\u884c\u8bbf\u95ee\uff0c\u5219\u5b58\u5728\u5b89\u5168\u9690\u60a3\u3002<\/p>\n<p>\u9519\u8bef\uff1a<\/p>\n<pre><code class=\"language-c++\">const int NAME_TYPE = 1;\nconst int ID_TYPE = 2;\n\n\/\/ \u8be5\u7c7b\u578b\u6839\u636e msg_type \u8fdb\u884c\u533a\u5206\uff0c\u5982\u679c\u5728\u5bf9MessageBuffer\u8fdb\u884c\u64cd\u4f5c\u65f6\u6ca1\u6709\u5224\u65ad\u76ee\u6807\u5bf9\u8c61\uff0c\u5219\u5b58\u5728\u7c7b\u578b\u6df7\u6dc6\nstruct MessageBuffer {\n  int msg_type;\n  union {\n    const char *name;\n    int name_id;\n  };\n};\n\nvoid Foo() {\n  struct MessageBuffer buf;\n  const char* default_message = &quot;Hello World&quot;;\n  \/\/ \u8bbe\u7f6e\u8be5\u6d88\u606f\u7c7b\u578b\u4e3a NAME_TYPE\uff0c\u56e0\u6b64buf\u9884\u671f\u7684\u7c7b\u578b\u4e3a msg_type + name\n  buf.msg_type = NAME_TYPE;\n  buf.name = default_message;\n  printf(&quot;Pointer of buf.name is %p\\n&quot;, buf.name);\n\n  \/\/ \u6ca1\u6709\u5224\u65ad\u76ee\u6807\u6d88\u606f\u7c7b\u578b\u662f\u5426\u4e3aID_TYPE\uff0c\u76f4\u63a5\u4fee\u6539nameID\uff0c\u5bfc\u81f4\u7c7b\u578b\u6df7\u6dc6\n  buf.name_id = user_controlled_value;\n\n  if (buf.msg_type == NAME_TYPE) {\n    printf(&quot;Pointer of buf.name is now %p\\n&quot;, buf.name);\n    \/\/ \u4ee5NAME_TYPE\u4f5c\u4e3a\u7c7b\u578b\u64cd\u4f5c\uff0c\u53ef\u80fd\u5bfc\u81f4\u975e\u6cd5\u5185\u5b58\u8bfb\u5199\n    printf(&quot;Message: %s\\n&quot;, buf.name);\n  } else {\n    printf(&quot;Message: Use ID %d\\n&quot;, buf.name_id);\n  }\n}<\/code><\/pre>\n<p>\u6b63\u786e\uff08\u5224\u65ad\u64cd\u4f5c\u7684\u76ee\u6807\u662f\u5426\u662f\u9884\u671f\u7c7b\u578b\uff09\uff1a<\/p>\n<pre><code class=\"language-c++\">void Foo() {\n  struct MessageBuffer buf;\n  const char* default_message = &quot;Hello World&quot;;\n  \/\/ \u8bbe\u7f6e\u8be5\u6d88\u606f\u7c7b\u578b\u4e3a NAME_TYPE\uff0c\u56e0\u6b64buf\u9884\u671f\u7684\u7c7b\u578b\u4e3a msg_type + name\n  buf.msg_type = NAME_TYPE;\n  buf.name = default_msessage;\n  printf(&quot;Pointer of buf.name is %p\\n&quot;, buf.name);\n\n  \/\/ \u5224\u65ad\u76ee\u6807\u6d88\u606f\u7c7b\u578b\u662f\u5426\u4e3a ID_TYPE\uff0c\u4e0d\u662f\u9884\u671f\u7c7b\u578b\u5219\u505a\u5bf9\u5e94\u64cd\u4f5c\n  if (buf.msg_type == ID_TYPE)\n    buf.name_id = user_controlled_value;\n\n  if (buf.msg_type == NAME_TYPE) {\n    printf(&quot;Pointer of buf.name is now %p\\n&quot;, buf.name);\n    printf(&quot;Message: %s\\n&quot;, buf.name);\n  } else {\n    printf(&quot;Message: Use ID %d\\n&quot;, buf.name_id);\n  }\n}<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u5185\u5b58\u7834\u574f<\/code><\/p>\n<p><a id=\"1.8.7\"><\/a><\/p>\n<h4>8.7 \u3010\u5fc5\u987b\u3011\u667a\u80fd\u6307\u9488\u4f7f\u7528\u5b89\u5168<\/h4>\n<p>\u5728\u4f7f\u7528\u667a\u80fd\u6307\u9488\u65f6\uff0c\u9632\u6b62\u5176\u548c\u539f\u59cb\u6307\u9488\u7684\u6df7\u7528\uff0c\u5426\u5219\u53ef\u80fd\u5bfc\u81f4\u5bf9\u8c61\u751f\u547d\u5468\u671f\u95ee\u9898\uff0c\u4f8b\u5982 UAF \u7b49\u5b89\u5168\u98ce\u9669\u3002<\/p>\n<p>\u9519\u8bef\u4f8b\u5b50\uff1a<\/p>\n<pre><code class=\"language-c++\">class Foo {\n public:\n  explicit Foo(int num) { data_ = num; };\n  void Function() { printf(&quot;Obj is %p, data = %d\\n&quot;, this, data_); };\n private:\n  int data_;\n};\n\nstd::unique_ptr&lt;Foo&gt; fool_u_ptr = nullptr;\nFoo* pfool_raw_ptr = nullptr;\n\nvoid Risk() {\n  fool_u_ptr = make_unique&lt;Foo&gt;(1);\n\n  \/\/ \u4ece\u72ec\u5360\u667a\u80fd\u6307\u9488\u4e2d\u83b7\u53d6\u539f\u59cb\u6307\u9488,&lt;Foo&gt;(1)\n  pfool_raw_ptr = fool_u_ptr.get();\n  \/\/ \u8c03\u7528&lt;Foo&gt;(1)\u7684\u51fd\u6570\n  pfool_raw_ptr-&gt;Function();\n\n  \/\/ \u72ec\u5360\u667a\u80fd\u6307\u9488\u91cd\u65b0\u8d4b\u503c\u540e\u4f1a\u91ca\u653e\u5185\u5b58\n  fool_u_ptr = make_unique&lt;Foo&gt;(2);\n  \/\/ \u901a\u8fc7\u539f\u59cb\u6307\u9488\u64cd\u4f5c\u4f1a\u5bfc\u81f4UAF\uff0cpfool_raw_ptr\u6307\u5411\u7684\u5bf9\u8c61\u5df2\u7ecf\u91ca\u653e\n  pfool_raw_ptr-&gt;Function();\n}\n\n\/\/ \u8f93\u51fa\uff1a\n\/\/ Obj is 0000027943087B80, data = 1\n\/\/ Obj is 0000027943087B80, data = -572662307<\/code><\/pre>\n<p>\u6b63\u786e\uff0c\u901a\u8fc7\u667a\u80fd\u6307\u9488\u64cd\u4f5c:<\/p>\n<pre><code class=\"language-c++\">void Safe() {\n  fool_u_ptr = make_unique&lt;Foo&gt;(1);\n  \/\/ \u8c03\u7528&lt;Foo&gt;(1)\u7684\u51fd\u6570\n  fool_u_ptr-&gt;Function();\n\n  fool_u_ptr = make_unique&lt;Foo&gt;(2);\n  \/\/ \u8c03\u7528&lt;Foo&gt;(2)\u7684\u51fd\u6570\n  fool_u_ptr-&gt;Function();\n}\n\n\/\/ \u8f93\u51fa\uff1a\n\/\/ Obj is 000002C7BB550830, data = 1\n\/\/ Obj is 000002C7BB557AF0, data = 2<\/code><\/pre>\n<p>\u5173\u8054\u6f0f\u6d1e:<\/p>\n<p><code>\u9ad8\u98ce\u9669-\u5185\u5b58\u7834\u574f<\/code><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u901a\u7528\u5b89\u5168\u6307\u5357 1 C\/C++\u4f7f\u7528\u9519\u8bef 1.1 \u3010\u5fc5\u987b\u3011\u4e0d\u5f97\u76f4\u63a5\u4f7f\u7528\u65e0\u957f\u5ea6\u9650\u5236\u7684\u5b57\u7b26\u62f7\u8d1d\u51fd\u6570 \u4e0d\u5e94\u76f4\u63a5\u4f7f\u7528legacy\u7684\u5b57\u7b26\u4e32\u62f7\u8d1d\u3001\u8f93\u5165\u51fd   \u2026 &#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0},"categories":[150],"tags":[],"_links":{"self":[{"href":"\/index.php?rest_route=\/wp\/v2\/posts\/2031"}],"collection":[{"href":"\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2031"}],"version-history":[{"count":1,"href":"\/index.php?rest_route=\/wp\/v2\/posts\/2031\/revisions"}],"predecessor-version":[{"id":2032,"href":"\/index.php?rest_route=\/wp\/v2\/posts\/2031\/revisions\/2032"}],"wp:attachment":[{"href":"\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2031"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2031"},{"taxonomy":"post_tag","embeddable":true,"href":"\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2031"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}