]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix unportable code in SockAddr_cidr_mask: you can't assume that
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 8 Nov 2004 01:54:40 +0000 (01:54 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 8 Nov 2004 01:54:40 +0000 (01:54 +0000)
shifting left by full word width gives zero.  Per bug report from
Tyson Thomson.

src/backend/libpq/ip.c

index 74bcda8eb1b64ceaf7abd9fa0323ce423cd581ba..539b140e053293c9e712b9cf26cbbdcb57ddec6b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/libpq/ip.c,v 1.29 2004/09/27 23:24:30 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/libpq/ip.c,v 1.30 2004/11/08 01:54:40 tgl Exp $
  *
  * This file and the IPV6 implementation were initially provided by
  * Nigel Kukard <nkukard@lbsd.net>, Linux Based Systems Design
@@ -340,37 +340,40 @@ SockAddr_cidr_mask(struct sockaddr_storage * mask, char *numbits, int family)
 {
        long            bits;
        char       *endptr;
-       struct sockaddr_in mask4;
-
-#ifdef HAVE_IPV6
-       struct sockaddr_in6 mask6;
-#endif
 
        bits = strtol(numbits, &endptr, 10);
 
        if (*numbits == '\0' || *endptr != '\0')
                return -1;
 
-       if ((bits < 0) || (family == AF_INET && bits > 32)
-#ifdef HAVE_IPV6
-               || (family == AF_INET6 && bits > 128)
-#endif
-               )
-               return -1;
-
        switch (family)
        {
                case AF_INET:
-                       mask4.sin_addr.s_addr =
-                               htonl((0xffffffffUL << (32 - bits))
-                                         & 0xffffffffUL);
-                       memcpy(mask, &mask4, sizeof(mask4));
-                       break;
+                       {
+                               struct sockaddr_in mask4;
+                               long            maskl;
+
+                               if (bits < 0 || bits > 32)
+                                       return -1;
+                               /* avoid "x << 32", which is not portable */
+                               if (bits > 0)
+                                       maskl = (0xffffffffUL << (32 - (int) bits))
+                                               & 0xffffffffUL;
+                               else
+                                       maskl = 0;
+                               mask4.sin_addr.s_addr = htonl(maskl);
+                               memcpy(mask, &mask4, sizeof(mask4));
+                               break;
+                       }
+
 #ifdef HAVE_IPV6
                case AF_INET6:
                        {
+                               struct sockaddr_in6 mask6;
                                int                     i;
 
+                               if (bits < 0 || bits > 128)
+                                       return -1;
                                for (i = 0; i < 16; i++)
                                {
                                        if (bits <= 0)
@@ -380,7 +383,7 @@ SockAddr_cidr_mask(struct sockaddr_storage * mask, char *numbits, int family)
                                        else
                                        {
                                                mask6.sin6_addr.s6_addr[i] =
-                                                       (0xff << (8 - bits)) & 0xff;
+                                                       (0xff << (8 - (int) bits)) & 0xff;
                                        }
                                        bits -= 8;
                                }