summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-02-19 14:01:17 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-02-19 14:01:17 +0000
commit09396dcf21d6d769f0537aacce69369132e9a4eb (patch)
tree08dea71b18f6f3aaf2cd6d4dbb8be226d1b460e7 /ext
parent98f82fc633d327350ca1f098d71b7e0bd5208bd8 (diff)
* ext/socket/ancdata.c (make_io_for_unix_rights): cmsg_len may be
bigger than msg_controllen. freeze unix_rights array. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22454 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
-rw-r--r--ext/socket/ancdata.c26
1 files changed, 15 insertions, 11 deletions
diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c
index 5c3f58e8d4..ffbf0e019c 100644
--- a/ext/socket/ancdata.c
+++ b/ext/socket/ancdata.c
@@ -1146,15 +1146,19 @@ discard_cmsg_resource(struct msghdr *mh)
#if defined(HAVE_ST_MSG_CONTROL)
static void
-make_io_for_unix_rights(VALUE ctl, struct cmsghdr *cmh)
+make_io_for_unix_rights(VALUE ctl, struct cmsghdr *cmh, char *msg_end)
{
if (cmh->cmsg_level == SOL_SOCKET && cmh->cmsg_type == SCM_RIGHTS) {
- int *fdp = (int *)CMSG_DATA(cmh);
- int *end = (int *)((char *)cmh + cmh->cmsg_len);
- while (fdp < end) {
+ int *fdp, *end;
+ VALUE ary = rb_ary_new();
+ rb_ivar_set(ctl, rb_intern("unix_rights"), ary);
+ fdp = (int *)CMSG_DATA(cmh);
+ end = (int *)((char *)cmh + cmh->cmsg_len);
+ while ((char *)fdp + sizeof(int) <= (char *)end &&
+ (char *)fdp + sizeof(int) <= msg_end) {
int fd = *fdp;
struct stat stbuf;
- VALUE io, ary;
+ VALUE io;
if (fstat(fd, &stbuf) == -1)
rb_raise(rb_eSocket, "invalid fd in SCM_RIGHTS");
if (S_ISSOCK(stbuf.st_mode))
@@ -1162,13 +1166,10 @@ make_io_for_unix_rights(VALUE ctl, struct cmsghdr *cmh)
else
io = rb_io_fdopen(fd, O_RDWR, NULL);
ary = rb_attr_get(ctl, rb_intern("unix_rights"));
- if (NIL_P(ary)) {
- ary = rb_ary_new();
- rb_ivar_set(ctl, rb_intern("unix_rights"), ary);
- }
rb_ary_push(ary, io);
fdp++;
}
+ OBJ_FREEZE(ary);
}
}
#endif
@@ -1343,15 +1344,18 @@ bsock_recvmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock)
#if defined(HAVE_ST_MSG_CONTROL)
family = rb_sock_getfamily(fptr->fd);
if (mh.msg_controllen) {
+ char *msg_end = (char *)mh.msg_control + mh.msg_controllen;
for (cmh = CMSG_FIRSTHDR(&mh); cmh != NULL; cmh = CMSG_NXTHDR(&mh, cmh)) {
VALUE ctl;
+ char *ctl_end;
size_t clen;
if (cmh->cmsg_len == 0) {
rb_raise(rb_eTypeError, "invalid control message (cmsg_len == 0)");
}
- clen = (char*)cmh + cmh->cmsg_len - (char*)CMSG_DATA(cmh);
+ ctl_end = (char*)cmh + cmh->cmsg_len;
+ clen = (ctl_end <= msg_end ? ctl_end : msg_end) - (char*)CMSG_DATA(cmh);
ctl = ancdata_new(family, cmh->cmsg_level, cmh->cmsg_type, rb_tainted_str_new((char*)CMSG_DATA(cmh), clen));
- make_io_for_unix_rights(ctl, cmh);
+ make_io_for_unix_rights(ctl, cmh, msg_end);
rb_ary_push(ret, ctl);
}
}