summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-09-05 15:14:23 +0000
committernagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-09-05 15:14:23 +0000
commit667af1ee3149ba51a5559a3db3d1fc52fda06bed (patch)
treeb39bc8069e54f596b8cf89829bf202fe96a3f661
parentaac5c2c7affaa188b84c4f9ccf8b21e83aa21141 (diff)
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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_1@47415 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog39
-rw-r--r--ext/socket/extconf.rb1
-rw-r--r--ext/socket/raddrinfo.c120
-rw-r--r--ext/socket/rubysocket.h1
-rw-r--r--ext/socket/sockport.h15
-rw-r--r--include/ruby/win32.h4
-rw-r--r--version.h6
-rw-r--r--win32/win32.c13
8 files changed, 187 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index 6a87536bfd..332d9507b3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,42 @@
+Sat Sep 6 00:05:02 2014 Nobuyoshi Nakada <[email protected]>
+
+ * 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 <[email protected]>
+
+ * 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 <[email protected]>
+
+ * 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 <[email protected]>
+
+ * 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 <[email protected]>
+
+ * ext/socket: Wrap struct addrinfo by struct rb_addrinfo.
+
Thu Sep 4 00:31:23 2014 Nobuyoshi Nakada <[email protected]>
* ext/thread/thread.c (get_array): check instance variables are
diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb
index f3be5862f0..6c61324e38 100644
--- a/ext/socket/extconf.rb
+++ b/ext/socket/extconf.rb
@@ -332,6 +332,7 @@ end
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
diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c
index 619f123dce..3deadd1aea 100644
--- a/ext/socket/raddrinfo.c
+++ b/ext/socket/raddrinfo.c
@@ -171,6 +171,90 @@ nogvl_getaddrinfo(void *arg)
}
#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 char *service,
{
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 char *service,
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);
}
diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h
index 74896ce30a..a4893d9698 100644
--- a/ext/socket/rubysocket.h
+++ b/ext/socket/rubysocket.h
@@ -280,6 +280,7 @@ int rsock_getfamily(int sockfd);
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);
diff --git a/ext/socket/sockport.h b/ext/socket/sockport.h
index a3c698e8a4..2b58958ae7 100644
--- a/ext/socket/sockport.h
+++ b/ext/socket/sockport.h
@@ -29,6 +29,12 @@
# 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 @@
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
diff --git a/include/ruby/win32.h b/include/ruby/win32.h
index 067ac010da..64fbdf2744 100644
--- a/include/ruby/win32.h
+++ b/include/ruby/win32.h
@@ -309,6 +309,7 @@ extern char **rb_w32_get_environ(void);
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);
#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)
diff --git a/version.h b/version.h
index 9949600482..ad27c5bb84 100644
--- a/version.h
+++ b/version.h
@@ -1,10 +1,10 @@
#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"
diff --git a/win32/win32.c b/win32/win32.c
index a2ced890ff..3051a97f56 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -6963,6 +6963,19 @@ rb_w32_inet_ntop(int af, const void *addr, char *numaddr, size_t numaddr_len)
}
/* 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)
{