1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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
This commit is contained in:
nagachika 2014-09-05 15:14:23 +00:00
parent aac5c2c7af
commit 667af1ee31
8 changed files with 187 additions and 12 deletions

View file

@ -1,3 +1,42 @@
Sat Sep 6 00:05:02 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
* 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@mbf.nifty.com>
* 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@fsij.org>
* 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@fsij.org>
* 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@fsij.org>
* ext/socket: Wrap struct addrinfo by struct rb_addrinfo.
Thu Sep 4 00:31:23 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/thread/thread.c (get_array): check instance variables are

View file

@ -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

View file

@ -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);
}

View file

@ -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);

View file

@ -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

View file

@ -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)

View file

@ -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"

View file

@ -6962,6 +6962,19 @@ rb_w32_inet_ntop(int af, const void *addr, char *numaddr, size_t numaddr_len)
return numaddr;
}
/* 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)