]> granicus.if.org Git - php/commitdiff
Bug #38687 - sockaddr local storage insufficient for all sock families
authorSara Golemon <pollita@php.net>
Mon, 11 Sep 2006 19:18:06 +0000 (19:18 +0000)
committerSara Golemon <pollita@php.net>
Mon, 11 Sep 2006 19:18:06 +0000 (19:18 +0000)
main/network.c

index 0832890389bfe83bcf8ee6bfbcf8f6fa4ecbe2e2..9e46a450d0985fb55afbe37a1f4fa367c5f1b409 100644 (file)
@@ -787,37 +787,46 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short
                        /* make a connection attempt */
 
                        if (bindto) {
-                               struct sockaddr local_address;
-                       
+                               struct sockaddr *local_address = NULL;
+                               int local_address_len = 0;
+       
                                if (sa->sa_family == AF_INET) {
-                                       struct sockaddr_in *in4 = (struct sockaddr_in*)&local_address;
-                               
+                                       struct sockaddr_in *in4 = emalloc(sizeof(struct sockaddr_in));
+
+                                       local_address = (struct sockaddr*)in4;
+                                       local_address_len = sizeof(struct sockaddr_in);
+
                                        in4->sin_family = sa->sa_family;
                                        in4->sin_port = htons(bindport);
                                        if (!inet_aton(bindto, &in4->sin_addr)) {
-                                               goto bad_ip;
+                                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid IP Address: %s", bindto);
+                                               goto skip_bind;
                                        }
                                        memset(&(in4->sin_zero), 0, sizeof(in4->sin_zero));
                                }
 #if HAVE_IPV6 && HAVE_INET_PTON
                                 else { /* IPV6 */
-                                       struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&local_address;
+                                       struct sockaddr_in6 *in6 = emalloc(sizeof(struct sockaddr_in6));
+
+                                       local_address = (struct sockaddr*)in6;
+                                       local_address_len = sizeof(struct sockaddr_in6);
                                
                                        in6->sin6_family = sa->sa_family;
                                        in6->sin6_port = htons(bindport);
                                        if (inet_pton(AF_INET6, bindto, &in6->sin6_addr) < 1) {
-                                               goto bad_ip;
+                                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid IP Address: %s", bindto);
+                                               goto skip_bind;
                                        }
                                }
 #endif
-                               if (bind(sock, &local_address, sizeof(struct sockaddr))) {
+                               if (!local_address || bind(sock, local_address, local_address_len)) {
                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to bind to '%s:%d', system said: %s", bindto, bindport, strerror(errno));
                                }
-                               goto bind_done;
-bad_ip:
-                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid IP Address: %s", bindto);
+skip_bind:
+                               if (local_address) {
+                                       efree(local_address);
+                               }
                        }
-bind_done:
                        /* free error string recieved during previous iteration (if any) */
                        if (error_string && *error_string) {
                                efree(*error_string);