mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-02 09:16:17 +01:00
Clamp number of vectors to IOV_MAX / UIO_MAXIOV for GOutputStream writev() calls in the implementations
More vectors will give an error and we can simply clamp here and consider it like a short write instead. In case of GSocketOutputStream this is done here instead of inside GSocket before calling sendmsg() because we we can't generically handle short writes when sending messages on a socket, e.g. for datagram sockets this causes only part of the datagram to be sent and an error would be more useful in this case than sending corrupted data. Also reduce the fallback limit to 16 in gsocket.c as that's the minimum value required by POSIX and add a static assertion that the limit is never bigger than G_MAXINT as that's the type recvmmsg/sendmmsg take.
This commit is contained in:
parent
57a1d79361
commit
20a2c379c4
@ -35,6 +35,23 @@ gboolean g_output_stream_async_close_is_via_threads (GOutputStream *stream);
|
||||
void g_socket_connection_set_cached_remote_address (GSocketConnection *connection,
|
||||
GSocketAddress *address);
|
||||
|
||||
/* POSIX defines IOV_MAX/UIO_MAXIOV as the maximum number of iovecs that can
|
||||
* be sent in one go. We define our own version of it here as there are two
|
||||
* possible names, and also define a fall-back value if none of the constants
|
||||
* are defined */
|
||||
#if defined(IOV_MAX)
|
||||
#define G_IOV_MAX IOV_MAX
|
||||
#elif defined(UIO_MAXIOV)
|
||||
#define G_IOV_MAX UIO_MAXIOV
|
||||
#else
|
||||
/* 16 is the minimum value required by POSIX */
|
||||
#define G_IOV_MAX 16
|
||||
#endif
|
||||
|
||||
/* The various functions taking iovecs as parameter use a plain int
|
||||
* for the number of vectors. Limit it to G_MAXINT for this reason.
|
||||
*/
|
||||
G_STATIC_ASSERT (G_IOV_MAX <= G_MAXINT);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#endif
|
||||
|
||||
#include "glib-private.h"
|
||||
#include "gioprivate.h"
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#include <io.h>
|
||||
@ -243,11 +244,11 @@ g_local_file_output_stream_writev (GOutputStream *stream,
|
||||
if (bytes_written)
|
||||
*bytes_written = 0;
|
||||
|
||||
/* Clamp to G_MAXINT as writev() takes an integer for the number of vectors.
|
||||
* We handle this like a short write in this case
|
||||
/* Clamp the number of vectors if more given than we can write in one go.
|
||||
* The caller has to handle short writes anyway.
|
||||
*/
|
||||
if (n_vectors > G_MAXINT)
|
||||
n_vectors = G_MAXINT;
|
||||
if (n_vectors > G_IOV_MAX)
|
||||
n_vectors = G_IOV_MAX;
|
||||
|
||||
file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
|
||||
|
||||
|
@ -74,6 +74,7 @@
|
||||
#include "gcredentials.h"
|
||||
#include "gcredentialsprivate.h"
|
||||
#include "glibintl.h"
|
||||
#include "gioprivate.h"
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
/* For Windows XP runtime compatibility, but use the system's if_nametoindex() if available */
|
||||
@ -4960,14 +4961,11 @@ g_socket_send_messages_with_timeout (GSocket *socket,
|
||||
struct mmsghdr *msgvec;
|
||||
gint i, num_sent;
|
||||
|
||||
#ifdef UIO_MAXIOV
|
||||
#define MAX_NUM_MESSAGES UIO_MAXIOV
|
||||
#else
|
||||
#define MAX_NUM_MESSAGES 1024
|
||||
#endif
|
||||
|
||||
if (num_messages > MAX_NUM_MESSAGES)
|
||||
num_messages = MAX_NUM_MESSAGES;
|
||||
/* Clamp the number of vectors if more given than we can write in one go.
|
||||
* The caller has to handle short writes anyway.
|
||||
*/
|
||||
if (num_messages > G_IOV_MAX)
|
||||
num_messages = G_IOV_MAX;
|
||||
|
||||
msgvec = g_newa (struct mmsghdr, num_messages);
|
||||
|
||||
@ -5482,14 +5480,11 @@ g_socket_receive_messages_with_timeout (GSocket *socket,
|
||||
struct mmsghdr *msgvec;
|
||||
guint i, num_received;
|
||||
|
||||
#ifdef UIO_MAXIOV
|
||||
#define MAX_NUM_MESSAGES UIO_MAXIOV
|
||||
#else
|
||||
#define MAX_NUM_MESSAGES 1024
|
||||
#endif
|
||||
|
||||
if (num_messages > MAX_NUM_MESSAGES)
|
||||
num_messages = MAX_NUM_MESSAGES;
|
||||
/* Clamp the number of vectors if more given than we can write in one go.
|
||||
* The caller has to handle short writes anyway.
|
||||
*/
|
||||
if (num_messages > G_IOV_MAX)
|
||||
num_messages = G_IOV_MAX;
|
||||
|
||||
msgvec = g_newa (struct mmsghdr, num_messages);
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "gioerror.h"
|
||||
#include "glibintl.h"
|
||||
#include "gfiledescriptorbased.h"
|
||||
#include "gioprivate.h"
|
||||
|
||||
struct _GSocketOutputStreamPrivate
|
||||
{
|
||||
@ -146,8 +147,8 @@ g_socket_output_stream_writev (GOutputStream *stream,
|
||||
/* Clamp the number of vectors if more given than we can write in one go.
|
||||
* The caller has to handle short writes anyway.
|
||||
*/
|
||||
if (n_vectors > G_MAXINT)
|
||||
n_vectors = G_MAXINT;
|
||||
if (n_vectors > G_IOV_MAX)
|
||||
n_vectors = G_IOV_MAX;
|
||||
|
||||
res = g_socket_send_message_with_timeout (output_stream->priv->socket, NULL,
|
||||
vectors, n_vectors,
|
||||
@ -194,8 +195,8 @@ g_socket_output_stream_pollable_writev_nonblocking (GPollableOutputStream *poll
|
||||
/* Clamp the number of vectors if more given than we can write in one go.
|
||||
* The caller has to handle short writes anyway.
|
||||
*/
|
||||
if (n_vectors > G_MAXINT)
|
||||
n_vectors = G_MAXINT;
|
||||
if (n_vectors > G_IOV_MAX)
|
||||
n_vectors = G_IOV_MAX;
|
||||
|
||||
return g_socket_send_message_with_timeout (output_stream->priv->socket,
|
||||
NULL, vectors, n_vectors,
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "gasynchelper.h"
|
||||
#include "gfiledescriptorbased.h"
|
||||
#include "glibintl.h"
|
||||
#include "gioprivate.h"
|
||||
|
||||
|
||||
/**
|
||||
@ -425,11 +426,11 @@ g_unix_output_stream_writev (GOutputStream *stream,
|
||||
if (bytes_written)
|
||||
*bytes_written = 0;
|
||||
|
||||
/* Clamp to G_MAXINT as writev() takes an integer for the number of vectors.
|
||||
* We handle this like a short write in this case
|
||||
/* Clamp the number of vectors if more given than we can write in one go.
|
||||
* The caller has to handle short writes anyway.
|
||||
*/
|
||||
if (n_vectors > G_MAXINT)
|
||||
n_vectors = G_MAXINT;
|
||||
if (n_vectors > G_IOV_MAX)
|
||||
n_vectors = G_IOV_MAX;
|
||||
|
||||
unix_stream = G_UNIX_OUTPUT_STREAM (stream);
|
||||
|
||||
@ -635,11 +636,11 @@ g_unix_output_stream_pollable_writev_nonblocking (GPollableOutputStream *stream
|
||||
return G_POLLABLE_RETURN_WOULD_BLOCK;
|
||||
}
|
||||
|
||||
/* Clamp to G_MAXINT as writev() takes an integer for the number of vectors.
|
||||
* We handle this like a short write in this case
|
||||
/* Clamp the number of vectors if more given than we can write in one go.
|
||||
* The caller has to handle short writes anyway.
|
||||
*/
|
||||
if (n_vectors > G_MAXINT)
|
||||
n_vectors = G_MAXINT;
|
||||
if (n_vectors > G_IOV_MAX)
|
||||
n_vectors = G_IOV_MAX;
|
||||
|
||||
if (G_OUTPUT_VECTOR_IS_IOVEC)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user