[{"id":3669277,"web_url":"http://patchwork.ozlabs.org/comment/3669277/","msgid":"<5604c2dd79a4fbcc34696e9853e2232c9ab88e0b.camel@redhat.com>","list_archive_url":null,"date":"2026-03-25T19:00:54","subject":"Re: [PATCH] analyzer: add fdopen and freopen handlers","submitter":{"id":24465,"url":"http://patchwork.ozlabs.org/api/people/24465/","name":"David Malcolm","email":"dmalcolm@redhat.com"},"content":"On Wed, 2026-03-25 at 13:07 +0100, Tomás Ortín Fernández wrote:\n> Add known_function handlers for fdopen and freopen.  Both check that\n> the mode string is null-terminated, and both participate in the\n> FILE-pointer state machine so the analyzer can detect leaks and\n> double-fclose.\n> \n> For freopen, the handler returns the stream argument (since freopen\n> returns the same stream pointer on success).  This is an initial\n> implementation: success/failure bifurcation is not yet implemented,\n> so\n> the failure path where the original stream is closed cannot be\n> modeled\n> without false positives.\n> \n> Also move fopen registration from the POSIX section to the C standard\n> section, and fix minor formatting issues in kf_fopen.\n> \n> Bootstrapped and tested on x86_64-pc-linux-gnu.\n\nHi Tomás, thanks for the patch.\n\nVarious comments inline below throughout.  Overall I think the patch is\npromising, but there are a bunch of TODOs that really need addressing.\n\nWould it help to split these into two separate patches?  (I don't know,\nbut I thought it worth mentioning)  My gut feeling is that freopen is\nsomewhat easier that fdopen, since freopen only has to interact with\nsm-file.cc, whereas fdopen probably needs to interact with both sm-\nfile.cc and sm-fd.cc.\n\n> \n> gcc/analyzer/ChangeLog:\n> \n> \t* kf.cc (class kf_fopen): Fix formatting.\n\nThe changes do rather more than just that; they add a check for \"mode\"\nbeing null-terminated.\n\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> \n> gcc/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> \n> Signed-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> diff --git a/gcc/analyzer/kf.cc b/gcc/analyzer/kf.cc\n> index 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 \n> check_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\nShould there be an interaction between the fd and file state machines?\n\nThis is a big can of worms: we need to at least make sure we don't get\nfalse positives about leaks from the fd state machine, and to ensure we\ndo get true positives about leaks from the file state machine.\n\nConsider something like:\n\n  int fd = open (pathname, flags);\n  if (fd == -1)\n     return;\n  FILE *fp = fdopen (fd, \"r\"); // shouldn't complain about leak of 'fd'\n  return; // should complain about leak of 'fp'.\n\nIn theory we could complain about mismatches between the mode of the fd\nand the mode of the fdopen, but IIRC there a bunch of platform-specific\nextensions to the mode string codes and we probably don't want to get\ninto dealing with that.\n\n\n> +    /* TODO: mode must not be NULL, but \n> check_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\nI think we probably need that bifurcation.\n\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 \n> check_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> ());\n> diff --git a/gcc/analyzer/sm-file.cc b/gcc/analyzer/sm-file.cc\n> index 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)\n> diff --git a/gcc/testsuite/gcc.dg/analyzer/fdopen-1.c \n> b/gcc/testsuite/gcc.dg/analyzer/fdopen-1.c\n> new file mode 100644\n> index 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 \n> over-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> +}\n\nNeed test coverage for not complaining about a leak where we know we\n\"own\" the fd (due to an \"open\" call).\n\n> diff --git a/gcc/testsuite/gcc.dg/analyzer/fopen-1.c \n> b/gcc/testsuite/gcc.dg/analyzer/fopen-1.c\n> index 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 \n> c-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\nProbably want a test_unterminated_mode here, if there isn't one\nalready.\n\n\n>   FILE *\n>   test_unterminated_pathname (const char *mode)\n>   {\n> diff --git a/gcc/testsuite/gcc.dg/analyzer/freopen-1.c \n> b/gcc/testsuite/gcc.dg/analyzer/freopen-1.c\n> new file mode 100644\n> index 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 \n> NULL 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\n> detect 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 \n> buffer 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 \n> uninitialized 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 \n> uninitialized 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 \n> close.  */\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> +/* f and stream alias the same FILE object, so using stream here is \n> valid.  */\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> +}\n\nThanks again\nDave","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 (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=WAy52d6h;\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 (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=WAy52d6h","sourceware.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com","sourceware.org; spf=pass smtp.mailfrom=redhat.com","server2.sourceware.org;\n arc=none smtp.remote-ip=170.10.129.124"],"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 4fgx8c2X0sz1xy3\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 26 Mar 2026 06:01:35 +1100 (AEDT)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 23EFA4BB588F\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 25 Mar 2026 19:01:33 +0000 (GMT)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.129.124])\n by sourceware.org (Postfix) with ESMTP id E81404B9DB6E\n for <gcc-patches@gcc.gnu.org>; Wed, 25 Mar 2026 19:01:00 +0000 (GMT)","from mail-qt1-f200.google.com (mail-qt1-f200.google.com\n [209.85.160.200]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-127-aFP7DFJ2NICVOrax5uTejA-1; Wed, 25 Mar 2026 15:00:58 -0400","by mail-qt1-f200.google.com with SMTP id\n d75a77b69052e-509044f54aaso7470741cf.1\n for <gcc-patches@gcc.gnu.org>; Wed, 25 Mar 2026 12:00:58 -0700 (PDT)","from t14s.localdomain (c-73-38-242-98.hsd1.nh.comcast.net.\n [73.38.242.98]) by smtp.gmail.com with ESMTPSA id\n d75a77b69052e-50b9237a40asm5030281cf.21.2026.03.25.12.00.55\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 25 Mar 2026 12:00:55 -0700 (PDT)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org 23EFA4BB588F","OpenDKIM Filter v2.11.0 sourceware.org E81404B9DB6E"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org E81404B9DB6E","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org E81404B9DB6E","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1774465261; cv=none;\n b=Yg8ZHYMp/iO5T7Pyf0A+9y+QimkhBOssdwjf9wmSwV6wQHk+4ga4cVgVMuVLM+PQp5vMivW97g8EnmP/Vxi8MNIeFPoFv8wMDJ1GRJcW2tBWBkUw9UeiRq05Gu44ByCtxMn5Zue0m2fyx8dUMwBBHgnDgAcEh8Qk6EmMM2g8Zgs=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1774465261; c=relaxed/simple;\n bh=r0dSxdy7UznV8S1g+/Eh8DzlS00tKroUvrkLat32AbE=;\n h=DKIM-Signature:Message-ID:Subject:From:To:Date:MIME-Version;\n b=hLtj62MF5kzGsa+kYXLGOmaBx/A+fNsZg+XlnVgocHWIQybRw58KTNvnNeVQPz9QG7T4kUd41Ad+K0nfx0IwksUzvoQybsPlJ7HPUJUbjmzXh+YgpjGRRoCvQTWiJqIvNn2tZiccvbKztV47Lt0kXxUaSpx9Vkrs2VwIEu+KB6U=","ARC-Authentication-Results":"i=1; server2.sourceware.org","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1774465260;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=qWOHrgUKS1+vvLBT4J3d53z1vgvxqrxrwHhxfF9MxeQ=;\n b=WAy52d6hSp5rIBZJK1OS0TkH6d5MR3Ga719C8i9zJGF0ZoTssDi02n/QPiQCfiTbZaEgXR\n iuM76ybCzXIF38Kx5kWDnku/swHuPYposWYn28STO/2JjL9g/CdxLFty2LndZ/wd4gmgVy\n kR4plsjMoqM4GO5fbTX27IpWJfrFt64=","X-MC-Unique":"aFP7DFJ2NICVOrax5uTejA-1","X-Mimecast-MFC-AGG-ID":"aFP7DFJ2NICVOrax5uTejA_1774465257","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1774465257; x=1775070057;\n h=mime-version:user-agent:content-transfer-encoding:references\n :in-reply-to:date:to:from:subject:message-id:x-gm-gg\n :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to;\n bh=mt2IdWVm9Af/WCZ3vwA7eh3dSLJ5S9dRUI86psDDsys=;\n b=Q+QlTx8AUHDpvUNdXabbA6xVikQv1rAwcFqsJoz7yLaRbgIJ0LmZcCn6drVqVmNw5s\n bkUKY4UqcMUE9UVMMZTXxVfL4Vv2xZStYUZUvW6UHoNcSH6rwaaNYZr3adqvXhC7ruue\n 6mjAslpqGPz3Imvf4FUGHZpGetXLrVd8WHvpnmOCcxjdz0TN30dJmp9VYbU6q8Kuacq0\n Wsz0anSoWCwjh57kNDaq3mBd7GD1KJJHmpg/skvMB3RO90WW1v9LO+rI8BDWAJUZUCpd\n fkLaHOtVOxMj1tgrIjPeQSmwKaVnZJ/qxuJmoupCpAOUWL+AYUSkd5WuB4hRHNF0Xtbp\n EEvA==","X-Forwarded-Encrypted":"i=1;\n AJvYcCVI09nrKrpOMCaC/0hSPNGJPn12cDJ5/8E1KpgA17cwtmIXKYX2NHNRfvuxPK1t3tXtf5nPcA2QPUF9DA==@gcc.gnu.org","X-Gm-Message-State":"AOJu0YyRfG++MMjT+Y3tVvOIqmaEGxeoTqrDeyca8qXr8d/hLXq35hQs\n MXil9pr1DV3mtLA44S4BW1NrfzxHrzkxtoclSLZFcpVAmH9G+o2VH40FaN+FAYpnfzXnFaof4wH\n MKwOeJM5AcW32UZex7Mh6O8b5FukWQr/eVrAa00Bvxhl1tTy0Q+s6qeopWh8=","X-Gm-Gg":"ATEYQzw9aTxzQvIuwEus86F4sOF2A6lbp9Qi46mYIpJRcY6O03NWRplPNAStSbwPSzG\n N8nkmB/mZxw4qANQsIZQIy9iHqi4DgmXNetY0KGHi+FNUeb17aYWUOs0SZ/jD6g3+z44eZ4JYq3\n Uuf+GpWZkb1dt0ZE2Nq+N3u29J2qjfCrYKHrYoNDtdeHBY60Xv3hh2PiBYmMrRLTivD8RP90L9k\n R4NNXb1mGmhJY8vVXlQi6iLctY5UCAvg25RrFXanFtGHVZDPohykQ3zuV8Ugs5TXTOCkXjNQ4/u\n G3Y04D6xYWw0sbIj4FF/A1iGkm0qNwB6CQF8MvEs4IHaro4E//bfMMX1Mloo1N0rUEwstBgn02O\n OxQGFTwZswjtBLdoAY9/cX1HJlKAr6L74uuwVQ8TPvVOEax0ncqrtvg+yXfb8Eg==","X-Received":["by 2002:ac8:7dd5:0:b0:509:11c6:d689 with SMTP id\n d75a77b69052e-50b80d350d9mr64798131cf.25.1774465257207;\n Wed, 25 Mar 2026 12:00:57 -0700 (PDT)","by 2002:ac8:7dd5:0:b0:509:11c6:d689 with SMTP id\n d75a77b69052e-50b80d350d9mr64797011cf.25.1774465256394;\n Wed, 25 Mar 2026 12:00:56 -0700 (PDT)"],"Message-ID":"<5604c2dd79a4fbcc34696e9853e2232c9ab88e0b.camel@redhat.com>","Subject":"Re: [PATCH] analyzer: add fdopen and freopen handlers","From":"David Malcolm <dmalcolm@redhat.com>","To":"=?iso-8859-1?q?Tom=E1s_Ort=EDn_Fern=E1ndez?= <quanrong@mailbox.org>,\n gcc-patches@gcc.gnu.org","Date":"Wed, 25 Mar 2026 15:00:54 -0400","In-Reply-To":"<c8c3a705-4579-49aa-b456-a2342303095d@mailbox.org>","References":"<c8c3a705-4579-49aa-b456-a2342303095d@mailbox.org>","User-Agent":"Evolution 3.54.3 (3.54.3-1.fc41)","MIME-Version":"1.0","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"gfeLUXMPL46h2jHh930wvyEHmQCMQKFS7fT4_AazjuQ_1774465257","X-Mimecast-Originator":"redhat.com","Content-Type":"text/plain; charset=\"UTF-8\"","Content-Transfer-Encoding":"quoted-printable","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"}}]