Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2215828/?format=api
{ "id": 2215828, "url": "http://patchwork.ozlabs.org/api/patches/2215828/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/c8c3a705-4579-49aa-b456-a2342303095d@mailbox.org/", "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": "<c8c3a705-4579-49aa-b456-a2342303095d@mailbox.org>", "list_archive_url": null, "date": "2026-03-25T12:07:36", "name": "analyzer: add fdopen and freopen handlers", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "f0a8c8ad443670ff0d197761ac34d2c6578a61d3", "submitter": { "id": 92826, "url": "http://patchwork.ozlabs.org/api/people/92826/?format=api", "name": "Tomás Ortín Fernández", "email": "quanrong@mailbox.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/c8c3a705-4579-49aa-b456-a2342303095d@mailbox.org/mbox/", "series": [ { "id": 497429, "url": "http://patchwork.ozlabs.org/api/series/497429/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=497429", "date": "2026-03-25T12:07:36", "name": "analyzer: add fdopen and freopen handlers", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/497429/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2215828/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2215828/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 secure) header.d=mailbox.org header.i=@mailbox.org header.a=rsa-sha256\n header.s=mail20150812 header.b=KpWrDiIq;\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 secure) header.d=mailbox.org header.i=@mailbox.org header.a=rsa-sha256\n header.s=mail20150812 header.b=KpWrDiIq", "sourceware.org;\n dmarc=pass (p=reject dis=none) header.from=mailbox.org", "sourceware.org; spf=pass smtp.mailfrom=mailbox.org", "server2.sourceware.org;\n arc=none smtp.remote-ip=80.241.56.171", "outgoing_mbo_mout; dkim=none;\n spf=pass (outgoing_mbo_mout: domain of quanrong@mailbox.org designates\n 2001:67c:2050:b231:465::202 as permitted sender)\n smtp.mailfrom=quanrong@mailbox.org" ], "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 4fglzt0cyMz1xy1\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 25 Mar 2026 23:08:25 +1100 (AEDT)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id CE8E24BB3B9A\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 25 Mar 2026 12:08:22 +0000 (GMT)", "from mout-p-201.mailbox.org (mout-p-201.mailbox.org [80.241.56.171])\n by sourceware.org (Postfix) with ESMTPS id B411F4B9DB51\n for <gcc-patches@gcc.gnu.org>; Wed, 25 Mar 2026 12:07:53 +0000 (GMT)", "from smtp202.mailbox.org (smtp202.mailbox.org\n [IPv6:2001:67c:2050:b231:465::202])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mout-p-201.mailbox.org (Postfix) with ESMTPS id 4fglz256bBz9v5f;\n Wed, 25 Mar 2026 13:07:42 +0100 (CET)" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org CE8E24BB3B9A", "OpenDKIM Filter v2.11.0 sourceware.org B411F4B9DB51" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org B411F4B9DB51", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org B411F4B9DB51", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1774440474; cv=none;\n b=BDUaVUDIChqE3g97frNhBvyeIUD1GGKSk6dC8zlHeBeTFidr/fLrU8ez689jwCbSGCSaarrMYFDu15088Q9h49ONqjBBH+jiWWJi+Ivq2bwODsj5kbGkMUum31QSmjsGVN642gpiXLJTbqvr1j8CAZvhwHqncsznjVf/Dew3/n4=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1774440474; c=relaxed/simple;\n bh=C/Exo1rCLdwzxFRWJnOE6igWiePirqlNNQY3fKiNUmE=;\n h=DKIM-Signature:Message-ID:Date:MIME-Version:To:From:Subject;\n b=lsHYaQ8zyzuV8ecUarAryEYi3PmjyA3JU90Fsd/oL+2h8M+GMDBGskp5LjbxRDJjM/JQbXql+HBpgud9rgSJo3fwYbAFnqL9NGQOrnwML0mo6ZIE0rhC5SuNYwJ9Zmb35ssrMjt1c2Fe4fYs9G2XXAT26507LLKm4iYgHF+/GVE=", "ARC-Authentication-Results": "i=1; server2.sourceware.org", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=mailbox.org;\n s=mail20150812; t=1774440465;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding;\n bh=CRM1nBBkjc25N/cgPWtwuE8K+gQ6TQPtcImnJJCisAE=;\n b=KpWrDiIqeSZa5NcTklmH4VOMGOT9Hh3huTS+3xVIkDyYJcExr5qgfgkCrjqj5ijT/DphEq\n pGxz+/udkSJjmX4898g3vXe7IqlIUWJvWlyve8+0hO68PuzeTrZsd3q97ZWODH1kjjl25c\n 5diU3WvcK8QRCUdgejnrcxjXHN92+djhXzJZUWh/mEldr8ONs8nsslC/M1bDq0sE+j7b95\n /GYIOcqCLwpZ8CACcV69LgU0QUSjpGuSaO++WMuBcUpjqMoV+OSuUmyplVJ2X0hvTLEQcM\n W57X3mzOsMjz61mdMDSiLoxKAMu2LCueT+mPfP5l6GBU6SvH02WSyK8ZtvSsPQ==", "Message-ID": "<c8c3a705-4579-49aa-b456-a2342303095d@mailbox.org>", "Date": "Wed, 25 Mar 2026 13:07:36 +0100", "MIME-Version": "1.0", "Content-Language": "en-US", "To": "gcc-patches@gcc.gnu.org", "Cc": "David Malcolm <dmalcolm@redhat.com>", "From": "=?utf-8?b?VG9tw6FzIE9ydMOtbiBGZXJuw6FuZGV6?= <quanrong@mailbox.org>", "Subject": "[PATCH] analyzer: add fdopen and freopen handlers", "Content-Type": "text/plain; charset=UTF-8; format=flowed", "Content-Transfer-Encoding": "7bit", "X-MBO-RS-META": "ppi7865udogn3x9wjxgpibbfi7hkqkqp", "X-MBO-RS-ID": "f4ed690d7e0ab5d7ae3", "X-Rspamd-Queue-Id": "4fglz256bBz9v5f", "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": "Add known_function handlers for fdopen and freopen. Both check that\nthe mode string is null-terminated, and both participate in the\nFILE-pointer state machine so the analyzer can detect leaks and\ndouble-fclose.\n\nFor freopen, the handler returns the stream argument (since freopen\nreturns the same stream pointer on success). This is an initial\nimplementation: success/failure bifurcation is not yet implemented, so\nthe failure path where the original stream is closed cannot be modeled\nwithout false positives.\n\nAlso move fopen registration from the POSIX section to the C standard\nsection, and fix minor formatting issues in kf_fopen.\n\nBootstrapped and tested on x86_64-pc-linux-gnu.\n\ngcc/analyzer/ChangeLog:\n\n\t* kf.cc (class kf_fopen): Fix formatting.\n\t(class kf_fdopen): New known_function handler.\n\t(class kf_freopen): New known_function handler.\n\t(register_known_functions): Register kf_fdopen and kf_freopen.\n\tMove fopen from POSIX to C standard section.\n\t* sm-file.cc (fileptr_state_machine::on_stmt): Handle fdopen\n\tand freopen in the FILE-pointer state machine.\n\ngcc/testsuite/ChangeLog:\n\n\t* gcc.dg/analyzer/fopen-1.c: Add test_null_mode.\n\t* gcc.dg/analyzer/fdopen-1.c: New test.\n\t* gcc.dg/analyzer/freopen-1.c: New test.\n\nSigned-off-by: Tomas Ortin Fernandez (quanrong) <quanrong@mailbox.org>\n---\n gcc/analyzer/kf.cc | 78 ++++++++++++++-\n gcc/analyzer/sm-file.cc | 4 +-\n gcc/testsuite/gcc.dg/analyzer/fdopen-1.c | 57 +++++++++++\n gcc/testsuite/gcc.dg/analyzer/fopen-1.c | 8 ++\n gcc/testsuite/gcc.dg/analyzer/freopen-1.c | 114 ++++++++++++++++++++++\n 5 files changed, 255 insertions(+), 6 deletions(-)\n create mode 100644 gcc/testsuite/gcc.dg/analyzer/fdopen-1.c\n create mode 100644 gcc/testsuite/gcc.dg/analyzer/freopen-1.c\n\n+/* f and stream alias the same FILE object, so using stream here is \nvalid. */\n+void\n+test_use_old_stream (const char *pathname, const char *mode, FILE *stream)\n+{\n+ FILE *f = freopen (pathname, mode, stream);\n+ if (!f)\n+ return;\n+ feof (stream);\n+ fclose (f);\n+}", "diff": "diff --git a/gcc/analyzer/kf.cc b/gcc/analyzer/kf.cc\nindex 0434ab0f0bf..63365f2ef91 100644\n--- a/gcc/analyzer/kf.cc\n+++ b/gcc/analyzer/kf.cc\n@@ -530,16 +530,19 @@ kf_error::impl_call_pre (const call_details &cd) const\n class kf_fopen : public known_function\n {\n public:\n- bool matches_call_types_p (const call_details &cd) const final override\n+ bool\n+ 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+ return (cd.num_args () == 2 && cd.arg_is_pointer_p (0)\n \t && cd.arg_is_pointer_p (1));\n }\n\n- void impl_call_pre (const call_details &cd) const final override\n+ void\n+ impl_call_pre (const call_details &cd) const final override\n {\n cd.check_for_null_terminated_string_arg (0);\n+ /* TODO: mode must not be NULL, but \ncheck_for_null_terminated_string_arg\n+ doesn't yet warn on NULL pointers. */\n cd.check_for_null_terminated_string_arg (1);\n cd.set_any_lhs_with_defaults ();\n\n@@ -548,6 +551,69 @@ public:\n }\n };\n\n+/* Handler for \"fdopen\":\n+ FILE *fdopen (int fd, const char *mode); */\n+\n+class kf_fdopen : public known_function\n+{\n+public:\n+ bool\n+ matches_call_types_p (const call_details &cd) const final override\n+ {\n+ return (cd.num_args () == 2 && cd.arg_is_integral_p (0)\n+\t && cd.arg_is_pointer_p (1));\n+ }\n+\n+ void\n+ impl_call_pre (const call_details &cd) const final override\n+ {\n+ /* TODO: check that fd is valid: warn on negative constants and\n+ integrate with the fd state machine to detect use of closed or\n+ invalid file descriptors. */\n+ /* TODO: mode must not be NULL, but \ncheck_for_null_terminated_string_arg\n+ doesn't yet warn on NULL pointers. */\n+ cd.check_for_null_terminated_string_arg (1);\n+ cd.set_any_lhs_with_defaults ();\n+ }\n+};\n+\n+/* Handler for \"freopen\":\n+ FILE *freopen (const char *path, const char *mode, FILE *stream);\n+\n+ The path argument can be NULL (reopen same file with new mode).\n+\n+ On success freopen returns stream. On failure it returns NULL and\n+ the original stream is closed. Without success/failure bifurcation\n+ we cannot distinguish these paths, so we do not transition stream\n+ to \"closed\" in the state machine (doing so would cause false\n+ positives on the success path where stream is still usable).\n+\n+ TODO: add success/failure bifurcation so that the failure path can\n+ transition stream to \"closed.\" */\n+\n+class kf_freopen : public known_function\n+{\n+public:\n+ bool\n+ matches_call_types_p (const call_details &cd) const final override\n+ {\n+ return (cd.num_args () == 3 && cd.arg_is_pointer_p (0)\n+\t && cd.arg_is_pointer_p (1) && cd.arg_is_pointer_p (2));\n+ }\n+\n+ void\n+ impl_call_pre (const call_details &cd) const final override\n+ {\n+ /* path (arg 0) may be NULL (reopen same file with new mode). */\n+ if (!zerop (cd.get_arg_tree (0)))\n+ cd.check_for_null_terminated_string_arg (0);\n+ /* TODO: mode must not be NULL, but \ncheck_for_null_terminated_string_arg\n+ doesn't yet warn on NULL pointers. */\n+ cd.check_for_null_terminated_string_arg (1);\n+ cd.maybe_set_lhs (cd.get_arg_svalue (2));\n+ }\n+};\n+\n /* Handler for \"free\", after sm-handling.\n\n If the ptr points to an underlying heap region, delete the region,\n@@ -2942,8 +3008,10 @@ register_known_functions (known_function_manager \n&kfm,\n kfm.add (\"__builtin_alloca\", std::make_unique<kf_alloca> ());\n kfm.add (\"calloc\", std::make_unique<kf_calloc> ());\n kfm.add (\"__builtin_calloc\", std::make_unique<kf_calloc> ());\n+ kfm.add (\"fopen\", std::make_unique<kf_fopen> ());\n kfm.add (\"free\", std::make_unique<kf_free> ());\n kfm.add (\"__builtin_free\", std::make_unique<kf_free> ());\n+ kfm.add (\"freopen\", std::make_unique<kf_freopen> ());\n kfm.add (\"malloc\", std::make_unique<kf_malloc> ());\n kfm.add (\"__builtin_malloc\", std::make_unique<kf_malloc> ());\n kfm.add (\"memcpy\",\n@@ -2994,7 +3062,7 @@ register_known_functions (known_function_manager &kfm,\n\n /* Known POSIX functions, and some non-standard extensions. */\n {\n- kfm.add (\"fopen\", std::make_unique<kf_fopen> ());\n+ kfm.add (\"fdopen\", std::make_unique<kf_fdopen> ());\n kfm.add (\"mkdtemp\", std::make_unique<kf_mktemp_simple> (\n \t\t\t kf_mktemp_family::outcome::null_ptr));\n kfm.add (\"mkostemp\", std::make_unique<kf_mkostemp> ());\ndiff --git a/gcc/analyzer/sm-file.cc b/gcc/analyzer/sm-file.cc\nindex b8a0e2bda78..980ac005610 100644\n--- a/gcc/analyzer/sm-file.cc\n+++ b/gcc/analyzer/sm-file.cc\n@@ -410,7 +410,9 @@ fileptr_state_machine::on_stmt (sm_context &sm_ctxt,\n if (const gcall *call = dyn_cast <const gcall *> (stmt))\n if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (*call))\n {\n-\tif (is_named_call_p (callee_fndecl, \"fopen\", *call, 2))\n+\tif (is_named_call_p (callee_fndecl, \"fopen\", *call, 2)\n+\t || is_named_call_p (callee_fndecl, \"fdopen\", *call, 2)\n+\t || is_named_call_p (callee_fndecl, \"freopen\", *call, 3))\n \t {\n \t tree lhs = gimple_call_lhs (call);\n \t if (lhs)\ndiff --git a/gcc/testsuite/gcc.dg/analyzer/fdopen-1.c \nb/gcc/testsuite/gcc.dg/analyzer/fdopen-1.c\nnew file mode 100644\nindex 00000000000..e4213ba3d99\n--- /dev/null\n+++ b/gcc/testsuite/gcc.dg/analyzer/fdopen-1.c\n@@ -0,0 +1,57 @@\n+/* { dg-prune-output \"-Wuse-after-free\" } */\n+\n+#include \"analyzer-decls.h\"\n+\n+typedef struct FILE FILE;\n+FILE *fdopen (int fd, const char *mode);\n+int fclose (FILE *);\n+\n+FILE *\n+test_passthrough (int fd, const char *mode)\n+{\n+ return fdopen (fd, mode);\n+}\n+\n+FILE *\n+test_null_mode (int fd)\n+{\n+ return fdopen (fd, NULL); /* TODO: should warn about NULL mode. */\n+}\n+\n+FILE *\n+test_simple_r (int fd)\n+{\n+ return fdopen (fd, \"r\");\n+}\n+\n+FILE *\n+test_unterminated_mode (int fd)\n+{\n+ char buf[3] = \"abc\";\n+ return fdopen (fd, buf); /* { dg-warning \"stack-based buffer \nover-read\" } */\n+ /* { dg-message \"while looking for null terminator for argument 2 \n\\\\('&buf'\\\\) of 'fdopen'...\" \"event\" { target *-*-* } .-1 } */\n+}\n+\n+FILE *\n+test_uninitialized_mode (int fd)\n+{\n+ char buf[10];\n+ return fdopen (fd, buf); /* { dg-warning \"use of uninitialized value \n'buf\\\\\\[0\\\\\\]'\" } */\n+ /* { dg-message \"while looking for null terminator for argument 2 \n\\\\('&buf'\\\\) of 'fdopen'...\" \"event\" { target *-*-* } .-1 } */\n+}\n+\n+void\n+test_leak (int fd)\n+{\n+ FILE *f = fdopen (fd, \"r\");\n+} /* { dg-warning \"leak of FILE 'f'\" } */\n+\n+void\n+test_double_fclose (int fd)\n+{\n+ FILE *f = fdopen (fd, \"r\");\n+ if (!f)\n+ return;\n+ fclose (f);\n+ fclose (f); /* { dg-warning \"double 'fclose' of FILE 'f'\" } */\n+}\ndiff --git a/gcc/testsuite/gcc.dg/analyzer/fopen-1.c \nb/gcc/testsuite/gcc.dg/analyzer/fopen-1.c\nindex f59d9efd3e1..2c7177374fa 100644\n--- a/gcc/testsuite/gcc.dg/analyzer/fopen-1.c\n+++ b/gcc/testsuite/gcc.dg/analyzer/fopen-1.c\n@@ -2,9 +2,17 @@\n string too long.\n C++ compatible parts have been moved into \nc-c++-common/analyzer/fopen-2.c */\n\n+#include \"analyzer-decls.h\"\n+\n typedef struct FILE FILE;\n FILE *fopen (const char *pathname, const char *mode);\n\n+FILE *\n+test_null_mode (const char *pathname)\n+{\n+ return fopen (pathname, NULL); /* TODO: should warn about NULL mode. */\n+}\n+\n FILE *\n test_unterminated_pathname (const char *mode)\n {\ndiff --git a/gcc/testsuite/gcc.dg/analyzer/freopen-1.c \nb/gcc/testsuite/gcc.dg/analyzer/freopen-1.c\nnew file mode 100644\nindex 00000000000..d7b8d1a4331\n--- /dev/null\n+++ b/gcc/testsuite/gcc.dg/analyzer/freopen-1.c\n@@ -0,0 +1,114 @@\n+/* { dg-prune-output \"-Wuse-after-free\" } */\n+\n+#include \"analyzer-decls.h\"\n+\n+typedef struct FILE FILE;\n+FILE *freopen (const char *pathname, const char *mode, FILE *stream);\n+int fclose (FILE *);\n+int feof (FILE *);\n+\n+FILE *\n+test_passthrough (const char *pathname, const char *mode, FILE *stream)\n+{\n+ return freopen (pathname, mode, stream);\n+}\n+\n+FILE *\n+test_null_pathname (const char *mode, FILE *stream)\n+{\n+ return freopen (NULL, mode, stream);\n+}\n+\n+FILE *\n+test_null_mode (const char *pathname, FILE *stream)\n+{\n+ return freopen (pathname, NULL, stream); /* TODO: should warn about \nNULL mode. */\n+}\n+\n+FILE *\n+test_simple_r (const char *pathname, FILE *stream)\n+{\n+ return freopen (pathname, \"r\", stream);\n+}\n+\n+FILE *\n+test_swapped_args (FILE *stream)\n+{\n+ return freopen (\"r\", \"foo.txt\", stream); /* TODO: would be nice to \ndetect this. */\n+}\n+\n+FILE *\n+test_unterminated_mode (const char *pathname, FILE *stream)\n+{\n+ char buf[3] = \"abc\";\n+ return freopen (pathname, buf, stream); /* { dg-warning \"stack-based \nbuffer over-read\" } */\n+ /* { dg-message \"while looking for null terminator for argument 2 \n\\\\('&buf'\\\\) of 'freopen'...\" \"event\" { target *-*-* } .-1 } */\n+}\n+\n+FILE *\n+test_uninitialized_pathname (const char *mode, FILE *stream)\n+{\n+ char buf[10];\n+ return freopen (buf, mode, stream); /* { dg-warning \"use of \nuninitialized value 'buf\\\\\\[0\\\\\\]'\" } */\n+ /* { dg-message \"while looking for null terminator for argument 1 \n\\\\('&buf'\\\\) of 'freopen'...\" \"event\" { target *-*-* } .-1 } */\n+}\n+\n+FILE *\n+test_uninitialized_mode (const char *pathname, FILE *stream)\n+{\n+ char buf[10];\n+ return freopen (pathname, buf, stream); /* { dg-warning \"use of \nuninitialized value 'buf\\\\\\[0\\\\\\]'\" } */\n+ /* { dg-message \"while looking for null terminator for argument 2 \n\\\\('&buf'\\\\) of 'freopen'...\" \"event\" { target *-*-* } .-1 } */\n+}\n+\n+void\n+test_no_leak (const char *pathname, const char *mode, FILE *stream)\n+{\n+ /* Not a leak, f is the same as stream. */\n+ FILE *f = freopen (pathname, mode, stream);\n+}\n+\n+void\n+test_double_fclose (const char *pathname, const char *mode, FILE *stream)\n+{\n+ FILE *f = freopen (pathname, mode, stream);\n+ if (!f)\n+ return;\n+ fclose (f);\n+ fclose (f); /* { dg-warning \"double 'fclose' of FILE 'f'\" } */\n+}\n+\n+void\n+test_fclose_old_stream (const char *pathname, const char *mode, FILE \n*stream)\n+{\n+ FILE *f = freopen (pathname, mode, stream);\n+ if (!f)\n+ return;\n+ /* f and stream alias the same FILE object, so this is the first \nclose. */\n+ fclose (stream);\n+ fclose (f); /* { dg-warning \"double 'fclose' of FILE 'f'\" } */\n+}\n+\n+void\n+test_freopen_after_fclose (const char *pathname, const char *mode,\n+\t\t\t FILE *stream)\n+{\n+ fclose (stream);\n+ /* TODO: should warn about passing a closed stream to freopen. */\n+ FILE *f = freopen (pathname, mode, stream);\n+ if (f)\n+ fclose (f); /* TODO: should warn, but the LHS transition overwrites\n+\t\t stream's m_closed state, needs success/failure\n+\t\t bifurcation. */\n+}\n+\n", "prefixes": [] }