get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2216073,
    "url": "http://patchwork.ozlabs.org/api/patches/2216073/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/20260325192014.12049-1-sandipkambli79@gmail.com/",
    "project": {
        "id": 17,
        "url": "http://patchwork.ozlabs.org/api/projects/17/?format=api",
        "name": "GNU Compiler Collection",
        "link_name": "gcc",
        "list_id": "gcc-patches.gcc.gnu.org",
        "list_email": "gcc-patches@gcc.gnu.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260325192014.12049-1-sandipkambli79@gmail.com>",
    "list_archive_url": null,
    "date": "2026-03-25T19:20:13",
    "name": "analyzer: model strnlen",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "354907c3c68750bba8f46136f429b13203c1d8cf",
    "submitter": {
        "id": 92949,
        "url": "http://patchwork.ozlabs.org/api/people/92949/?format=api",
        "name": "Saish Sandip Kambali",
        "email": "sandipkambli79@gmail.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/20260325192014.12049-1-sandipkambli79@gmail.com/mbox/",
    "series": [
        {
            "id": 497502,
            "url": "http://patchwork.ozlabs.org/api/series/497502/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=497502",
            "date": "2026-03-25T19:20:13",
            "name": "analyzer: model strnlen",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/497502/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2216073/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2216073/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "gcc-patches@gcc.gnu.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@legolas.ozlabs.org",
            "gcc-patches@gcc.gnu.org"
        ],
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=CmXkb4kE;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)",
            "sourceware.org;\n\tdkim=pass (2048-bit key,\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=CmXkb4kE",
            "sourceware.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com",
            "sourceware.org; spf=pass smtp.mailfrom=gmail.com",
            "server2.sourceware.org;\n arc=none smtp.remote-ip=209.85.216.53"
        ],
        "Received": [
            "from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fgxZv6j58z1xy1\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 26 Mar 2026 06:20:55 +1100 (AEDT)",
            "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 756D24BB3BEF\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 25 Mar 2026 19:20:53 +0000 (GMT)",
            "from mail-pj1-f53.google.com (mail-pj1-f53.google.com\n [209.85.216.53])\n by sourceware.org (Postfix) with ESMTPS id 8AB3D4B9DB75\n for <gcc-patches@gcc.gnu.org>; Wed, 25 Mar 2026 19:20:20 +0000 (GMT)",
            "by mail-pj1-f53.google.com with SMTP id\n 98e67ed59e1d1-35b98def50bso154125a91.0\n for <gcc-patches@gcc.gnu.org>; Wed, 25 Mar 2026 12:20:20 -0700 (PDT)",
            "from ShreeKrishna.localdomain ([106.213.84.157])\n by smtp.gmail.com with ESMTPSA id\n 98e67ed59e1d1-35c03211351sm6626858a91.15.2026.03.25.12.20.17\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 25 Mar 2026 12:20:18 -0700 (PDT)"
        ],
        "DKIM-Filter": [
            "OpenDKIM Filter v2.11.0 sourceware.org 756D24BB3BEF",
            "OpenDKIM Filter v2.11.0 sourceware.org 8AB3D4B9DB75"
        ],
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 8AB3D4B9DB75",
        "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 8AB3D4B9DB75",
        "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1774466420; cv=none;\n b=D6etAYCfaWd8UIG0qJWdhQuj7PKkSL59ThP4OoEcJ+lPY1CcsUEJ98WQyM2DmbNQ1gszlUXgaKGhqOO0zk0t/q3rEn9JERpL372k78tGIF1gSewzwN6gEr4IJIi5cftYkR4sLIYI5VO13OMgHWcbopXkMDjWiD7eG7z7NmA/u+E=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1774466420; c=relaxed/simple;\n bh=xJOwLgq1NFBi5QomHvvQqGbZVQGIQbcuFBRNjdxerGo=;\n h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;\n b=TBER0M8ym4ohHOUn/2vLfVUvYTFSaZtIMk/8VIsWoA03sGjPAFrsEY+TmVDUI7/NiZy/Q42MtQJ7635aZOKINR7H13L8YBhpWPuA7sbmxLcCYSSfoWLfybkb21taErn37y5AxXaewGGyKGeNU6U1XHma9MmzEhC8uOg93q7tZlo=",
        "ARC-Authentication-Results": "i=1; server2.sourceware.org",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1774466419; x=1775071219; darn=gcc.gnu.org;\n h=content-transfer-encoding:mime-version:message-id:date:subject:cc\n :to:from:from:to:cc:subject:date:message-id:reply-to;\n bh=wEQG/ks8lg1pvSaxFz1pIAWy6Z9N0d7Nktxqp2xUr7U=;\n b=CmXkb4kE7me7gX88Ps5TxjnwmP2frcsqjtZpAyIhi1GRIm5FqZMCR7oYGsZZpKP70y\n D6hFhUkUd8gheR5IwBfbUIRHZq2GOoiMAR81RlbyOTF85BSe1SxmQBFDsgX7+ykhQqnP\n ojL7+NKCgNjLAmkBWdMZCJoiAhpBuqL4zzQhb3jrAJ4Bz9fq3M/Wz63Nocjo5VnBeaZ8\n J70ODa/ebLQ3qfAD7axKjwoKn9iAJj94S8qbMlTgX8iXKuhcDQO24x7zs0EBk5VXAStV\n 5Pcetu6jnuyBOaDRUr8ZB6sR4Rhw03jNUrf+bq34VPw7xWILh6npJQG8R3tmTZGfYZzi\n KPEw==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1774466419; x=1775071219;\n h=content-transfer-encoding:mime-version:message-id:date:subject:cc\n :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n :message-id:reply-to;\n bh=wEQG/ks8lg1pvSaxFz1pIAWy6Z9N0d7Nktxqp2xUr7U=;\n b=romLQ8dVbBnGSH4vHCPYfVdYUiD229RRoO/P02sfCjixLt+f6EJJKUBPcHd4yphDbe\n TovqfnEfnnlm+0AhDizh2f0Z1aZYxzJvpKL2Z23RBWWlYh0tliyCV6qsOifh29rf6VnR\n SlaCv/dVRxOJsuLPMTxzt4NCKvx3uD8wquhOtnKy2RILBmpn/Qc0htFn2XWyiADeafci\n /0dB40hQsVWA0lRvFfH5lyFYSFcdHkdVj7fyQnGNIoJyYoZkAtLr1YbckRzVbmqFfWqP\n v+43pGb5avAUaFWlbhefaMcYuZWOOIJd4HydyxQ/qQO1YgrHowl6ClU/QS1DR/oOQ0Be\n Sk0g==",
        "X-Gm-Message-State": "AOJu0Yz43cC/M8maJ0dRCm8Z1I6snHJC0Pt1O8GDWUL32n8YbNXKxEDT\n Dm6GB9p64v8NVxq4wm8oPvQnZyho7vDujEV/PBrKnN1h+4IqGJPtHgzigS1sdw==",
        "X-Gm-Gg": "ATEYQzxheiH8x8XWsT6XDu8vT1EaKO8exTemR+rrhyaHQcHVOpZ+TV2VU2Nr/o3ufcE\n ml/qVxtg9BZVRhzLQ5rrush9YZMAQCVhwNdVTmJYzlEALW/QUxewx9Jp5TbgdqvqHx8AF42a829\n 9ODB+UDcOHihALK7JdUh5OqcEPvEdwqxyvgiIk4CZCmdcoxEee0Ns9/HmnJg9mZJMcuGc31wUpD\n rsmZSv/XGmo7ROFhUC+y2gWvGGYV19i5bXBVsOuYLGa5MmTxFACFLpY4pLuLGoC4+TePz/4pqzY\n hB11uliydzAI9hiHmjnuz9rz7Q8h1zca37KyblWwcYLRIiGDDMN0QCpSqpHsfHvIJIkgXy3y1rK\n LB0ybtGEyyhTr6ijroIHFNnjWOOG8rrdKyVb0T0IEi9uuvKN5FA9EQ2CzLrJlSGzNVfUuzvI6CA\n BeRmfBIksC/20gwjToJkW7ovnCKFo+IaqyXXAPE0iz7OxLsgVIKPvazcKS7HcQAtUp96fB2bAb7\n oMs0w==",
        "X-Received": "by 2002:a17:90b:2687:b0:35c:1c77:fac8 with SMTP id\n 98e67ed59e1d1-35c1c77fae2mr530389a91.30.1774466419100;\n Wed, 25 Mar 2026 12:20:19 -0700 (PDT)",
        "From": "Saish Sandip Kambali <sandipkambli79@gmail.com>",
        "To": "gcc-patches@gcc.gnu.org",
        "Cc": "dmalcolm@redhat.com,\n\tsandipkambli79@gmail.com",
        "Subject": "[PATCH] analyzer: model strnlen",
        "Date": "Wed, 25 Mar 2026 19:20:13 +0000",
        "Message-ID": "<20260325192014.12049-1-sandipkambli79@gmail.com>",
        "X-Mailer": "git-send-email 2.43.0",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-BeenThere": "gcc-patches@gcc.gnu.org",
        "X-Mailman-Version": "2.1.30",
        "Precedence": "list",
        "List-Id": "Gcc-patches mailing list <gcc-patches.gcc.gnu.org>",
        "List-Unsubscribe": "<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>",
        "List-Archive": "<https://gcc.gnu.org/pipermail/gcc-patches/>",
        "List-Post": "<mailto:gcc-patches@gcc.gnu.org>",
        "List-Help": "<mailto:gcc-patches-request@gcc.gnu.org?subject=help>",
        "List-Subscribe": "<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>",
        "Errors-To": "gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"
    },
    "content": "This patch implements known_function handling for strnlen and\n__builtin_strnlen within the analyzer, it uses bifurcation logic\nfor truncated and full read conditions.\n\ngcc/analyzer/ChangeLog:\n\t* kf.cc (class kf_strnlen): New known_function subclass.\n\t(register_known_functions_libc): Register strnlen and\n\t__builtin_strnlen.\n\ngcc/testsuite/ChangeLog:\n\t* gcc.dg/analyzer/strnlen-1.c: New test.\n\nSigned-off-by: Saish Sandip Kambali <sandipkambli79@gmail.com>\n---\n gcc/analyzer/kf.cc                        | 191 ++++++++++++++++++++++\n gcc/testsuite/gcc.dg/analyzer/strnlen-1.c | 121 ++++++++++++++\n 2 files changed, 312 insertions(+)\n create mode 100644 gcc/testsuite/gcc.dg/analyzer/strnlen-1.c",
    "diff": "diff --git a/gcc/analyzer/kf.cc b/gcc/analyzer/kf.cc\nindex b1ccbd6584a..a292e220c1e 100644\n--- a/gcc/analyzer/kf.cc\n+++ b/gcc/analyzer/kf.cc\n@@ -1710,6 +1710,194 @@ public:\n   }\n };\n \n+\n+/* Handles strnlen by splitting into two outcomes:\n+   a) Truncated read: The limit 'n' is reached before the null-terminator,\n+   in this case the result is 'n'.\n+   b) Full read: The null-terminator is found before or at the limit n,\n+   in this case the result is the number of bytes read before the\n+   null-terminator.  */\n+\n+class kf_strnlen : public builtin_known_function\n+{\n+public:\n+  bool matches_call_types_p (const call_details &cd) const final override\n+  {\n+    return (cd.num_args () == 2\n+\t    && cd.arg_is_pointer_p (0)\n+\t    && cd.arg_is_integral_p (1));\n+  }\n+\n+  enum built_in_function builtin_code () const final override\n+  {\n+    return BUILT_IN_STRNLEN;\n+  }\n+\n+  void impl_call_pre (const call_details &cd) const final override;\n+  void impl_call_post (const call_details &cd) const final override;\n+};\n+\n+void\n+kf_strnlen::impl_call_pre (const call_details &cd) const\n+{\n+  cd.check_for_null_terminated_string_arg (0);\n+}\n+\n+void\n+kf_strnlen::impl_call_post (const call_details &cd) const\n+{\n+  class strnlen_call_info : public call_info\n+  {\n+  public:\n+    strnlen_call_info (const call_details &cd,\n+\t\t       const svalue *num_bytes_with_terminator_sval,\n+\t\t       bool truncated_read)\n+    : call_info (cd),\n+    m_num_bytes_with_terminator_sval (num_bytes_with_terminator_sval),\n+    m_truncated_read (truncated_read)\n+    {\n+    }\n+\n+    void print_desc (pretty_printer &pp) const final override\n+    {\n+      if (m_truncated_read)\n+        pp_printf (&pp, \"when %qE reaches the maximum limit\", get_fndecl ());\n+      else\n+        pp_printf (&pp, \"when %qE finds the null terminator\", get_fndecl ());\n+    }\n+\n+    bool update_model (region_model *model,\n+\t\t       const exploded_edge *,\n+\t\t       region_model_context *ctxt) const final override\n+    {\n+      const call_details cd (get_call_details (model, ctxt));\n+\n+      /* Arguments at index '0' is the string pointer.  */\n+      const svalue *src_sval = cd.get_arg_svalue (0);\n+      const region *src_reg\n+        = model->deref_rvalue (src_sval, cd.get_arg_tree (0), ctxt);\n+\n+      /* Argument 1 is the limit n.  */\n+      const svalue *limit_n_sval = cd.get_arg_svalue (1);\n+\n+      /* Symbolic values for return value of the call.  */\n+      const svalue *result_sval = nullptr;\n+      const svalue *bytes_to_check = nullptr;\n+\n+      /* Truncated read.  */\n+      if (m_truncated_read)\n+        {\n+\t  result_sval = limit_n_sval;\n+\n+\t  if (m_num_bytes_with_terminator_sval)\n+\t    {\n+\t      /* The null-terminator is not in the bounds of n.  */\n+\t      if (!model->add_constraint (m_num_bytes_with_terminator_sval,\n+\t\t\t\t\t  GT_EXPR, limit_n_sval, ctxt))\n+\t\treturn false;\n+\t    }\n+\t  else\n+\t    {\n+\t    }\n+        }\n+      else\n+        {\n+\t  if (m_num_bytes_with_terminator_sval)\n+\t    {\n+\t      /* The string length is less than or equal to n.  */\n+\t      if (!model->add_constraint (m_num_bytes_with_terminator_sval,\n+\t\t\t\t\t  LE_EXPR, limit_n_sval, ctxt))\n+\t\treturn false;\n+\t    }\n+\t  else\n+\t    {\n+\t      /* This bifurcation part is removed once failed.  */\n+\t      return false;\n+\t    }\n+        }\n+\n+      /* Computing return value only if lhs is present.  */\n+      if (tree lhs_type = cd.get_lhs_type ())\n+        {\n+\t  if (!m_truncated_read && m_num_bytes_with_terminator_sval)\n+\t    {\n+\t      /* Since the strnlen() returns the count of bytes excluding \\0.  */\n+\t      result_sval = model->get_manager ()->get_or_create_binop (\n+\t\tlhs_type, MINUS_EXPR, m_num_bytes_with_terminator_sval,\n+\t\tmodel->get_manager ()->get_or_create_constant_svalue (\n+\t\t  lhs_type, build_int_cst (lhs_type, 1)));\n+\t    }\n+\n+\t  /* This sets the return value, if the lhs type is decalred.  */\n+\t  if (result_sval)\n+\t    {\n+\t      cd.maybe_set_lhs (result_sval);\n+\t    }\n+\t  else\n+\t    {\n+\t    }\n+        }\n+\n+      /* This checks for buffer over read, and poison bytes as a safety check\n+         for both the lhs data type for null and non-null.  */\n+      bytes_to_check = m_truncated_read ? limit_n_sval\n+\t\t\t\t\t: m_num_bytes_with_terminator_sval;\n+\n+      if (bytes_to_check)\n+        {\n+\t  model->read_bytes (src_reg, cd.get_arg_tree (0), bytes_to_check, ctxt);\n+\t}\n+\n+      return true;\n+    }\n+\n+  private:\n+    /* This symbolic value representing the number of bytes read upto the\n+       first non-terminating character, it will be a null pointer.  */\n+    const svalue *m_num_bytes_with_terminator_sval;\n+\n+    /* If true: We are simulating 'truncated read'\n+       If false: We are simulating the 'full read'.  */\n+    bool m_truncated_read;\n+  };\n+\n+  const svalue *limit_n_sval = cd.get_arg_svalue (1);\n+\n+  if (tree n_cst = limit_n_sval->maybe_get_constant ())\n+    {\n+      if (zerop (n_cst))\n+        {\n+\t  cd.maybe_set_lhs (limit_n_sval);\n+\t  return;\n+\t}\n+    }\n+\n+  /* Body of kf_strnlen::impl_call_post.  */\n+  if (cd.get_ctxt ())\n+    {\n+      /* First, scan for a null terminator as if there were no limit,\n+         with a null ctxt so no errors reported.  */\n+      const region_model *model = cd.get_model ();\n+      const svalue *ptr_arg_sval = cd.get_arg_svalue (0);\n+      const region *buf_reg\n+        = model->deref_rvalue  (ptr_arg_sval, cd.get_arg_tree (0), nullptr);\n+\n+      const svalue *num_bytes_with_terminator_sval\n+        = model->scan_for_null_terminator (buf_reg, cd.get_arg_tree (0),\n+\t\t\t\t\t  nullptr, nullptr);\n+      cd.get_ctxt ()->bifurcate (\n+\tstd::make_unique<strnlen_call_info> (cd,\n+\t\t\t\t\t     num_bytes_with_terminator_sval,\n+\t\t\t\t\t     false));\n+      cd.get_ctxt ()->bifurcate (\n+\tstd::make_unique<strnlen_call_info> (cd,\n+\t\t\t\t\t     num_bytes_with_terminator_sval,\n+\t\t\t\t\t     true));\n+      cd.get_ctxt ()->terminate_path ();\n+    }\n+}\n+\n+\n /* Handler for \"strstr\" and \"__builtin_strstr\".\n      extern char *strstr (const char* str, const char* substr);\n    See e.g. https://en.cppreference.com/w/c/string/byte/strstr  */\n@@ -2337,6 +2525,8 @@ register_known_functions (known_function_manager &kfm,\n     kfm.add (\"__builtin_strncpy\", std::make_unique<kf_strncpy> ());\n     kfm.add (\"strndup\", std::make_unique<kf_strndup> ());\n     kfm.add (\"__builtin_strndup\", std::make_unique<kf_strndup> ());\n+    kfm.add (\"strnlen\", std::make_unique<kf_strnlen> ());\n+    kfm.add (\"__builtin_strnlen\", std::make_unique<kf_strnlen> ());\n     kfm.add (\"strlen\", std::make_unique<kf_strlen> ());\n     kfm.add (\"__builtin_strlen\", std::make_unique<kf_strlen> ());\n     kfm.add (\"strstr\", std::make_unique<kf_strstr> ());\n@@ -2402,6 +2592,7 @@ register_known_functions (known_function_manager &kfm,\n     kfm.add_std_ns (\"strcat\", std::make_unique<kf_strcat> (2, false));\n     kfm.add_std_ns (\"strcpy\", std::make_unique<kf_strcpy> (2, false));\n     kfm.add_std_ns (\"strlen\", std::make_unique<kf_strlen> ());\n+    kfm.add_std_ns (\"strnlen\", std::make_unique<kf_strnlen> ());\n     kfm.add_std_ns (\"strncpy\", std::make_unique<kf_strncpy> ());\n     kfm.add_std_ns (\"strtok\", std::make_unique<kf_strtok> (rmm));\n   }\ndiff --git a/gcc/testsuite/gcc.dg/analyzer/strnlen-1.c b/gcc/testsuite/gcc.dg/analyzer/strnlen-1.c\nnew file mode 100644\nindex 00000000000..78cfe0c0629\n--- /dev/null\n+++ b/gcc/testsuite/gcc.dg/analyzer/strnlen-1.c\n@@ -0,0 +1,121 @@\n+#include \"analyzer-decls.h\"\n+\n+typedef __SIZE_TYPE__ size_t;\n+\n+/* noinline wrapper of test_string.  */\n+static size_t __attribute__((noinline))\n+call_strnlen_1 (const char *p, size_t n)\n+{\n+  return __builtin_strnlen (p, n);\n+}\n+\n+void test_string (void)\n+{\n+  /* case 1: n is greater than string length */\n+  __analyzer_eval (call_strnlen_1 (\"abc\", 10) == 3); /* { dg-warning \"TRUE\" } */\n+\n+  /* case 2: n is smaller than the string length */\n+  __analyzer_eval (call_strnlen_1 (\"abc\", 2) == 2); /* { dg-warning \"TRUE\" } */\n+\n+  /* case 3: n is exactly the string length */\n+  __analyzer_eval (call_strnlen_1 (\"abc\", 3) == 3); /* { dg-warning \"TRUE\" } */\n+\n+  /* case 4: n is zero and should return 0 immediately.  */\n+  __analyzer_eval (call_strnlen_1 (\"abc\", 0) == 0); /* { dg-warning \"TRUE\" } */\n+}\n+\n+/* checks if pointer is NULL */\n+void test_null_1 (void)\n+{\n+  __builtin_strnlen (NULL, 1); /* { dg-warning \"use of NULL where non-null expected\" } */\n+}\n+\n+void test_null_0 (void)\n+{\n+  /* n == 0 should not trigger a NULL warning in strnlen.  */\n+  __analyzer_eval (__builtin_strnlen (NULL, 0) == 0); /* { dg-warning \"TRUE\" } */\n+}\n+\n+/* buffer declared but not initialized yet, warning if read uninitialized values */\n+void test_uninitialized (size_t n)\n+{\n+  char buf[16];\n+  if (n > 0)\n+    __builtin_strnlen (buf, n); /* { dg-warning \"use of uninitialized value\" } */   \n+}\n+\n+/* buffer is declared and partially initialized, warning if read uninitialized values */\n+void test_partially_initialized (void)\n+{\n+  char buf[16];\n+  buf[0] = 'a';\n+  __builtin_strnlen (buf, 2); /* { dg-warning \"use of uninitialized value\" } */\n+}\n+\n+/* noinline wrapper of test_unterminated case 1 */\n+static size_t __attribute__((noinline))\n+call_strnlen_2 (const char *p, size_t n)\n+{\n+  return __builtin_strnlen (p, n); /* { dg-warning \"stack-based buffer over-read\" } */\n+}\n+\n+/* noinline wrapper of test_unterminated case 2 */\n+static size_t __attribute__((noinline))\n+call_strnlen_3 (const char *p, size_t n)\n+{\n+  return __builtin_strnlen (p, n); /* { dg-warning \"stack-based buffer over-read\" } */\n+}\n+\n+void test_unterminated (void)\n+{\n+  const char buf[3] = {'a', 'b', 'c'};\n+\n+  /* case 1: SAFE as strnlen stops at n = 3, so never looked for \\0 */\n+  size_t result = call_strnlen_2 (buf, 3);\n+  __analyzer_eval (result == 3); /* { dg-warning \"TRUE\" } */\n+\n+  /* case 2: Unsafe as n=4 forces the analyzer to look past the 3 bytes buffer */\n+  call_strnlen_3 (buf, 4);\n+}\n+\n+/* noinline wrapper of test_max_n */\n+static size_t __attribute__((noinline))\n+call_strnlen_4 (const char *p, size_t n)\n+{\n+  return __builtin_strnlen (p, n);\n+}\n+\n+/* for abstraction, assures the length l < n */\n+void test_abstract (const char *s, size_t n)\n+{\n+  if (s == NULL)\n+    return;\n+  size_t length = call_strnlen_4 (s, n);\n+\n+  __analyzer_eval (length <= n); /* { dg-warning \"UNKNOWN\" } */\n+}\n+\n+/* noinline wrapper of test_array_initialization, case: true */\n+static size_t __attribute__((noinline))\n+call_strnlen_5 (const char *p, size_t n)\n+{\n+  return __builtin_strnlen (p, n);\n+}\n+\n+/* noinline wrapper of test_array_initialized, case: unknown */\n+static size_t __attribute__((noinline))\n+call_strnlen_5a (const char *p, size_t n)\n+{\n+  return __builtin_strnlen (p, n); /* { dg-warning \"stack-based buffer over-read\" } */\n+}\n+\n+/* pointer arithmetic can be performed and warnings for over reading buffer */\n+void test_array_initialization_implicit_length (void)\n+{\n+  const char buf[] = \"abc\";\n+\n+  __analyzer_eval (call_strnlen_5 (buf, 10) == 3); /* { dg-warning \"TRUE\" } */\n+  __analyzer_eval (call_strnlen_5 (buf + 2, 3) == 1); /* { dg-warning \"TRUE\" } */\n+  __analyzer_eval (call_strnlen_5 (buf + 3, 3) == 0); /* { dg-warning \"TRUE\" } */\n+  __analyzer_eval (call_strnlen_5a (buf + 4, 3) == 0); /* { dg-warning \"FALSE\" } */\n+}\n",
    "prefixes": []
}