public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-4424] analyzer: fix ICE on bind/connect with a constant fd [PR107928]
@ 2022-12-01  2:31 David Malcolm
  0 siblings, 0 replies; only message in thread
From: David Malcolm @ 2022-12-01  2:31 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:45a75fd3d31265e43aa3ce7a5e851083d534b00b

commit r13-4424-g45a75fd3d31265e43aa3ce7a5e851083d534b00b
Author: David Malcolm <dmalcolm@redhat.com>
Date:   Wed Nov 30 21:26:41 2022 -0500

    analyzer: fix ICE on bind/connect with a constant fd [PR107928]
    
    gcc/analyzer/ChangeLog:
            PR analyzer/107928
            * sm-fd.cc (fd_state_machine::on_bind): Handle m_constant_fd in
            the "success" outcome.
            (fd_state_machine::on_connect): Likewise.
            * sm-fd.dot: Add "constant_fd" state and its transitions.
    
    gcc/testsuite/ChangeLog:
            PR analyzer/107928
            * gcc.dg/analyzer/fd-bind-pr107928.c: New test.
            * gcc.dg/analyzer/fd-connect-pr107928.c: New test.
            * gcc.dg/analyzer/fd-stream-socket-active-open.c
            (test_active_open_from_connect_constant): New, adapted from
            test_active_open_from_connect.
            * gcc.dg/analyzer/fd-stream-socket-passive-open.c
            (test_passive_open_from_bind_constant): New, adapted from
            test_passive_open_from_bind.
            (test_passive_open_from_listen_constant): New, adapted from
            test_passive_open_from_listen.
    
    Signed-off-by: David Malcolm <dmalcolm@redhat.com>

Diff:
---
 gcc/analyzer/sm-fd.cc                              |  6 +-
 gcc/analyzer/sm-fd.dot                             |  6 ++
 gcc/testsuite/gcc.dg/analyzer/fd-bind-pr107928.c   | 10 +++
 .../gcc.dg/analyzer/fd-connect-pr107928.c          | 10 +++
 .../gcc.dg/analyzer/fd-stream-socket-active-open.c | 31 +++++++
 .../analyzer/fd-stream-socket-passive-open.c       | 98 ++++++++++++++++++++++
 6 files changed, 159 insertions(+), 2 deletions(-)

diff --git a/gcc/analyzer/sm-fd.cc b/gcc/analyzer/sm-fd.cc
index 794733e55ca..799847cb8e8 100644
--- a/gcc/analyzer/sm-fd.cc
+++ b/gcc/analyzer/sm-fd.cc
@@ -1861,7 +1861,8 @@ fd_state_machine::on_bind (const call_details &cd,
 	next_state = m_bound_datagram_socket;
       else if (old_state == m_new_unknown_socket)
 	next_state = m_bound_unknown_socket;
-      else if (old_state == m_start)
+      else if (old_state == m_start
+	       || old_state == m_constant_fd)
 	next_state = m_bound_unknown_socket;
       else if (old_state == m_stop)
 	next_state = m_stop;
@@ -2116,7 +2117,8 @@ fd_state_machine::on_connect (const call_details &cd,
 	next_state = m_new_datagram_socket;
       else if (old_state == m_new_unknown_socket)
 	next_state = m_stop;
-      else if (old_state == m_start)
+      else if (old_state == m_start
+	       || old_state == m_constant_fd)
 	next_state = m_stop;
       else if (old_state == m_stop)
 	next_state = m_stop;
diff --git a/gcc/analyzer/sm-fd.dot b/gcc/analyzer/sm-fd.dot
index da925b0989f..d7676b1f779 100644
--- a/gcc/analyzer/sm-fd.dot
+++ b/gcc/analyzer/sm-fd.dot
@@ -27,6 +27,9 @@ digraph "fd" {
   /* Start state.  */
   start;
 
+  /* State for a constant file descriptor (>= 0).  */
+  constant_fd;
+
   /* States representing a file descriptor that hasn't yet been
     checked for validity after opening, for three different
     access modes.  */
@@ -129,6 +132,7 @@ digraph "fd" {
 
   /* On "bind".  */
   start -> bound_unknown_socket [label="when 'bind(X, ...)' succeeds"];
+  constant_fd -> bound_unknown_socket [label="when 'bind(X, ...)' succeeds"];
   new_stream_socket -> bound_stream_socket [label="when 'bind(X, ...)' succeeds"];
   new_datagram_socket -> bound_datagram_socket [label="when 'bind(X, ...)' succeeds"];
   new_unknown_socket -> bound_unknown_socket [label="when 'bind(X, ...)' succeeds"];
@@ -140,12 +144,14 @@ digraph "fd" {
 
   /* On "accept".  */
   start -> connected_stream_socket [label="when 'accept(OTHER, ...)' succeeds on a listening_stream_socket"];
+  constant_fd -> connected_stream_socket [label="when 'accept(OTHER, ...)' succeeds on a listening_stream_socket"];
 
   /* On "connect".  */
   new_stream_socket -> connected_stream_socket [label="when 'connect(X, ...)' succeeds"];
   new_datagram_socket -> new_datagram_socket [label="when 'connect(X, ...)' succeeds"];
   new_unknown_socket -> stop [label="when 'connect(X, ...)' succeeds"];
   start -> stop [label="when 'connect(X, ...)' succeeds"];
+  constant_fd -> stop [label="when 'connect(X, ...)' succeeds"];
 
   /* on_condition.  */
   unchecked_read_write -> valid_read_write [label="on 'X >= 0'"];
diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-bind-pr107928.c b/gcc/testsuite/gcc.dg/analyzer/fd-bind-pr107928.c
new file mode 100644
index 00000000000..acc1a1df8e0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/fd-bind-pr107928.c
@@ -0,0 +1,10 @@
+struct sa {};
+
+int
+bind (int, struct sa *, int);
+
+int
+foo (struct sa sa)
+{
+  return bind (1, &sa, sizeof sa);
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-connect-pr107928.c b/gcc/testsuite/gcc.dg/analyzer/fd-connect-pr107928.c
new file mode 100644
index 00000000000..f3bdc87c210
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/fd-connect-pr107928.c
@@ -0,0 +1,10 @@
+struct sa {};
+
+int
+connect (int, struct sa *, int);
+
+int
+foo (struct sa sa)
+{
+  return connect (1, &sa, sizeof sa);
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket-active-open.c b/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket-active-open.c
index 841894cc1bd..89ea82e59c9 100644
--- a/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket-active-open.c
+++ b/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket-active-open.c
@@ -74,3 +74,34 @@ void test_active_open_from_connect (int fd, const char *sockname, void *buf)
   close (fd);
   __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-stop'" } */
 }
+
+void test_active_open_from_connect_constant (const char *sockname, void *buf)
+{
+  const int fd = 42;
+  __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-constant'" } */
+
+  struct sockaddr_un addr;
+  memset (&addr, 0, sizeof (addr));
+  addr.sun_family = AF_UNIX;
+  strncpy (addr.sun_path, sockname, sizeof(addr.sun_path) - 1);
+
+  errno = 0;
+  if (connect (fd, (struct sockaddr *)&addr, sizeof (addr)) == -1)
+    {
+      __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-constant'" } */
+      __analyzer_eval (errno > 0); /* { dg-warning "TRUE" } */
+      close (fd);
+      __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-closed'" } */
+      return;
+    }
+
+  __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-stop'" } */
+  __analyzer_eval (errno == 0); /* { dg-warning "TRUE" } */
+  __analyzer_eval (fd >= 0); /* { dg-warning "TRUE" } */
+
+  write (fd, "hello", 6);
+  read (fd, buf, 100);
+
+  close (fd);
+  __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-stop'" } */
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket-passive-open.c b/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket-passive-open.c
index a61091101ed..8af52904d7e 100644
--- a/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket-passive-open.c
+++ b/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket-passive-open.c
@@ -129,6 +129,62 @@ void test_passive_open_from_bind (int fd, const char *sockname, void *buf)
   __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-closed'" } */
 }
 
+void test_passive_open_from_bind_constant (const char *sockname, void *buf)
+{
+  const int fd = 42;
+  struct sockaddr_un addr;
+  int afd;
+  __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-constant'" } */
+  memset (&addr, 0, sizeof (addr));
+  addr.sun_family = AF_UNIX;
+  strncpy (addr.sun_path, sockname, sizeof(addr.sun_path) - 1);
+  errno = 0;
+  if (bind (fd, (struct sockaddr *)&addr, sizeof (addr)) == -1)
+    {
+      __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-constant'" } */
+      __analyzer_eval (errno > 0); /* { dg-warning "TRUE" } */
+      close (fd);
+      __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-closed'" } */
+      return;
+    }
+  __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-bound-unknown-socket'" } */
+  __analyzer_eval (errno == 0); /* { dg-warning "TRUE" } */
+  __analyzer_eval (fd >= 0); /* { dg-warning "TRUE" } */
+  if (listen (fd, 5) == -1)
+    {
+      __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-bound-unknown-socket'" } */
+      __analyzer_eval (errno > 0); /* { dg-warning "TRUE" } */
+      close (fd);
+      __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-closed'" } */
+      return;
+    }
+  __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-listening-stream-socket'" } */
+  __analyzer_eval (errno == 0); /* { dg-warning "TRUE" } */
+  __analyzer_eval (fd >= 0); /* { dg-warning "TRUE" } */
+  afd = accept (fd, NULL, NULL);
+  if (afd == -1)
+    {
+      __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-listening-stream-socket'" } */
+      __analyzer_eval (errno > 0); /* { dg-warning "TRUE" } */
+      close (fd);
+      __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-closed'" } */
+      return;
+    }
+  __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-listening-stream-socket'" } */
+  __analyzer_dump_state ("file-descriptor", afd); /* { dg-warning "state: 'fd-connected-stream-socket'" } */
+  __analyzer_eval (errno == 0); /* { dg-warning "TRUE" } */
+  __analyzer_eval (fd >= 0); /* { dg-warning "TRUE" } */
+  __analyzer_eval (afd >= 0); /* { dg-warning "TRUE" } */
+
+  write (afd, "hello", 6);  
+  read (afd, buf, 100);
+
+  close (afd);
+  close (fd);
+  __analyzer_dump_state ("file-descriptor", afd); /* { dg-warning "state: 'fd-closed'" } */
+  __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-closed'" } */
+}
+
 void test_passive_open_from_listen (int fd, void *buf)
 {
   int afd;
@@ -169,6 +225,48 @@ void test_passive_open_from_listen (int fd, void *buf)
   __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-closed'" } */
 }
 
+
+void test_passive_open_from_listen_constant (void *buf)
+{
+  const int fd = 42;
+  int afd;
+  errno = 0;
+  __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-constant'" } */
+  if (listen (fd, 5) == -1)
+    {
+      __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-constant'" } */
+      __analyzer_eval (errno > 0); /* { dg-warning "TRUE" } */
+      close (fd);
+      __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-closed'" } */
+      return;
+    }
+  __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-listening-stream-socket'" } */
+  __analyzer_eval (errno == 0); /* { dg-warning "TRUE" } */
+  __analyzer_eval (fd >= 0); /* { dg-warning "TRUE" } */
+  afd = accept (fd, NULL, NULL);
+  if (afd == -1)
+    {
+      __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-listening-stream-socket'" } */
+      __analyzer_eval (errno > 0); /* { dg-warning "TRUE" } */
+      close (fd);
+      __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-closed'" } */
+      return;
+    }
+  __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-listening-stream-socket'" } */
+  __analyzer_dump_state ("file-descriptor", afd); /* { dg-warning "state: 'fd-connected-stream-socket'" } */
+  __analyzer_eval (errno == 0); /* { dg-warning "TRUE" } */
+  __analyzer_eval (fd >= 0); /* { dg-warning "TRUE" } */
+  __analyzer_eval (afd >= 0); /* { dg-warning "TRUE" } */
+
+  write (afd, "hello", 6);
+  read (afd, buf, 100);
+
+  close (afd);
+  close (fd);
+  __analyzer_dump_state ("file-descriptor", afd); /* { dg-warning "state: 'fd-closed'" } */
+  __analyzer_dump_state ("file-descriptor", fd); /* { dg-warning "state: 'fd-closed'" } */
+}
+
 void test_passive_open_from_accept (int fd, void *buf)
 {
   int afd;

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-12-01  2:31 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-01  2:31 [gcc r13-4424] analyzer: fix ICE on bind/connect with a constant fd [PR107928] David Malcolm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).