https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106283

xan9xxx at gmail dot com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |xan9xxx at gmail dot com

--- Comment #2 from xan9xxx at gmail dot com ---
Hi David,

I'm a new contributor interested in the analyzer, and I'd like to work on this
bug. Is anyone already working on it? If not, I'd be happy to take it.

Tested with trunk 543617c9359 (2026-09-17).

While reproducing comment 1, I noticed that the reported path takes the false
branch of "if (fd > 2)" on line 16, so closefrom is never called on that path.

  $ gcc -fanalyzer -fanalyzer-verbosity=3 -fdiagnostics-plain-output -c t.c
  t.c: In function ‘daemonize’:
  t.c:18:1: warning: leak of file descriptor ‘fd’ [CWE-775]
[-Wanalyzer-fd-leak]
  t.c:8:12: note: (1) opened here
  t.c:9:6: note: (2) assuming ‘fd’ is a valid file descriptor (>= 0)
  t.c:9:6: note: (3) following ‘false’ branch (when ‘fd >= 0’)...
  t.c:12:3: note: (4) ...to here
  t.c:16:6: note: (5) following ‘false’ branch (when ‘fd <= 2’)...
  t.c:16:6: note: (6) ...to here
  t.c:18:1: note: (7) ‘fd’ leaks here; was opened at (1)

Replacing closefrom(3) with close(fd) on line 17 still gives the same warning,
via the same path:

  $ diff -u t.c pr-106283-c1-close-fd.c
  --- t.c 2026-10-09 08:45:57.770656508 +0800
  +++ pr-106283-c1-close-fd.c     2026-10-09 09:34:23.484884593 +0800
  @@ -14,5 +14,5 @@
     dup2(fd, 2);

     if (fd > 2)
  -    closefrom(3);  /* closes fd, but analyzer doesn't know */
  +    close(fd);
   }

  $ gcc -fanalyzer -fanalyzer-verbosity=3 -fdiagnostics-plain-output -c
pr-106283-c1-close-fd.c
  pr-106283-c1-close-fd.c: In function ‘daemonize’:
  pr-106283-c1-close-fd.c:18:1: warning: leak of file descriptor ‘fd’ [CWE-775]
[-Wanalyzer-fd-leak]
  pr-106283-c1-close-fd.c:8:12: note: (1) opened here
  pr-106283-c1-close-fd.c:9:6: note: (2) assuming ‘fd’ is a valid file
descriptor (>= 0)
  pr-106283-c1-close-fd.c:9:6: note: (3) following ‘false’ branch (when ‘fd >=
0’)...
  pr-106283-c1-close-fd.c:12:3: note: (4) ...to here
  pr-106283-c1-close-fd.c:16:6: note: (5) following ‘false’ branch (when ‘fd <=
2’)...
  pr-106283-c1-close-fd.c:16:6: note: (6) ...to here
  pr-106283-c1-close-fd.c:18:1: note: (7) ‘fd’ leaks here; was opened at (1)

So this part doesn't seem to be about closefrom: on that path fd is 0, 1 or 2,
i.e. one of the standard streams, which is intentionally left open. This looks
related to PR 109839.

A testcase that isolates the closefrom issue:

  $ cat test_closefrom_0.c
  #include <unistd.h>
  #include <fcntl.h>

  extern void closefrom(int lowfd);

  void test_closefrom_0(void)
  {
    int fd = open("/dev/null", O_RDWR);
    if (fd < 0)
      return;

    closefrom(0);
  }
  $ gcc -fanalyzer -fanalyzer-verbosity=3 -fdiagnostics-plain-output -c
test_closefrom_0.c
  test_closefrom_0.c: In function ‘test_closefrom_0’:
  test_closefrom_0.c:13:1: warning: leak of file descriptor ‘fd’ [CWE-775]
[-Wanalyzer-fd-leak]
  test_closefrom_0.c:8:12: note: (1) opened here
  test_closefrom_0.c:9:6: note: (2) assuming ‘fd’ is a valid file descriptor
(>= 0)
  test_closefrom_0.c:9:6: note: (3) following ‘false’ branch (when ‘fd >=
0’)...
  test_closefrom_0.c:12:3: note: (4) ...to here
  test_closefrom_0.c:13:1: note: (5) ‘fd’ leaks here; was opened at (1)

My plan is to start with closefrom in sm-fd.cc:
- if the analyzer can prove that an fd is in the range being closed, mark it as
closed;
- if it can prove the fd is outside the range, leave it unchanged;
- if it can't decide (e.g. closefrom(3) when fd is only known to be >= 0), stop
tracking it, as already happens when an fd is passed to an unknown function, to
avoid introducing new false positives.

Does this approach sound reasonable? And would you prefer close_range to be
handled in the same patch, or separately?

Thanks!

Reply via email to