get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/98523/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 98523,
    "url": "http://patches.dpdk.org/api/patches/98523/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20210910020147.148019-1-zhihongx.peng@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20210910020147.148019-1-zhihongx.peng@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210910020147.148019-1-zhihongx.peng@intel.com",
    "date": "2021-09-10T02:01:47",
    "name": "Enable AddressSanitizer feature on DPDK",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "272ce918363ef554984f1b90a14d67f97852af5e",
    "submitter": {
        "id": 1643,
        "url": "http://patches.dpdk.org/api/people/1643/?format=api",
        "name": "Peng, ZhihongX",
        "email": "zhihongx.peng@intel.com"
    },
    "delegate": {
        "id": 24651,
        "url": "http://patches.dpdk.org/api/users/24651/?format=api",
        "username": "dmarchand",
        "first_name": "David",
        "last_name": "Marchand",
        "email": "david.marchand@redhat.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20210910020147.148019-1-zhihongx.peng@intel.com/mbox/",
    "series": [
        {
            "id": 18811,
            "url": "http://patches.dpdk.org/api/series/18811/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=18811",
            "date": "2021-09-10T02:01:47",
            "name": "Enable AddressSanitizer feature on DPDK",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/18811/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/98523/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/98523/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 3EB06A0548;\n\tFri, 10 Sep 2021 04:10:55 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id AFABC4003F;\n\tFri, 10 Sep 2021 04:10:54 +0200 (CEST)",
            "from mga11.intel.com (mga11.intel.com [192.55.52.93])\n by mails.dpdk.org (Postfix) with ESMTP id 31FA94003E\n for <dev@dpdk.org>; Fri, 10 Sep 2021 04:10:52 +0200 (CEST)",
            "from fmsmga008.fm.intel.com ([10.253.24.58])\n by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 09 Sep 2021 19:10:52 -0700",
            "from unknown (HELO localhost.localdomain) ([10.240.183.65])\n by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 09 Sep 2021 19:10:49 -0700"
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6200,9189,10102\"; a=\"217802406\"",
            "E=Sophos;i=\"5.85,282,1624345200\"; d=\"scan'208\";a=\"217802406\"",
            "E=Sophos;i=\"5.85,282,1624345200\"; d=\"scan'208\";a=\"504862450\""
        ],
        "From": "zhihongx.peng@intel.com",
        "To": "anatoly.burakov@intel.com, konstantin.ananyev@intel.com,\n stephen@networkplumber.org",
        "Cc": "dev@dpdk.org, xueqin.lin@intel.com, Zhihong Peng <zhihongx.peng@intel.com>",
        "Date": "Fri, 10 Sep 2021 02:01:47 +0000",
        "Message-Id": "<20210910020147.148019-1-zhihongx.peng@intel.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH] Enable AddressSanitizer feature on DPDK",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Zhihong Peng <zhihongx.peng@intel.com>\n\nAddressSanitizer (ASan) is a google memory error detect\nstandard tool. It could help to detect use-after-free and\n{heap,stack,global}-buffer overflow bugs in C/C++ programs,\nprint detailed error information when error happens, large\nimprove debug efficiency.\n\nBy referring to its implementation algorithm\n(https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm),\nenable heap-buffer-overflow and use-after-free functions on dpdk.\n\nHere is an example of heap-buffer-overflow bug:\n\t......\n        char *p = rte_zmalloc(NULL, 7, 0);\n        p[7] = 'a';\n\t......\n\nHere is an example of use-after-free bug:\n\t......\n        char *p = rte_zmalloc(NULL, 7, 0);\n        rte_free(p);\n        *p = 'a';\n\t......\n\nIf you want to use this feature,\nyou need to add below compilation options when compiling code:\n-Dbuildtype=debug -Db_lundef=false -Db_sanitize=address\n\"-Dbuildtype=debug\": Display code information when coredump occurs\nin the program.\n\"-Db_lundef=false\": It is enabled by default, and needs to be\ndisabled when using asan.\n\nSigned-off-by: Xueqin Lin <xueqin.lin@intel.com>\nSigned-off-by: Zhihong Peng <zhihongx.peng@intel.com>\n---\n app/test/meson.build                      |   2 +\n app/test/test_asan_heap_buffer_overflow.c |  30 ++++\n app/test/test_asan_use_after_free.c       |  31 ++++\n doc/guides/prog_guide/asan.rst            | 130 ++++++++++++++++\n doc/guides/prog_guide/index.rst           |   1 +\n lib/eal/common/malloc_elem.c              |  26 +++-\n lib/eal/common/malloc_elem.h              | 172 +++++++++++++++++++++-\n lib/eal/common/malloc_heap.c              |  12 ++\n lib/eal/common/meson.build                |   4 +\n lib/eal/common/rte_malloc.c               |   9 +-\n lib/pipeline/rte_swx_pipeline.c           |   4 +-\n 11 files changed, 416 insertions(+), 5 deletions(-)\n create mode 100644 app/test/test_asan_heap_buffer_overflow.c\n create mode 100644 app/test/test_asan_use_after_free.c\n create mode 100644 doc/guides/prog_guide/asan.rst",
    "diff": "diff --git a/app/test/meson.build b/app/test/meson.build\nindex a7611686ad..12a366bcec 100644\n--- a/app/test/meson.build\n+++ b/app/test/meson.build\n@@ -150,6 +150,8 @@ test_sources = files(\n         'test_trace_perf.c',\n         'test_version.c',\n         'virtual_pmd.c',\n+\t'test_asan_heap_buffer_overflow.c',\n+        'test_asan_use_after_free.c',\n )\n \n test_deps = [\ndiff --git a/app/test/test_asan_heap_buffer_overflow.c b/app/test/test_asan_heap_buffer_overflow.c\nnew file mode 100644\nindex 0000000000..001e2853f8\n--- /dev/null\n+++ b/app/test/test_asan_heap_buffer_overflow.c\n@@ -0,0 +1,30 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) <2021> Intel Corporation\n+ */\n+\n+#include <stdint.h>\n+#include <stdio.h>\n+#include <stdarg.h>\n+#include <errno.h>\n+#include <string.h>\n+#include <rte_per_lcore.h>\n+#include <rte_errno.h>\n+#include <rte_string_fns.h>\n+#include <rte_malloc.h>\n+\n+#include \"test.h\"\n+\n+static int\n+asan_heap_buffer_overflow(void)\n+{\n+\tchar *p = rte_zmalloc(NULL, 9, 0);\n+\tif (!p) {\n+\t\tprintf(\"rte_zmalloc error.\");\n+\t\treturn -1;\n+\t}\n+\tp[9] = 'a';\n+\n+\treturn 0;\n+}\n+\n+REGISTER_TEST_COMMAND(asan_heap_buffer_overflow_autotest, asan_heap_buffer_overflow);\ndiff --git a/app/test/test_asan_use_after_free.c b/app/test/test_asan_use_after_free.c\nnew file mode 100644\nindex 0000000000..b9c4ec8eba\n--- /dev/null\n+++ b/app/test/test_asan_use_after_free.c\n@@ -0,0 +1,31 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) <2021> Intel Corporation\n+ */\n+\n+#include <stdint.h>\n+#include <stdio.h>\n+#include <stdarg.h>\n+#include <errno.h>\n+#include <string.h>\n+#include <rte_per_lcore.h>\n+#include <rte_errno.h>\n+#include <rte_string_fns.h>\n+#include <rte_malloc.h>\n+\n+#include \"test.h\"\n+\n+static int\n+asan_use_after_free(void)\n+{\n+\tchar *p = rte_zmalloc(NULL, 9, 0);\n+\tif (!p) {\n+\t\tprintf(\"rte_zmalloc error.\");\n+\t\treturn -1;\n+\t}\n+\trte_free(p);\n+\t*p = 'a';\n+\n+\treturn 0;\n+}\n+\n+REGISTER_TEST_COMMAND(asan_use_after_free_autotest, asan_use_after_free);\ndiff --git a/doc/guides/prog_guide/asan.rst b/doc/guides/prog_guide/asan.rst\nnew file mode 100644\nindex 0000000000..721a99b946\n--- /dev/null\n+++ b/doc/guides/prog_guide/asan.rst\n@@ -0,0 +1,130 @@\n+.. Copyright (c) <2021>, Intel Corporation\n+   All rights reserved.\n+\n+Memory error detect standard tool - AddressSanitizer(Asan)\n+==========================================================\n+\n+AddressSanitizer (ASan) is a google memory error detect\n+standard tool. It could help to detect use-after-free and\n+{heap,stack,global}-buffer overflow bugs in C/C++ programs,\n+print detailed error information when error happens, large\n+improve debug efficiency.\n+\n+By referring to its implementation algorithm\n+(https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm),\n+enabled heap-buffer-overflow and use-after-free functions on dpdk.\n+DPDK ASAN function currently only supports on Linux x86_64.\n+\n+AddressSanitizer is a part of LLVM(3.1+)and GCC(4.8+).\n+\n+Example heap-buffer-overflow error\n+----------------------------------\n+\n+Following error was reported when Asan was enabled::\n+\n+    app/test/test_asan_heap_buffer_overflow.c:25: Applied 9 bytes\n+    of memory, but accessed the 10th byte of memory, so heap-buffer-overflow\n+    appeared.\n+\n+Below code results in this error::\n+\n+    char *p = rte_zmalloc(NULL, 9, 0);\n+    if (!p) {\n+        printf(\"rte_zmalloc error.\");\n+        return -1;\n+    }\n+    p[9] = 'a';\n+\n+The error log::\n+\n+    ==49433==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7f773fafa249 at pc 0x5556b13bdae4 bp 0x7ffeb4965e40 sp 0x7ffeb4965e30 WRITE of size 1 at 0x7f773fafa249 thread T0\n+    #0 0x5556b13bdae3 in asan_heap_buffer_overflow ../app/test/test_asan_heap_buffer_overflow.c:25\n+    #1 0x5556b043e9d4 in cmd_autotest_parsed ../app/test/commands.c:71\n+    #2 0x5556b1cdd4b0 in cmdline_parse ../lib/cmdline/cmdline_parse.c:290\n+    #3 0x5556b1cd8987 in cmdline_valid_buffer ../lib/cmdline/cmdline.c:26\n+    #4 0x5556b1ce477a in rdline_char_in ../lib/cmdline/cmdline_rdline.c:421\n+    #5 0x5556b1cd923e in cmdline_in ../lib/cmdline/cmdline.c:149\n+    #6 0x5556b1cd9769 in cmdline_interact ../lib/cmdline/cmdline.c:223\n+    #7 0x5556b045f53b in main ../app/test/test.c:234\n+    #8 0x7f7f1eba90b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)\n+    #9 0x5556b043e70d in _start (/home/pzh/yyy/x86_64-native-linuxapp-gcc/app/test/dpdk-test+0x7ce70d)\n+\n+    Address 0x7f773fafa249 is a wild pointer.\n+    SUMMARY: AddressSanitizer: heap-buffer-overflow ../app/test/test_asan_heap_buffer_overflow.c:25 in asan_heap_buffer_overflow\n+    Shadow bytes around the buggy address:\n+    0x0fef67f573f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n+    0x0fef67f57400: fa fa 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n+    0x0fef67f57410: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n+    0x0fef67f57420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n+    0x0fef67f57430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n+    =>0x0fef67f57440: 00 00 00 00 00 00 fa fa 00[01]fa 00 00 00 00 00\n+    0x0fef67f57450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n+    0x0fef67f57460: 00 00 00 00 00 00 fa fa 00 00 00 00 00 00 00 00\n+    0x0fef67f57470: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n+    0x0fef67f57480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n+\n+Example use-after-free error\n+----------------------------\n+\n+Following error was reported when Asan was enabled::\n+\n+    app/test/test_asan_use_after_free.c:26: Applied for 9 bytes of\n+    memory, and accessed the first byte after released, so\n+    heap-use-after-free appeared.\n+\n+Below code results in this error::\n+\n+\tchar *p = rte_zmalloc(NULL, 9, 0);\n+\tif (!p) {\n+        printf(\"rte_zmalloc error.\");\n+        return -1;\n+    }\n+\trte_free(p);\n+\t*p = 'a';\n+\n+The error log::\n+\n+    ==49478==ERROR: AddressSanitizer: heap-use-after-free on address 0x7fe2ffafa240 at pc 0x56409b084bc8 bp 0x7ffef62c57d0 sp 0x7ffef62c57c0 WRITE of size 1 at 0x7fe2ffafa240 thread T0\n+    #0 0x56409b084bc7 in asan_use_after_free ../app/test/test_asan_use_after_free.c:26\n+    #1 0x56409a1059d4 in cmd_autotest_parsed ../app/test/commands.c:71\n+    #2 0x56409b9a44b0 in cmdline_parse ../lib/cmdline/cmdline_parse.c:290\n+    #3 0x56409b99f987 in cmdline_valid_buffer ../lib/cmdline/cmdline.c:26\n+    #4 0x56409b9ab77a in rdline_char_in ../lib/cmdline/cmdline_rdline.c:421\n+    #5 0x56409b9a023e in cmdline_in ../lib/cmdline/cmdline.c:149\n+    #6 0x56409b9a0769 in cmdline_interact ../lib/cmdline/cmdline.c:223\n+    #7 0x56409a12653b in main ../app/test/test.c:234\n+    #8 0x7feafafc20b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)\n+    #9 0x56409a10570d in _start (/home/pzh/yyy/x86_64-native-linuxapp-gcc/app/test/dpdk-test+0x7ce70d)\n+\n+    Address 0x7fe2ffafa240 is a wild pointer.\n+    SUMMARY: AddressSanitizer: heap-use-after-free ../app/test/test_asan_use_after_free.c:26 in asan_use_after_free\n+    Shadow bytes around the buggy address:\n+    0x0ffcdff573f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n+    0x0ffcdff57400: fa fa 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n+    0x0ffcdff57410: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n+    0x0ffcdff57420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n+    0x0ffcdff57430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n+    =>0x0ffcdff57440: 00 00 00 00 00 00 00 00[fd]fd fd fd fd fd fd fd\n+    0x0ffcdff57450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n+    0x0ffcdff57460: 00 00 00 00 00 00 fa fa 00 00 00 00 00 00 00 00\n+    0x0ffcdff57470: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n+    0x0ffcdff57480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n+    0x0ffcdff57490: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n+\n+Usage\n+-----\n+\n+meson build\n+^^^^^^^^^^^\n+\n+To enable Asan in meson build system, use following meson build command:\n+\n+Example usage::\n+\n+ meson build -Dbuildtype=debug -Db_lundef=false -Db_sanitize=address\n+ ninja -C build\n+\n+.. Note::\n+\n+  Centos8 needs to install libasan separately.\n+  If the program uses cmdline, when a memory bug occurs, need to execute the \"stty echo\" command.\ndiff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst\nindex 2dce507f46..df8a4b93e1 100644\n--- a/doc/guides/prog_guide/index.rst\n+++ b/doc/guides/prog_guide/index.rst\n@@ -71,3 +71,4 @@ Programmer's Guide\n     lto\n     profile_app\n     glossary\n+    asan\ndiff --git a/lib/eal/common/malloc_elem.c b/lib/eal/common/malloc_elem.c\nindex c2c9461f1d..bdd20a162e 100644\n--- a/lib/eal/common/malloc_elem.c\n+++ b/lib/eal/common/malloc_elem.c\n@@ -446,6 +446,8 @@ malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align,\n \t\tstruct malloc_elem *new_free_elem =\n \t\t\t\tRTE_PTR_ADD(new_elem, size + MALLOC_ELEM_OVERHEAD);\n \n+\t\tasan_clear_split_alloczone(new_free_elem);\n+\n \t\tsplit_elem(elem, new_free_elem);\n \t\tmalloc_elem_free_list_insert(new_free_elem);\n \n@@ -458,6 +460,8 @@ malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align,\n \t\telem->state = ELEM_BUSY;\n \t\telem->pad = old_elem_size;\n \n+\t\tasan_clear_alloczone(elem);\n+\n \t\t/* put a dummy header in padding, to point to real element header */\n \t\tif (elem->pad > 0) { /* pad will be at least 64-bytes, as everything\n \t\t                     * is cache-line aligned */\n@@ -470,12 +474,18 @@ malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align,\n \t\treturn new_elem;\n \t}\n \n+\tasan_clear_split_alloczone(new_elem);\n+\n \t/* we are going to split the element in two. The original element\n \t * remains free, and the new element is the one allocated.\n \t * Re-insert original element, in case its new size makes it\n \t * belong on a different list.\n \t */\n+\n \tsplit_elem(elem, new_elem);\n+\n+\tasan_clear_alloczone(new_elem);\n+\n \tnew_elem->state = ELEM_BUSY;\n \tmalloc_elem_free_list_insert(elem);\n \n@@ -601,6 +611,8 @@ malloc_elem_hide_region(struct malloc_elem *elem, void *start, size_t len)\n \tif (next && next_elem_is_adjacent(elem)) {\n \t\tlen_after = RTE_PTR_DIFF(next, hide_end);\n \t\tif (len_after >= MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE) {\n+\t\t\tasan_clear_split_alloczone(hide_end);\n+\n \t\t\t/* split after */\n \t\t\tsplit_elem(elem, hide_end);\n \n@@ -615,6 +627,8 @@ malloc_elem_hide_region(struct malloc_elem *elem, void *start, size_t len)\n \tif (prev && prev_elem_is_adjacent(elem)) {\n \t\tlen_before = RTE_PTR_DIFF(hide_start, elem);\n \t\tif (len_before >= MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE) {\n+\t\t\tasan_clear_split_alloczone(hide_start);\n+\n \t\t\t/* split before */\n \t\t\tsplit_elem(elem, hide_start);\n \n@@ -628,6 +642,8 @@ malloc_elem_hide_region(struct malloc_elem *elem, void *start, size_t len)\n \t\t}\n \t}\n \n+\tasan_clear_alloczone(elem);\n+\n \tremove_elem(elem);\n }\n \n@@ -641,8 +657,10 @@ malloc_elem_resize(struct malloc_elem *elem, size_t size)\n \tconst size_t new_size = size + elem->pad + MALLOC_ELEM_OVERHEAD;\n \n \t/* if we request a smaller size, then always return ok */\n-\tif (elem->size >= new_size)\n+\tif (elem->size >= new_size) {\n+\t\tasan_clear_alloczone(elem);\n \t\treturn 0;\n+\t}\n \n \t/* check if there is a next element, it's free and adjacent */\n \tif (!elem->next || elem->next->state != ELEM_FREE ||\n@@ -661,9 +679,15 @@ malloc_elem_resize(struct malloc_elem *elem, size_t size)\n \t\t/* now we have a big block together. Lets cut it down a bit, by splitting */\n \t\tstruct malloc_elem *split_pt = RTE_PTR_ADD(elem, new_size);\n \t\tsplit_pt = RTE_PTR_ALIGN_CEIL(split_pt, RTE_CACHE_LINE_SIZE);\n+\n+\t\tasan_clear_split_alloczone(split_pt);\n+\n \t\tsplit_elem(elem, split_pt);\n \t\tmalloc_elem_free_list_insert(split_pt);\n \t}\n+\n+\tasan_clear_alloczone(elem);\n+\n \treturn 0;\n }\n \ndiff --git a/lib/eal/common/malloc_elem.h b/lib/eal/common/malloc_elem.h\nindex a1e5f7f02c..0e91ace17f 100644\n--- a/lib/eal/common/malloc_elem.h\n+++ b/lib/eal/common/malloc_elem.h\n@@ -36,10 +36,20 @@ struct malloc_elem {\n \tuint64_t header_cookie;         /* Cookie marking start of data */\n \t                                /* trailer cookie at start + size */\n #endif\n+#ifdef RTE_MALLOC_ASAN\n+\tsize_t user_size;\n+\tuint64_t asan_cookie[2]; /*must be next to header_cookie*/\n+#endif\n } __rte_cache_aligned;\n \n+static const unsigned MALLOC_ELEM_HEADER_LEN = sizeof(struct malloc_elem);\n+\n #ifndef RTE_MALLOC_DEBUG\n+#ifdef RTE_MALLOC_ASAN\n+static const unsigned MALLOC_ELEM_TRAILER_LEN = RTE_CACHE_LINE_SIZE;\n+#else\n static const unsigned MALLOC_ELEM_TRAILER_LEN = 0;\n+#endif\n \n /* dummy function - just check if pointer is non-null */\n static inline int\n@@ -90,9 +100,169 @@ malloc_elem_cookies_ok(const struct malloc_elem *elem)\n \n #endif\n \n-static const unsigned MALLOC_ELEM_HEADER_LEN = sizeof(struct malloc_elem);\n #define MALLOC_ELEM_OVERHEAD (MALLOC_ELEM_HEADER_LEN + MALLOC_ELEM_TRAILER_LEN)\n \n+#ifdef RTE_MALLOC_ASAN\n+\n+#define ASAN_SHADOW_GRAIN_SIZE\t8\n+#define ASAN_MEM_FREE_FLAG\t0xfd\n+#define ASAN_MEM_REDZONE_FLAG\t0xfa\n+#define ASAN_MEM_TO_SHADOW(mem) (((mem) >> 3) + 0x00007fff8000)\n+\n+#if defined(__clang__)\n+__attribute__((no_sanitize(\"address\", \"hwaddress\")))\n+#else\n+__attribute__((no_sanitize_address))\n+#endif\n+static inline void\n+asan_set_shadow(void *addr, char val)\n+{\n+\t*(char *)addr = val;\n+}\n+\n+static inline void\n+asan_set_zone(void *ptr, size_t len, uint32_t val)\n+{\n+\tsize_t offset;\n+\tchar *shadow;\n+\tsize_t zone_len = len / ASAN_SHADOW_GRAIN_SIZE;\n+\tif (len % ASAN_SHADOW_GRAIN_SIZE != 0)\n+\t\tzone_len += 1;\n+\n+\tfor (size_t i = 0; i < zone_len; i++) {\n+\t\toffset = i * ASAN_SHADOW_GRAIN_SIZE;\n+\t\tshadow = (char *)ASAN_MEM_TO_SHADOW(((int64_t)ptr + offset));\n+\t\tasan_set_shadow(shadow, val);\n+\t}\n+}\n+\n+/*\n+ * When the memory is released, the release mark is\n+ * set in the corresponding range of the shadow area.\n+ */\n+static inline void\n+asan_set_freezone(void *ptr, size_t size)\n+{\n+\tasan_set_zone(ptr, size, ASAN_MEM_FREE_FLAG);\n+}\n+\n+/*\n+ * When the memory is allocated, memory state must set as accessible.\n+ */\n+static inline void\n+asan_clear_alloczone(struct malloc_elem *elem)\n+{\n+\tasan_set_zone((void *)elem, elem->size, 0x0);\n+}\n+\n+static inline void\n+asan_clear_split_alloczone(struct malloc_elem *elem)\n+{\n+\tvoid *ptr = RTE_PTR_SUB(elem, MALLOC_ELEM_TRAILER_LEN);\n+\tasan_set_zone(ptr, MALLOC_ELEM_OVERHEAD, 0x0);\n+}\n+\n+/*\n+ * When the memory is allocated, the memory boundary is\n+ * marked in the corresponding range of the shadow area.\n+ */\n+static inline void\n+asan_set_redzone(struct malloc_elem *elem, size_t user_size)\n+{\n+\tuint64_t ptr;\n+\tchar *shadow;\n+\tif (elem != NULL) {\n+\t\tif (elem->state != ELEM_PAD)\n+\t\t\telem = RTE_PTR_ADD(elem, elem->pad);\n+\n+\t\telem->user_size = user_size;\n+\n+\t\t/* Set mark before the start of the allocated memory */\n+\t\tptr = (uint64_t)RTE_PTR_ADD(elem, MALLOC_ELEM_HEADER_LEN)\n+\t\t\t- ASAN_SHADOW_GRAIN_SIZE;\n+\t\tshadow = (char *)ASAN_MEM_TO_SHADOW(ptr);\n+\t\tasan_set_shadow(shadow, ASAN_MEM_REDZONE_FLAG);\n+\t\tshadow = (char *)ASAN_MEM_TO_SHADOW(ptr\n+\t\t\t\t- ASAN_SHADOW_GRAIN_SIZE);\n+\t\tasan_set_shadow(shadow, ASAN_MEM_REDZONE_FLAG);\n+\n+\t\t/* Set mark after the end of the allocated memory */\n+\t\tptr = (uint64_t)RTE_PTR_ADD(elem, MALLOC_ELEM_HEADER_LEN\n+\t\t\t\t+ elem->user_size);\n+\t\tshadow = (char *)ASAN_MEM_TO_SHADOW(ptr);\n+\t\tuint32_t val = (ptr % ASAN_SHADOW_GRAIN_SIZE);\n+\t\tval = (val == 0) ? ASAN_MEM_REDZONE_FLAG : val;\n+\t\tasan_set_shadow(shadow, val);\n+\t\tshadow = (char *)ASAN_MEM_TO_SHADOW(ptr\n+\t\t\t\t+ ASAN_SHADOW_GRAIN_SIZE);\n+\t\tasan_set_shadow(shadow, ASAN_MEM_REDZONE_FLAG);\n+\t}\n+}\n+\n+/*\n+ * When the memory is released, the mark of the memory boundary\n+ * in the corresponding range of the shadow area is cleared.\n+ */\n+static inline void\n+asan_clear_redzone(struct malloc_elem *elem)\n+{\n+\tuint64_t ptr;\n+\tchar *shadow;\n+\tif (elem != NULL) {\n+\t\telem = RTE_PTR_ADD(elem, elem->pad);\n+\n+\t\t/* Clear mark before the start of the allocated memory */\n+\t\tptr = (uint64_t)RTE_PTR_ADD(elem, MALLOC_ELEM_HEADER_LEN)\n+\t\t\t- ASAN_SHADOW_GRAIN_SIZE;\n+\t\tshadow = (char *)ASAN_MEM_TO_SHADOW(ptr);\n+\t\tasan_set_shadow(shadow, 0x00);\n+\t\tshadow = (char *)ASAN_MEM_TO_SHADOW(ptr\n+\t\t\t\t- ASAN_SHADOW_GRAIN_SIZE);\n+\t\tasan_set_shadow(shadow, 0x00);\n+\n+\t\t/* Clear mark after the end of the allocated memory */\n+\t\tptr = (uint64_t)RTE_PTR_ADD(elem, MALLOC_ELEM_HEADER_LEN\n+\t\t\t\t+ elem->user_size);\n+\t\tshadow = (char *)ASAN_MEM_TO_SHADOW(ptr);\n+\t\tasan_set_shadow(shadow, 0x00);\n+\t\tshadow = (char *)ASAN_MEM_TO_SHADOW(ptr\n+\t\t\t\t+ ASAN_SHADOW_GRAIN_SIZE);\n+\t\tasan_set_shadow(shadow, 0x00);\n+\t}\n+}\n+\n+static inline size_t\n+old_malloc_size(struct malloc_elem *elem)\n+{\n+\tif (elem->state != ELEM_PAD)\n+\t\telem = RTE_PTR_ADD(elem, elem->pad);\n+\n+\treturn elem->user_size;\n+}\n+#else\n+static inline void\n+asan_set_freezone(void *ptr __rte_unused, size_t size __rte_unused) { }\n+\n+static inline void\n+asan_clear_alloczone(struct malloc_elem *elem __rte_unused) { }\n+\n+static inline void\n+asan_clear_split_alloczone(struct malloc_elem *elem __rte_unused) { }\n+\n+static inline void\n+asan_set_redzone(struct malloc_elem *elem __rte_unused,\n+\t\t\t\t\tsize_t user_size __rte_unused) { }\n+\n+static inline void\n+asan_clear_redzone(struct malloc_elem *elem __rte_unused) { }\n+\n+static inline size_t\n+old_malloc_size(struct malloc_elem *elem)\n+{\n+\treturn elem->size - elem->pad - MALLOC_ELEM_OVERHEAD;\n+}\n+#endif\n+\n /*\n  * Given a pointer to the start of a memory block returned by malloc, get\n  * the actual malloc_elem header for that block.\ndiff --git a/lib/eal/common/malloc_heap.c b/lib/eal/common/malloc_heap.c\nindex ee400f38ec..775d6789df 100644\n--- a/lib/eal/common/malloc_heap.c\n+++ b/lib/eal/common/malloc_heap.c\n@@ -237,6 +237,7 @@ heap_alloc(struct malloc_heap *heap, const char *type __rte_unused, size_t size,\n \t\tunsigned int flags, size_t align, size_t bound, bool contig)\n {\n \tstruct malloc_elem *elem;\n+\tsize_t user_size = size;\n \n \tsize = RTE_CACHE_LINE_ROUNDUP(size);\n \talign = RTE_CACHE_LINE_ROUNDUP(align);\n@@ -250,6 +251,8 @@ heap_alloc(struct malloc_heap *heap, const char *type __rte_unused, size_t size,\n \n \t\t/* increase heap's count of allocated elements */\n \t\theap->alloc_count++;\n+\n+\t\tasan_set_redzone(elem, user_size);\n \t}\n \n \treturn elem == NULL ? NULL : (void *)(&elem[1]);\n@@ -270,6 +273,8 @@ heap_alloc_biggest(struct malloc_heap *heap, const char *type __rte_unused,\n \n \t\t/* increase heap's count of allocated elements */\n \t\theap->alloc_count++;\n+\n+\t\tasan_set_redzone(elem, size);\n \t}\n \n \treturn elem == NULL ? NULL : (void *)(&elem[1]);\n@@ -841,6 +846,8 @@ malloc_heap_free(struct malloc_elem *elem)\n \tif (!malloc_elem_cookies_ok(elem) || elem->state != ELEM_BUSY)\n \t\treturn -1;\n \n+\tasan_clear_redzone(elem);\n+\n \t/* elem may be merged with previous element, so keep heap address */\n \theap = elem->heap;\n \tmsl = elem->msl;\n@@ -848,6 +855,9 @@ malloc_heap_free(struct malloc_elem *elem)\n \n \trte_spinlock_lock(&(heap->lock));\n \n+\tvoid *asan_ptr = RTE_PTR_ADD(elem, MALLOC_ELEM_HEADER_LEN + elem->pad);\n+\tsize_t asan_data_len = elem->size - MALLOC_ELEM_OVERHEAD - elem->pad;\n+\n \t/* mark element as free */\n \telem->state = ELEM_FREE;\n \n@@ -1001,6 +1011,8 @@ malloc_heap_free(struct malloc_elem *elem)\n \n \trte_mcfg_mem_write_unlock();\n free_unlock:\n+\tasan_set_freezone(asan_ptr, asan_data_len);\n+\n \trte_spinlock_unlock(&(heap->lock));\n \treturn ret;\n }\ndiff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build\nindex edfca77779..2f786841d0 100644\n--- a/lib/eal/common/meson.build\n+++ b/lib/eal/common/meson.build\n@@ -5,6 +5,10 @@ includes += include_directories('.')\n \n cflags += [ '-DABI_VERSION=\"@0@\"'.format(abi_version) ]\n \n+if get_option('b_sanitize').startswith('address')\n+\tcflags += '-DRTE_MALLOC_ASAN'\n+endif\n+\n if is_windows\n     sources += files(\n             'eal_common_bus.c',\ndiff --git a/lib/eal/common/rte_malloc.c b/lib/eal/common/rte_malloc.c\nindex 9d39e58c08..d0bec26920 100644\n--- a/lib/eal/common/rte_malloc.c\n+++ b/lib/eal/common/rte_malloc.c\n@@ -162,6 +162,8 @@ rte_calloc(const char *type, size_t num, size_t size, unsigned align)\n void *\n rte_realloc_socket(void *ptr, size_t size, unsigned int align, int socket)\n {\n+\tsize_t user_size;\n+\n \tif (ptr == NULL)\n \t\treturn rte_malloc_socket(NULL, size, align, socket);\n \n@@ -171,6 +173,8 @@ rte_realloc_socket(void *ptr, size_t size, unsigned int align, int socket)\n \t\treturn NULL;\n \t}\n \n+\tuser_size = size;\n+\n \tsize = RTE_CACHE_LINE_ROUNDUP(size), align = RTE_CACHE_LINE_ROUNDUP(align);\n \n \t/* check requested socket id and alignment matches first, and if ok,\n@@ -181,6 +185,9 @@ rte_realloc_socket(void *ptr, size_t size, unsigned int align, int socket)\n \t\t\tRTE_PTR_ALIGN(ptr, align) == ptr &&\n \t\t\tmalloc_heap_resize(elem, size) == 0) {\n \t\trte_eal_trace_mem_realloc(size, align, socket, ptr);\n+\n+\t\tasan_set_redzone(elem, user_size);\n+\n \t\treturn ptr;\n \t}\n \n@@ -192,7 +199,7 @@ rte_realloc_socket(void *ptr, size_t size, unsigned int align, int socket)\n \tif (new_ptr == NULL)\n \t\treturn NULL;\n \t/* elem: |pad|data_elem|data|trailer| */\n-\tconst size_t old_size = elem->size - elem->pad - MALLOC_ELEM_OVERHEAD;\n+\tconst size_t old_size = old_malloc_size(elem);\n \trte_memcpy(new_ptr, ptr, old_size < size ? old_size : size);\n \trte_free(ptr);\n \ndiff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c\nindex 8eb978a30c..aaa0107d02 100644\n--- a/lib/pipeline/rte_swx_pipeline.c\n+++ b/lib/pipeline/rte_swx_pipeline.c\n@@ -6340,7 +6340,7 @@ instr_meter_translate(struct rte_swx_pipeline *p,\n \t\treturn 0;\n \t}\n \n-\tCHECK(0, EINVAL);\n+\treturn -EINVAL;\n }\n \n static inline struct meter *\n@@ -8025,7 +8025,7 @@ instr_translate(struct rte_swx_pipeline *p,\n \t\t\t\t\t      instr,\n \t\t\t\t\t      data);\n \n-\tCHECK(0, EINVAL);\n+\treturn -EINVAL;\n }\n \n static struct instruction_data *\n",
    "prefixes": []
}