gsocket: Work around broken CMSG_FIRSTHDR()

As RFC 2292 points out, some platforms (e.g. Darwin 9.8.0) provide
CMSG_FIRSTHDR(msg) which just returns msg.msg_control without first
checking if msg.msg_controllen is non-zero. We need a workaround for
such platforms not to let g_socket_receive_message() segfault.

https://bugzilla.gnome.org/show_bug.cgi?id=690388
This commit is contained in:
PHO
2012-12-18 08:33:50 +09:00
committed by Dan Winship
parent 780871d273
commit f0f6c8d231

View File

@@ -4154,33 +4154,36 @@ g_socket_receive_message (GSocket *socket,
GPtrArray *my_messages = NULL; GPtrArray *my_messages = NULL;
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg)) if (msg.msg_controllen >= sizeof (struct cmsghdr))
{ {
GSocketControlMessage *message; for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg))
{
GSocketControlMessage *message;
message = g_socket_control_message_deserialize (cmsg->cmsg_level, message = g_socket_control_message_deserialize (cmsg->cmsg_level,
cmsg->cmsg_type, cmsg->cmsg_type,
cmsg->cmsg_len - ((char *)CMSG_DATA (cmsg) - (char *)cmsg), cmsg->cmsg_len - ((char *)CMSG_DATA (cmsg) - (char *)cmsg),
CMSG_DATA (cmsg)); CMSG_DATA (cmsg));
if (message == NULL) if (message == NULL)
/* We've already spewed about the problem in the /* We've already spewed about the problem in the
deserialization code, so just continue */ deserialization code, so just continue */
continue; continue;
if (messages == NULL) if (messages == NULL)
{ {
/* we have to do it this way if the user ignores the /* we have to do it this way if the user ignores the
* messages so that we will close any received fds. * messages so that we will close any received fds.
*/ */
g_object_unref (message); g_object_unref (message);
} }
else else
{ {
if (my_messages == NULL) if (my_messages == NULL)
my_messages = g_ptr_array_new (); my_messages = g_ptr_array_new ();
g_ptr_array_add (my_messages, message); g_ptr_array_add (my_messages, message);
} }
} }
}
if (num_messages) if (num_messages)
*num_messages = my_messages != NULL ? my_messages->len : 0; *num_messages = my_messages != NULL ? my_messages->len : 0;