Skip to content

Commit 3598e34

Browse files
committed
merge revision(s) r45046,r45047,r45063,r45087,r45146,r45150,r45151,r45152: [Backport ruby#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 ruby#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
1 parent 645588b commit 3598e34

File tree

8 files changed

+187
-12
lines changed

8 files changed

+187
-12
lines changed

ChangeLog

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,42 @@
1+
Sat Sep 6 00:05:02 2014 Nobuyoshi Nakada <[email protected]>
2+
3+
* include/ruby/win32.h, win32/win32.c (rb_w32_inet_pton): add a
4+
wrapper function for inet_pton minimum supported client is
5+
Vista, as well as inet_ntop.
6+
7+
Sat Sep 6 00:05:02 2014 Kazuhiro NISHIYAMA <[email protected]>
8+
9+
* ext/socket/raddrinfo.c (rb_getaddrinfo): second argument of
10+
MEMZERO is type. Coverity Scan found this bug.
11+
12+
Sat Sep 6 00:05:02 2014 Tanaka Akira <[email protected]>
13+
14+
* ext/socket/raddrinfo.c (numeric_getaddrinfo): Use xcalloc.
15+
Suggested by Eric Wong.
16+
https://bugs.ruby-lang.org/issues/9525#note-14
17+
18+
Sat Sep 6 00:05:02 2014 Tanaka Akira <[email protected]>
19+
20+
* ext/socket: Bypass getaddrinfo() if node and serv are numeric.
21+
Reporeted by Naotoshi Seo. [ruby-core:60801] [Bug #9525]
22+
23+
* ext/socket/extconf.rb: Detect struct sockaddr_in6.sin6_len.
24+
25+
* ext/socket/sockport.h (SET_SIN6_LEN): New macro.
26+
(INIT_SOCKADDR_IN6): Ditto.
27+
28+
* ext/socket/rubysocket.h (struct rb_addrinfo): Add
29+
allocated_by_malloc field.
30+
31+
* ext/socket/raddrinfo.c (numeric_getaddrinfo): New function.
32+
(rb_getaddrinfo): Call numeric_getaddrinfo at first.
33+
(rb_freeaddrinfo): Free struct addrinfo properly when it is
34+
allocated by numeric_getaddrinfo.
35+
36+
Sat Sep 6 00:05:02 2014 Tanaka Akira <[email protected]>
37+
38+
* ext/socket: Wrap struct addrinfo by struct rb_addrinfo.
39+
140
Thu Sep 4 00:31:23 2014 Nobuyoshi Nakada <[email protected]>
241

342
* ext/thread/thread.c (get_array): check instance variables are

ext/socket/extconf.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ def test_recvmsg_with_msg_peek_creates_fds(headers)
332332

333333
have_struct_member("struct sockaddr", "sa_len", headers) # 4.4BSD
334334
have_struct_member("struct sockaddr_in", "sin_len", headers) # 4.4BSD
335+
have_struct_member("struct sockaddr_in6", "sin6_len", headers) # 4.4BSD
335336

336337
if have_type("struct sockaddr_un", headers) # POSIX
337338
have_struct_member("struct sockaddr_un", "sun_len", headers) # 4.4BSD

ext/socket/raddrinfo.c

Lines changed: 111 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -171,28 +171,119 @@ nogvl_getaddrinfo(void *arg)
171171
}
172172
#endif
173173

174+
static int
175+
numeric_getaddrinfo(const char *node, const char *service,
176+
const struct addrinfo *hints,
177+
struct addrinfo **res)
178+
{
179+
#ifdef HAVE_INET_PTON
180+
# if defined __MINGW64__
181+
# define inet_pton(f,s,d) rb_w32_inet_pton(f,s,d)
182+
# endif
183+
184+
if (node && (!service || strspn(service, "0123456789") == strlen(service))) {
185+
static const struct {
186+
int socktype;
187+
int protocol;
188+
} list[] = {
189+
{ SOCK_STREAM, IPPROTO_TCP },
190+
{ SOCK_DGRAM, IPPROTO_UDP },
191+
{ SOCK_RAW, 0 }
192+
};
193+
struct addrinfo *ai = NULL;
194+
int port = service ? (unsigned short)atoi(service): 0;
195+
int hint_family = hints ? hints->ai_family : PF_UNSPEC;
196+
int hint_socktype = hints ? hints->ai_socktype : 0;
197+
int hint_protocol = hints ? hints->ai_protocol : 0;
198+
char ipv4addr[4];
199+
#ifdef AF_INET6
200+
char ipv6addr[16];
201+
if ((hint_family == PF_UNSPEC || hint_family == PF_INET6) &&
202+
strspn(node, "0123456789abcdefABCDEF.:") == strlen(node) &&
203+
inet_pton(AF_INET6, node, ipv6addr)) {
204+
int i;
205+
for (i = numberof(list)-1; 0 <= i; i--) {
206+
if ((hint_socktype == 0 || hint_socktype == list[i].socktype) &&
207+
(hint_protocol == 0 || list[i].protocol == 0 || hint_protocol == list[i].protocol)) {
208+
struct addrinfo *ai0 = xcalloc(1, sizeof(struct addrinfo));
209+
struct sockaddr_in6 *sa = xmalloc(sizeof(struct sockaddr_in6));
210+
INIT_SOCKADDR_IN6(sa, sizeof(struct sockaddr_in6));
211+
memcpy(&sa->sin6_addr, ipv6addr, sizeof(ipv6addr));
212+
sa->sin6_port = htons(port);
213+
ai0->ai_family = PF_INET6;
214+
ai0->ai_socktype = list[i].socktype;
215+
ai0->ai_protocol = hint_protocol ? hint_protocol : list[i].protocol;
216+
ai0->ai_addrlen = sizeof(struct sockaddr_in6);
217+
ai0->ai_addr = (struct sockaddr *)sa;
218+
ai0->ai_canonname = NULL;
219+
ai0->ai_next = ai;
220+
ai = ai0;
221+
}
222+
}
223+
}
224+
else
225+
#endif
226+
if ((hint_family == PF_UNSPEC || hint_family == PF_INET) &&
227+
strspn(node, "0123456789.") == strlen(node) &&
228+
inet_pton(AF_INET, node, ipv4addr)) {
229+
int i;
230+
for (i = numberof(list)-1; 0 <= i; i--) {
231+
if ((hint_socktype == 0 || hint_socktype == list[i].socktype) &&
232+
(hint_protocol == 0 || list[i].protocol == 0 || hint_protocol == list[i].protocol)) {
233+
struct addrinfo *ai0 = xcalloc(1, sizeof(struct addrinfo));
234+
struct sockaddr_in *sa = xmalloc(sizeof(struct sockaddr_in));
235+
INIT_SOCKADDR_IN(sa, sizeof(struct sockaddr_in));
236+
memcpy(&sa->sin_addr, ipv4addr, sizeof(ipv4addr));
237+
sa->sin_port = htons(port);
238+
ai0->ai_family = PF_INET;
239+
ai0->ai_socktype = list[i].socktype;
240+
ai0->ai_protocol = hint_protocol ? hint_protocol : list[i].protocol;
241+
ai0->ai_addrlen = sizeof(struct sockaddr_in);
242+
ai0->ai_addr = (struct sockaddr *)sa;
243+
ai0->ai_canonname = NULL;
244+
ai0->ai_next = ai;
245+
ai = ai0;
246+
}
247+
}
248+
}
249+
if (ai) {
250+
*res = ai;
251+
return 0;
252+
}
253+
}
254+
#endif
255+
return EAI_FAIL;
256+
}
257+
174258
int
175259
rb_getaddrinfo(const char *node, const char *service,
176260
const struct addrinfo *hints,
177261
struct rb_addrinfo **res)
178262
{
179263
struct addrinfo *ai;
180264
int ret;
265+
int allocated_by_malloc = 0;
181266

267+
ret = numeric_getaddrinfo(node, service, hints, &ai);
268+
if (ret == 0)
269+
allocated_by_malloc = 1;
270+
else {
182271
#ifdef GETADDRINFO_EMU
183-
ret = getaddrinfo(node, service, hints, &ai);
272+
ret = getaddrinfo(node, service, hints, &ai);
184273
#else
185-
struct getaddrinfo_arg arg;
186-
MEMZERO(&arg, sizeof arg, 1);
187-
arg.node = node;
188-
arg.service = service;
189-
arg.hints = hints;
190-
arg.res = &ai;
191-
ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getaddrinfo, &arg, RUBY_UBF_IO, 0);
274+
struct getaddrinfo_arg arg;
275+
MEMZERO(&arg, struct getaddrinfo_arg, 1);
276+
arg.node = node;
277+
arg.service = service;
278+
arg.hints = hints;
279+
arg.res = &ai;
280+
ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getaddrinfo, &arg, RUBY_UBF_IO, 0);
192281
#endif
282+
}
193283

194284
if (ret == 0) {
195285
*res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo));
286+
(*res)->allocated_by_malloc = allocated_by_malloc;
196287
(*res)->ai = ai;
197288
}
198289
return ret;
@@ -201,7 +292,18 @@ rb_getaddrinfo(const char *node, const char *service,
201292
void
202293
rb_freeaddrinfo(struct rb_addrinfo *ai)
203294
{
204-
freeaddrinfo(ai->ai);
295+
if (!ai->allocated_by_malloc)
296+
freeaddrinfo(ai->ai);
297+
else {
298+
struct addrinfo *ai1, *ai2;
299+
ai1 = ai->ai;
300+
while (ai1) {
301+
ai2 = ai1->ai_next;
302+
xfree(ai1->ai_addr);
303+
xfree(ai1);
304+
ai1 = ai2;
305+
}
306+
}
205307
xfree(ai);
206308
}
207309

ext/socket/rubysocket.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ int rsock_getfamily(int sockfd);
280280

281281
struct rb_addrinfo {
282282
struct addrinfo *ai;
283+
int allocated_by_malloc;
283284
};
284285
int rb_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct rb_addrinfo **res);
285286
void rb_freeaddrinfo(struct rb_addrinfo *ai);

ext/socket/sockport.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@
2929
# define SET_SIN_LEN(sa, len) SET_SA_LEN((struct sockaddr *)(sa), (len))
3030
#endif
3131

32+
#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
33+
# define SET_SIN6_LEN(sa, len) (void)((sa)->sin6_len = (len))
34+
#else
35+
# define SET_SIN6_LEN(sa, len) SET_SA_LEN((struct sockaddr *)(sa), (len))
36+
#endif
37+
3238
#define INIT_SOCKADDR(addr, family, len) \
3339
do { \
3440
struct sockaddr *init_sockaddr_ptr = (addr); \
@@ -47,6 +53,15 @@
4753
SET_SIN_LEN(init_sockaddr_ptr, init_sockaddr_len); \
4854
} while (0)
4955

56+
#define INIT_SOCKADDR_IN6(addr, len) \
57+
do { \
58+
struct sockaddr_in6 *init_sockaddr_ptr = (addr); \
59+
socklen_t init_sockaddr_len = (len); \
60+
memset(init_sockaddr_ptr, 0, init_sockaddr_len); \
61+
init_sockaddr_ptr->sin6_family = AF_INET6; \
62+
SET_SIN6_LEN(init_sockaddr_ptr, init_sockaddr_len); \
63+
} while (0)
64+
5065

5166
/* for strict-aliasing rule */
5267
#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN

include/ruby/win32.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ extern char **rb_w32_get_environ(void);
309309
extern void rb_w32_free_environ(char **);
310310
extern int rb_w32_map_errno(DWORD);
311311
extern const char *WSAAPI rb_w32_inet_ntop(int,const void *,char *,size_t);
312+
extern int WSAAPI rb_w32_inet_pton(int,const char *,void *);
312313
extern DWORD rb_w32_osver(void);
313314

314315
extern int chown(const char *, int, int);
@@ -652,6 +653,9 @@ extern char *rb_w32_strerror(int);
652653
#undef inet_ntop
653654
#define inet_ntop(f,a,n,l) rb_w32_inet_ntop(f,a,n,l)
654655

656+
#undef inet_pton
657+
#define inet_pton(f,s,d) rb_w32_inet_pton(f,s,d)
658+
655659
#undef accept
656660
#define accept(s, a, l) rb_w32_accept(s, a, l)
657661

version.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#define RUBY_VERSION "2.1.2"
2-
#define RUBY_RELEASE_DATE "2014-09-04"
3-
#define RUBY_PATCHLEVEL 222
2+
#define RUBY_RELEASE_DATE "2014-09-06"
3+
#define RUBY_PATCHLEVEL 223
44

55
#define RUBY_RELEASE_YEAR 2014
66
#define RUBY_RELEASE_MONTH 9
7-
#define RUBY_RELEASE_DAY 4
7+
#define RUBY_RELEASE_DAY 6
88

99
#include "ruby/version.h"
1010

win32/win32.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6962,6 +6962,19 @@ rb_w32_inet_ntop(int af, const void *addr, char *numaddr, size_t numaddr_len)
69626962
return numaddr;
69636963
}
69646964

6965+
/* License: Ruby's */
6966+
int WSAAPI
6967+
rb_w32_inet_pton(int af, const char *src, void *dst)
6968+
{
6969+
typedef int (WSAAPI inet_pton_t)(int, const char*, void *);
6970+
inet_pton_t *pInetPton;
6971+
pInetPton = (inet_pton_t *)get_proc_address("ws2_32", "inet_pton", NULL);
6972+
if (pInetPton) {
6973+
return pInetPton(af, src, dst);
6974+
}
6975+
return 0;
6976+
}
6977+
69656978
/* License: Ruby's */
69666979
char
69676980
rb_w32_fd_is_text(int fd)

0 commit comments

Comments
 (0)