1  /* { dg-require-effective-target sockets } */
       2  /* { dg-skip-if "" { powerpc*-*-aix* } } */
       3  
       4  #include <sys/socket.h>
       5  #include <sys/un.h>
       6  #include <unistd.h>
       7  #include <errno.h>
       8  #include "analyzer-decls.h"
       9  
      10  void test_bind (int fd, const char *sockname)
      11  {
      12    struct sockaddr_un addr;
      13    memset (&addr, 0, sizeof (addr));
      14    addr.sun_family = AF_UNIX;
      15    strncpy (addr.sun_path, sockname, sizeof(addr.sun_path) - 1);
      16    if (bind (fd, (struct sockaddr *)&addr, sizeof (addr)) == -1)
      17      __analyzer_dump_path (); /* { dg-message "path" } */
      18    else
      19      __analyzer_dump_path (); /* { dg-message "path" } */
      20  }
      21  
      22  void test_null_bind (int fd)
      23  {
      24    errno = 0;
      25    int result = bind (fd, NULL, 0);
      26    __analyzer_eval (result == -1); /* { dg-warning "TRUE" } */
      27    __analyzer_eval (errno > 0); /* { dg-warning "TRUE" } */
      28  }
      29  
      30  void test_double_bind (int fd, const char *sockname)
      31  {
      32    struct sockaddr_un addr;
      33    memset (&addr, 0, sizeof (addr));
      34    addr.sun_family = AF_UNIX;
      35    strncpy (addr.sun_path, sockname, sizeof(addr.sun_path) - 1);
      36    bind (fd, (struct sockaddr *)&addr, sizeof (addr));
      37    bind (fd, (struct sockaddr *)&addr, sizeof (addr)); /* { dg-warning "'bind' on file descriptor 'fd' in wrong phase \\\[-Wanalyzer-fd-phase-mismatch\\\]" "warning" } */
      38    /* { dg-message "'bind' expects a new socket file descriptor but 'fd' has already been bound" "final event" { target *-*-* } .-1 } */
      39  }
      40  
      41  int test_uninit_addr (int fd, const char *sockname)
      42  {
      43    struct sockaddr_un addr;
      44    return bind (fd, (struct sockaddr *)&addr, sizeof (addr));
      45    // TODO: complain about uninit addr.
      46  }
      47  
      48  void test_bind_after_connect (int fd, const char *sockname,
      49  				const struct sockaddr *caddr, socklen_t caddrlen)
      50  {
      51    if (connect (fd, caddr, caddrlen) == -1)
      52      return;
      53  
      54    struct sockaddr_un addr;
      55    memset (&addr, 0, sizeof (addr));
      56    addr.sun_family = AF_UNIX;
      57    strncpy (addr.sun_path, sockname, sizeof(addr.sun_path) - 1);
      58    bind (fd, (struct sockaddr *)&addr, sizeof (addr));
      59    /* TODO: we don't warn for this; after the plain "connect" we're
      60       in the stop state.  */
      61  }
      62  
      63  void test_bind_after_accept (int fd, const char *sockname)
      64  {
      65    int afd = accept (fd, NULL, NULL);
      66    if (afd == -1)
      67      return;
      68  
      69    struct sockaddr_un addr;
      70    memset (&addr, 0, sizeof (addr));
      71    addr.sun_family = AF_UNIX;
      72    strncpy (addr.sun_path, sockname, sizeof(addr.sun_path) - 1);
      73    bind (afd, (struct sockaddr *)&addr, sizeof (addr)); /* { dg-warning "'bind' on file descriptor 'afd' in wrong phase \\\[-Wanalyzer-fd-phase-mismatch\\\]" "warning" } */
      74    /* { dg-message "'bind' expects a new socket file descriptor but 'afd' is already connected" "final event" { target *-*-* } .-1 } */
      75  
      76    close (afd);
      77  }
      78  
      79  int test_bind_on_constant ()
      80  {
      81    return bind (0, NULL, 0);
      82  }