ruby-changes:35333
From: nagachika <ko1@a...>
Date: Sat, 6 Sep 2014 00:14:35 +0900 (JST)
Subject: [ruby-changes:35333] nagachika:r47415 (ruby_2_1): merge revision(s) r45046, r45047, r45063, r45087, r45146, r45150, r45151, r45152: [Backport #9525]
nagachika 2014-09-06 00:14:23 +0900 (Sat, 06 Sep 2014) New Revision: 47415 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=47415 Log: merge revision(s) r45046,r45047,r45063,r45087,r45146,r45150,r45151,r45152: [Backport #9525] * ext/socket: Wrap struct addrinfo by struct rb_addrinfo. * ext/socket: Bypass getaddrinfo() if node and serv are numeric. Reporeted by Naotoshi Seo. [ruby-core:60801] [Bug #9525] * ext/socket/extconf.rb: Detect struct sockaddr_in6.sin6_len. * ext/socket/sockport.h (SET_SIN6_LEN): New macro. (INIT_SOCKADDR_IN6): Ditto. * ext/socket/rubysocket.h (struct rb_addrinfo): Add allocated_by_malloc field. * ext/socket/raddrinfo.c (numeric_getaddrinfo): New function. (rb_getaddrinfo): Call numeric_getaddrinfo at first. (rb_freeaddrinfo): Free struct addrinfo properly when it is allocated by numeric_getaddrinfo. * ext/socket/raddrinfo.c (numeric_getaddrinfo): Use xcalloc. Suggested by Eric Wong. https://bugs.ruby-lang.org/issues/9525#note-14 * ext/socket/raddrinfo.c (rb_getaddrinfo): second argument of MEMZERO is type. Coverity Scan found this bug. * include/ruby/win32.h, win32/win32.c (rb_w32_inet_pton): add a wrapper function for inet_pton minimum supported client is Vista, as well as inet_ntop. * ext/socket/option.c (inet_pton): use rb_w32_inet_pton, instead of inet_ntop directly, which is unavailable on older version Windows. * ext/socket/raddrinfo.c (inet_pton): use rb_w32_inet_pton, instead of inet_pton directly, which is unavailable on older version Windows. Modified directories: branches/ruby_2_1/ Modified files: branches/ruby_2_1/ChangeLog branches/ruby_2_1/ext/socket/extconf.rb branches/ruby_2_1/ext/socket/raddrinfo.c branches/ruby_2_1/ext/socket/rubysocket.h branches/ruby_2_1/ext/socket/sockport.h branches/ruby_2_1/include/ruby/win32.h branches/ruby_2_1/version.h branches/ruby_2_1/win32/win32.c Index: ruby_2_1/include/ruby/win32.h =================================================================== --- ruby_2_1/include/ruby/win32.h (revision 47414) +++ ruby_2_1/include/ruby/win32.h (revision 47415) @@ -309,6 +309,7 @@ extern char **rb_w32_get_environ(void); https://github.com/ruby/ruby/blob/trunk/ruby_2_1/include/ruby/win32.h#L309 extern void rb_w32_free_environ(char **); extern int rb_w32_map_errno(DWORD); extern const char *WSAAPI rb_w32_inet_ntop(int,const void *,char *,size_t); +extern int WSAAPI rb_w32_inet_pton(int,const char *,void *); extern DWORD rb_w32_osver(void); extern int chown(const char *, int, int); @@ -652,6 +653,9 @@ extern char *rb_w32_strerror(int); https://github.com/ruby/ruby/blob/trunk/ruby_2_1/include/ruby/win32.h#L653 #undef inet_ntop #define inet_ntop(f,a,n,l) rb_w32_inet_ntop(f,a,n,l) +#undef inet_pton +#define inet_pton(f,s,d) rb_w32_inet_pton(f,s,d) + #undef accept #define accept(s, a, l) rb_w32_accept(s, a, l) Index: ruby_2_1/ChangeLog =================================================================== --- ruby_2_1/ChangeLog (revision 47414) +++ ruby_2_1/ChangeLog (revision 47415) @@ -1,3 +1,42 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_1/ChangeLog#L1 +Sat Sep 6 00:05:02 2014 Nobuyoshi Nakada <nobu@r...> + + * include/ruby/win32.h, win32/win32.c (rb_w32_inet_pton): add a + wrapper function for inet_pton minimum supported client is + Vista, as well as inet_ntop. + +Sat Sep 6 00:05:02 2014 Kazuhiro NISHIYAMA <zn@m...> + + * ext/socket/raddrinfo.c (rb_getaddrinfo): second argument of + MEMZERO is type. Coverity Scan found this bug. + +Sat Sep 6 00:05:02 2014 Tanaka Akira <akr@f...> + + * ext/socket/raddrinfo.c (numeric_getaddrinfo): Use xcalloc. + Suggested by Eric Wong. + https://bugs.ruby-lang.org/issues/9525#note-14 + +Sat Sep 6 00:05:02 2014 Tanaka Akira <akr@f...> + + * ext/socket: Bypass getaddrinfo() if node and serv are numeric. + Reporeted by Naotoshi Seo. [ruby-core:60801] [Bug #9525] + + * ext/socket/extconf.rb: Detect struct sockaddr_in6.sin6_len. + + * ext/socket/sockport.h (SET_SIN6_LEN): New macro. + (INIT_SOCKADDR_IN6): Ditto. + + * ext/socket/rubysocket.h (struct rb_addrinfo): Add + allocated_by_malloc field. + + * ext/socket/raddrinfo.c (numeric_getaddrinfo): New function. + (rb_getaddrinfo): Call numeric_getaddrinfo at first. + (rb_freeaddrinfo): Free struct addrinfo properly when it is + allocated by numeric_getaddrinfo. + +Sat Sep 6 00:05:02 2014 Tanaka Akira <akr@f...> + + * ext/socket: Wrap struct addrinfo by struct rb_addrinfo. + Thu Sep 4 00:31:23 2014 Nobuyoshi Nakada <nobu@r...> * ext/thread/thread.c (get_array): check instance variables are Index: ruby_2_1/win32/win32.c =================================================================== --- ruby_2_1/win32/win32.c (revision 47414) +++ ruby_2_1/win32/win32.c (revision 47415) @@ -6963,6 +6963,19 @@ rb_w32_inet_ntop(int af, const void *add https://github.com/ruby/ruby/blob/trunk/ruby_2_1/win32/win32.c#L6963 } /* License: Ruby's */ +int WSAAPI +rb_w32_inet_pton(int af, const char *src, void *dst) +{ + typedef int (WSAAPI inet_pton_t)(int, const char*, void *); + inet_pton_t *pInetPton; + pInetPton = (inet_pton_t *)get_proc_address("ws2_32", "inet_pton", NULL); + if (pInetPton) { + return pInetPton(af, src, dst); + } + return 0; +} + +/* License: Ruby's */ char rb_w32_fd_is_text(int fd) { Index: ruby_2_1/ext/socket/rubysocket.h =================================================================== --- ruby_2_1/ext/socket/rubysocket.h (revision 47414) +++ ruby_2_1/ext/socket/rubysocket.h (revision 47415) @@ -280,6 +280,7 @@ int rsock_getfamily(int sockfd); https://github.com/ruby/ruby/blob/trunk/ruby_2_1/ext/socket/rubysocket.h#L280 struct rb_addrinfo { struct addrinfo *ai; + int allocated_by_malloc; }; int rb_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct rb_addrinfo **res); void rb_freeaddrinfo(struct rb_addrinfo *ai); Index: ruby_2_1/ext/socket/raddrinfo.c =================================================================== --- ruby_2_1/ext/socket/raddrinfo.c (revision 47414) +++ ruby_2_1/ext/socket/raddrinfo.c (revision 47415) @@ -171,6 +171,90 @@ nogvl_getaddrinfo(void *arg) https://github.com/ruby/ruby/blob/trunk/ruby_2_1/ext/socket/raddrinfo.c#L171 } #endif +static int +numeric_getaddrinfo(const char *node, const char *service, + const struct addrinfo *hints, + struct addrinfo **res) +{ +#ifdef HAVE_INET_PTON +# if defined __MINGW64__ +# define inet_pton(f,s,d) rb_w32_inet_pton(f,s,d) +# endif + + if (node && (!service || strspn(service, "0123456789") == strlen(service))) { + static const struct { + int socktype; + int protocol; + } list[] = { + { SOCK_STREAM, IPPROTO_TCP }, + { SOCK_DGRAM, IPPROTO_UDP }, + { SOCK_RAW, 0 } + }; + struct addrinfo *ai = NULL; + int port = service ? (unsigned short)atoi(service): 0; + int hint_family = hints ? hints->ai_family : PF_UNSPEC; + int hint_socktype = hints ? hints->ai_socktype : 0; + int hint_protocol = hints ? hints->ai_protocol : 0; + char ipv4addr[4]; +#ifdef AF_INET6 + char ipv6addr[16]; + if ((hint_family == PF_UNSPEC || hint_family == PF_INET6) && + strspn(node, "0123456789abcdefABCDEF.:") == strlen(node) && + inet_pton(AF_INET6, node, ipv6addr)) { + int i; + for (i = numberof(list)-1; 0 <= i; i--) { + if ((hint_socktype == 0 || hint_socktype == list[i].socktype) && + (hint_protocol == 0 || list[i].protocol == 0 || hint_protocol == list[i].protocol)) { + struct addrinfo *ai0 = xcalloc(1, sizeof(struct addrinfo)); + struct sockaddr_in6 *sa = xmalloc(sizeof(struct sockaddr_in6)); + INIT_SOCKADDR_IN6(sa, sizeof(struct sockaddr_in6)); + memcpy(&sa->sin6_addr, ipv6addr, sizeof(ipv6addr)); + sa->sin6_port = htons(port); + ai0->ai_family = PF_INET6; + ai0->ai_socktype = list[i].socktype; + ai0->ai_protocol = hint_protocol ? hint_protocol : list[i].protocol; + ai0->ai_addrlen = sizeof(struct sockaddr_in6); + ai0->ai_addr = (struct sockaddr *)sa; + ai0->ai_canonname = NULL; + ai0->ai_next = ai; + ai = ai0; + } + } + } + else +#endif + if ((hint_family == PF_UNSPEC || hint_family == PF_INET) && + strspn(node, "0123456789.") == strlen(node) && + inet_pton(AF_INET, node, ipv4addr)) { + int i; + for (i = numberof(list)-1; 0 <= i; i--) { + if ((hint_socktype == 0 || hint_socktype == list[i].socktype) && + (hint_protocol == 0 || list[i].protocol == 0 || hint_protocol == list[i].protocol)) { + struct addrinfo *ai0 = xcalloc(1, sizeof(struct addrinfo)); + struct sockaddr_in *sa = xmalloc(sizeof(struct sockaddr_in)); + INIT_SOCKADDR_IN(sa, sizeof(struct sockaddr_in)); + memcpy(&sa->sin_addr, ipv4addr, sizeof(ipv4addr)); + sa->sin_port = htons(port); + ai0->ai_family = PF_INET; + ai0->ai_socktype = list[i].socktype; + ai0->ai_protocol = hint_protocol ? hint_protocol : list[i].protocol; + ai0->ai_addrlen = sizeof(struct sockaddr_in); + ai0->ai_addr = (struct sockaddr *)sa; + ai0->ai_canonname = NULL; + ai0->ai_next = ai; + ai = ai0; + } + } + } + if (ai) { + *res = ai; + return 0; + } + } +#endif + return EAI_FAIL; +} + int rb_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, @@ -178,21 +262,28 @@ rb_getaddrinfo(const char *node, const c https://github.com/ruby/ruby/blob/trunk/ruby_2_1/ext/socket/raddrinfo.c#L262 { struct addrinfo *ai; int ret; + int allocated_by_malloc = 0; + ret = numeric_getaddrinfo(node, service, hints, &ai); + if (ret == 0) + allocated_by_malloc = 1; + else { #ifdef GETADDRINFO_EMU - ret = getaddrinfo(node, service, hints, &ai); + ret = getaddrinfo(node, service, hints, &ai); #else - struct getaddrinfo_arg arg; - MEMZERO(&arg, sizeof arg, 1); - arg.node = node; - arg.service = service; - arg.hints = hints; - arg.res = &ai; - ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getaddrinfo, &arg, RUBY_UBF_IO, 0); + struct getaddrinfo_arg arg; + MEMZERO(&arg, struct getaddrinfo_arg, 1); + arg.node = node; + arg.service = service; + arg.hints = hints; + arg.res = &ai; + ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getaddrinfo, &arg, RUBY_UBF_IO, 0); #endif + } if (ret == 0) { *res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo)); + (*res)->allocated_by_malloc = allocated_by_malloc; (*res)->ai = ai; } return ret; @@ -201,7 +292,18 @@ rb_getaddrinfo(const char *node, const c https://github.com/ruby/ruby/blob/trunk/ruby_2_1/ext/socket/raddrinfo.c#L292 void rb_freeaddrinfo(struct rb_addrinfo *ai) { - freeaddrinfo(ai->ai); + if (!ai->allocated_by_malloc) + freeaddrinfo(ai->ai); + else { + struct addrinfo *ai1, *ai2; + ai1 = ai->ai; + while (ai1) { + ai2 = ai1->ai_next; + xfree(ai1->ai_addr); + xfree(ai1); + ai1 = ai2; + } + } xfree(ai); } Index: ruby_2_1/ext/socket/sockport.h =================================================================== --- ruby_2_1/ext/socket/sockport.h (revision 47414) +++ ruby_2_1/ext/socket/sockport.h (revision 47415) @@ -29,6 +29,12 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_1/ext/socket/sockport.h#L29 # define SET_SIN_LEN(sa, len) SET_SA_LEN((struct sockaddr *)(sa), (len)) #endif +#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN +# define SET_SIN6_LEN(sa, len) (void)((sa)->sin6_len = (len)) +#else +# define SET_SIN6_LEN(sa, len) SET_SA_LEN((struct sockaddr *)(sa), (len)) +#endif + #define INIT_SOCKADDR(addr, family, len) \ do { \ struct sockaddr *init_sockaddr_ptr = (addr); \ @@ -47,6 +53,15 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_1/ext/socket/sockport.h#L53 SET_SIN_LEN(init_sockaddr_ptr, init_sockaddr_len); \ } while (0) +#define INIT_SOCKADDR_IN6(addr, len) \ + do { \ + struct sockaddr_in6 *init_sockaddr_ptr = (addr); \ + socklen_t init_sockaddr_len = (len); \ + memset(init_sockaddr_ptr, 0, init_sockaddr_len); \ + init_sockaddr_ptr->sin6_family = AF_INET6; \ + SET_SIN6_LEN(init_sockaddr_ptr, init_sockaddr_len); \ + } while (0) + /* for strict-aliasing rule */ #ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN Index: ruby_2_1/ext/socket/extconf.rb =================================================================== --- ruby_2_1/ext/socket/extconf.rb (revision 47414) +++ ruby_2_1/ext/socket/extconf.rb (revision 47415) @@ -332,6 +332,7 @@ end https://github.com/ruby/ruby/blob/trunk/ruby_2_1/ext/socket/extconf.rb#L332 have_struct_member("struct sockaddr", "sa_len", headers) # 4.4BSD have_struct_member("struct sockaddr_in", "sin_len", headers) # 4.4BSD +have_struct_member("struct sockaddr_in6", "sin6_len", headers) # 4.4BSD if have_type("struct sockaddr_un", headers) # POSIX have_struct_member("struct sockaddr_un", "sun_len", headers) # 4.4BSD Index: ruby_2_1/version.h =================================================================== --- ruby_2_1/version.h (revision 47414) +++ ruby_2_1/version.h (revision 47415) @@ -1,10 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_1/version.h#L1 #define RUBY_VERSION "2.1.2" -#define RUBY_RELEASE_DATE "2014-09-04" -#define RUBY_PATCHLEVEL 222 +#define RUBY_RELEASE_DATE "2014-09-06" +#define RUBY_PATCHLEVEL 223 #define RUBY_RELEASE_YEAR 2014 #define RUBY_RELEASE_MONTH 9 -#define RUBY_RELEASE_DAY 4 +#define RUBY_RELEASE_DAY 6 #include "ruby/version.h" Property changes on: ruby_2_1 ___________________________________________________________________ Modified: svn:mergeinfo Merged /trunk:r45047,45063,45087,45146,45150-45152 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/