Bugzilla bug #77264: the IsValidNetAddrLen() check should accept both NSPRPUB_CLIENT_BRANCH
authorwtc%netscape.com
Wed, 23 May 2001 04:16:25 +0000
branchNSPRPUB_CLIENT_BRANCH
changeset 1898 823ac813127ae5fe255f89d232988db67237254b
parent 1896 8d84200691f91eb2ee0ad7bf8b0af2c1a6ad222f
child 1899 3611ec22cb8ba48d004094186e70e5881b39b6ed
child 1900 36a7addce1c82e87e8998b3c3eb1e93058f73039
child 1904 2999f349654d0386a7453e465bec310f61566852
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 NSPRPUB_CLIENT_BRANCH
pr/src/io/prsocket.c
pr/src/pthreads/ptio.c
--- a/pr/src/io/prsocket.c
+++ b/pr/src/io/prsocket.c
@@ -44,31 +44,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
@@ -169,16 +169,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 */
 
 /*****************************************************************************/