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

            Bug ID: 128374
           Summary: analyzer: sm-fd ignores 3-arg open(), rejects valid
                    socket() fds in fd_arg, and drops mode checks on
                    unchecked/non-literal fds
           Product: gcc
           Version: 16.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: analyzer
          Assignee: dmalcolm at gcc dot gnu.org
          Reporter: 220245569 at seu dot edu.cn
                CC: 220255623 at seu dot edu.cn, jianhao.xu at seu dot edu.cn
  Target Milestone: ---
            Target: *-*-*

Reproducer
----------
$ cat trigger.c
#define O_RDONLY 0
#define O_WRONLY 1
#define O_CREAT 0100
#define SOCK_STREAM 1

int open (const char *, int, ...);
int socket (int, int, int);
int close (int);

void use_fd (int fd) __attribute__((fd_arg (1)));
void write_fd (int fd) __attribute__((fd_arg_write (1)));

void bug_3arg_open (const char *path)
{
  int fd = open (path, O_RDONLY | O_CREAT, 0644);
  if (fd >= 0)
    write_fd (fd); /* false-positive fd-use-without-check; misses mode mismatch
& leak */
}

void bug_checked_socket (void)
{
  int s = socket (2, SOCK_STREAM, 0);
  if (s >= 0)
    {
      use_fd (s); /* false-positive fd-use-without-check after socket()
succeeds */
      close (s);
    }
}

void bug_unchecked_mode_mismatch (const char *path)
{
  int fd = open (path, O_RDONLY);
  write_fd (fd); /* warns fd-use-without-check, but misses access-mode-mismatch
*/
  close (fd);
}

Compile flag: x86_64-linux-gnu-gcc -O0 -fanalyzer -S trigger.c

trigger.c: In function 'bug_3arg_open':
trigger.c:17:5: warning: 'write_fd' on possibly invalid file descriptor 'fd'
[-Wanalyzer-fd-use-without-check]
trigger.c: In function 'bug_checked_socket':
trigger.c:25:7: warning: 'use_fd' on possibly invalid file descriptor 's'
[-Wanalyzer-fd-use-without-check]
   22 |   int s = socket (2, SOCK_STREAM, 0);
      |           (1) stream socket created here
      |           (2) when 'socket' succeeds
   23 |   if (s >= 0)
      |      (3) following 'true' branch (when 's >= 0')...
   25 |       use_fd (s);
      |       (5) 's' could be invalid
# bug_unchecked_mode_mismatch warns fd-use-without-check at line 33 but misses
-Wanalyzer-fd-access-mode-mismatch

Root cause
----------
1. fd_state_machine::on_stmt (gcc/analyzer/sm-fd.cc:1333) matches open via
   is_named_call_p (callee_fndecl, "open", *call, 2), which requires exactly
   2 arguments.  Any 3-argument open (path, O_RDONLY | O_CREAT, mode) is left
   in m_start, causing false-positive -Wanalyzer-fd-use-without-check after
   if (fd >= 0) and missing mode-mismatch / leak warnings.
2. check_for_fd_attrs (sm-fd.cc:1463) checks
   !(is_valid_fd_p (state) || (state == m_stop)) and omits
   is_socket_fd_p (state) (unlike check_for_open_fd at line 1911), so checked
   socket() descriptors trigger a false-positive
-Wanalyzer-fd-use-without-check.
3. check_for_fd_attrs executes 'continue;' at line 1472 after warning on an
   unchecked descriptor, skipping the DIRS_READ / DIRS_WRITE mode check; and
   on_open (line 1522) checks TREE_CODE (arg) == INTEGER_CST on the raw GIMPLE
   operand instead of querying the region model's constant svalue.

Suggested Fix
-------------
1. Accept both 2-argument and 3-argument open() calls in
fd_state_machine::on_stmt
   (sm-fd.cc:1333).
2. Add is_socket_fd_p (state) to check_for_fd_attrs (sm-fd.cc:1463) and remove
   the 'continue;' at line 1472.
3. In fd_state_machine::on_open (sm-fd.cc:1522), resolve non-INTEGER_CST flag
   operands via the region model's maybe_get_constant ().

Reply via email to