Bugzilla bug #77264: the IsValidNetAddrLen() check should accept both of
authorwtc%netscape.com
Wed, 23 May 2001 04:17:33 +0000
changeset 1901 4b0b7d690448505cf651366afd68f80c3f38fa0e
parent 1897 af8112ddb9a6aa486041786b51485ab654d053cf
child 1902 702ec3f5bc5b132ff0455d69fbc4d91c7e72a0d9
push idunknown
push userunknown
push dateunknown
bugs77264
Bugzilla bug #77264: the IsValidNetAddrLen() check should accept both of the possible sizes of struct sockaddr_in6 on Linux. Modified files: prsocket.c, ptio.c.
pr/src/io/prsocket.c
pr/src/pthreads/ptio.c
--- a/pr/src/io/prsocket.c
+++ b/pr/src/io/prsocket.c
@@ -60,31 +60,41 @@ static PRBool IsValidNetAddrLen(const PR
      * The definition of the length of a Unix domain socket address
      * is not uniform, so we don't check it.
      */
     if ((addr != NULL)
 #ifdef XP_UNIX
             && (addr->raw.family != AF_UNIX)
 #endif
             && (PR_NETADDR_SIZE(addr) != addr_len)) {
+#if defined(LINUX)
+        /*
+         * In glibc 2.1, struct sockaddr_in6 is 24 bytes.  In glibc 2.2
+         * and in the 2.4 kernel, struct sockaddr_in6 has the scope_id
+         * field and is 28 bytes.  It is possible for socket functions
+         * to return an addr_len greater than sizeof(struct sockaddr_in6).
+         * We need to allow that.  (Bugzilla bug #77264)
+         */
+        if ((PR_AF_INET6 == addr->raw.family)
+                && (sizeof(addr->ipv6) == addr_len)) {
+            return PR_TRUE;
+        }
+#endif
         /*
          * The accept(), getsockname(), etc. calls on some platforms
          * do not set the actual socket address length on return.
          * In this case, we verifiy addr_len is still the value we
          * passed in (i.e., sizeof(PRNetAddr)).
          */
 #if defined(QNX)
-        if (sizeof(PRNetAddr) != addr_len) {
-            return PR_FALSE;
-        } else {
+        if (sizeof(PRNetAddr) == addr_len) {
             return PR_TRUE;
         }
-#else
+#endif
         return PR_FALSE;
-#endif
     }
     return PR_TRUE;
 }
 
 #endif /* DEBUG */
 
 static PRInt32 PR_CALLBACK SocketWritev(PRFileDesc *fd, const PRIOVec *iov,
 PRInt32 iov_size, PRIntervalTime timeout)
--- a/pr/src/pthreads/ptio.c
+++ b/pr/src/pthreads/ptio.c
@@ -231,16 +231,29 @@ static PRBool IsValidNetAddrLen(const PR
 {
     /*
      * The definition of the length of a Unix domain socket address
      * is not uniform, so we don't check it.
      */
     if ((addr != NULL)
             && (addr->raw.family != AF_UNIX)
             && (PR_NETADDR_SIZE(addr) != addr_len)) {
+#if defined(LINUX)
+        /*
+         * In glibc 2.1, struct sockaddr_in6 is 24 bytes.  In glibc 2.2
+         * and in the 2.4 kernel, struct sockaddr_in6 has the scope_id
+         * field and is 28 bytes.  It is possible for socket functions
+         * to return an addr_len greater than sizeof(struct sockaddr_in6).
+         * We need to allow that.  (Bugzilla bug #77264)
+         */
+        if ((PR_AF_INET6 == addr->raw.family)
+                && (sizeof(addr->ipv6) == addr_len)) {
+            return PR_TRUE;
+        }
+#endif
         return PR_FALSE;
     }
     return PR_TRUE;
 }
 
 #endif /* DEBUG */
 
 /*****************************************************************************/