mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-04-22 15:19:16 +02:00
Bug 616877 – Several issues with g_socket_receive_message
The messages array was not reallocated correctly because it was using malloc instead of realloc. Also, if the user requested messages but none were received we would segfault. Rewrite the code to fix this and, for better readability, use GPtrArray instead of rolling our own. Also make the docs mention that the user need to free the returned GSocketControlMessage objects using g_object_unref(). Clarify that *messages may be set to %NULL if there are no messages (this will save pointless allocs of arrays). Finally, the Win32 version didn't set messages to the expected value. https://bugzilla.gnome.org/show_bug.cgi?id=616877 Signed-off-by: David Zeuthen <davidz@redhat.com>
This commit is contained in:
parent
cd062e841f
commit
3ceddd74bb
@ -2962,7 +2962,7 @@ g_socket_send_message (GSocket *socket,
|
|||||||
* @address: a pointer to a #GSocketAddress pointer, or %NULL
|
* @address: a pointer to a #GSocketAddress pointer, or %NULL
|
||||||
* @vectors: an array of #GInputVector structs
|
* @vectors: an array of #GInputVector structs
|
||||||
* @num_vectors: the number of elements in @vectors, or -1
|
* @num_vectors: the number of elements in @vectors, or -1
|
||||||
* @messages: a pointer which will be filled with an array of
|
* @messages: a pointer which may be filled with an array of
|
||||||
* #GSocketControlMessages, or %NULL
|
* #GSocketControlMessages, or %NULL
|
||||||
* @num_messages: a pointer which will be filled with the number of
|
* @num_messages: a pointer which will be filled with the number of
|
||||||
* elements in @messages, or %NULL
|
* elements in @messages, or %NULL
|
||||||
@ -2990,12 +2990,13 @@ g_socket_send_message (GSocket *socket,
|
|||||||
* single '\0' byte for the purposes of transferring ancillary data.
|
* single '\0' byte for the purposes of transferring ancillary data.
|
||||||
*
|
*
|
||||||
* @messages, if non-%NULL, will be set to point to a newly-allocated
|
* @messages, if non-%NULL, will be set to point to a newly-allocated
|
||||||
* array of #GSocketControlMessage instances. These correspond to the
|
* array of #GSocketControlMessage instances or %NULL if no such
|
||||||
* control messages received from the kernel, one
|
* messages was received. These correspond to the control messages
|
||||||
* #GSocketControlMessage per message from the kernel. This array is
|
* received from the kernel, one #GSocketControlMessage per message
|
||||||
* %NULL-terminated and must be freed by the caller using g_free(). If
|
* from the kernel. This array is %NULL-terminated and must be freed
|
||||||
* @messages is %NULL, any control messages received will be
|
* by the caller using g_free() after calling g_object_unref() on each
|
||||||
* discarded.
|
* element. If @messages is %NULL, any control messages received will
|
||||||
|
* be discarded.
|
||||||
*
|
*
|
||||||
* @num_messages, if non-%NULL, will be set to the number of control
|
* @num_messages, if non-%NULL, will be set to the number of control
|
||||||
* messages received.
|
* messages received.
|
||||||
@ -3165,8 +3166,7 @@ g_socket_receive_message (GSocket *socket,
|
|||||||
|
|
||||||
/* decode control messages */
|
/* decode control messages */
|
||||||
{
|
{
|
||||||
GSocketControlMessage **my_messages = NULL;
|
GPtrArray *my_messages = NULL;
|
||||||
gint allocated = 0, index = 0;
|
|
||||||
const gchar *scm_pointer;
|
const gchar *scm_pointer;
|
||||||
struct cmsghdr *cmsg;
|
struct cmsghdr *cmsg;
|
||||||
gsize scm_size;
|
gsize scm_size;
|
||||||
@ -3187,35 +3187,39 @@ g_socket_receive_message (GSocket *socket,
|
|||||||
deserialization code, so just continue */
|
deserialization code, so just continue */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (index == allocated)
|
if (messages == NULL)
|
||||||
{
|
{
|
||||||
/* estimated 99% case: exactly 1 control message */
|
/* we have to do it this way if the user ignores the
|
||||||
allocated = MAX (allocated * 2, 1);
|
* messages so that we will close any received fds.
|
||||||
my_messages = g_new (GSocketControlMessage *, (allocated + 1));
|
*/
|
||||||
}
|
g_object_unref (message);
|
||||||
|
|
||||||
my_messages[index++] = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num_messages)
|
|
||||||
*num_messages = index;
|
|
||||||
|
|
||||||
if (messages)
|
|
||||||
{
|
|
||||||
my_messages[index++] = NULL;
|
|
||||||
*messages = my_messages;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gint i;
|
if (my_messages == NULL)
|
||||||
|
my_messages = g_ptr_array_new ();
|
||||||
|
g_ptr_array_add (my_messages, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* free all those messages we just constructed.
|
if (num_messages)
|
||||||
* we have to do it this way if the user ignores the
|
*num_messages = my_messages != NULL ? my_messages->len : 0;
|
||||||
* messages so that we will close any received fds.
|
|
||||||
*/
|
if (messages)
|
||||||
for (i = 0; i < index; i++)
|
{
|
||||||
g_object_unref (my_messages[i]);
|
if (my_messages == NULL)
|
||||||
g_free (my_messages);
|
{
|
||||||
|
*messages = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_ptr_array_add (my_messages, NULL);
|
||||||
|
*messages = (GSocketControlMessage **) g_ptr_array_free (my_messages, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_assert (my_messages == NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3305,6 +3309,11 @@ g_socket_receive_message (GSocket *socket,
|
|||||||
if (flags != NULL)
|
if (flags != NULL)
|
||||||
*flags = win_flags;
|
*flags = win_flags;
|
||||||
|
|
||||||
|
if (messages != NULL)
|
||||||
|
*messages = NULL;
|
||||||
|
if (n_messages != NULL)
|
||||||
|
*n_messages = 0;
|
||||||
|
|
||||||
return bytes_received;
|
return bytes_received;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user