<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
<title></title>
<style type="text/css">code{white-space: pre;}</style>
</head>
<body>
<p>Hi Dennis,</p>
<p>As code within VLC should be able to assume that <code>recvmsg</code> and <code>sendmsg</code>are <em>POSIX</em>-compliant, I vote that some adjustments should be made to these implementations so that we do not run into issues with unexpected behavior in the future.</p>
<p>See the below resource for the specification in full:</p>
<ul>
<li>http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html</li>
</ul>
<p>On 2017-03-13 12:37, Dennis Hamester wrote:</p>
<blockquote style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;color:#500050">
<pre><code> From: Dennis Hamester <dennis.hamester@startmail.com>
compat/recvmsg.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++-
compat/sendmsg.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
configure.ac | 2 ++
3 files changed, 101 insertions(+), 2 deletions(-)
diff --git a/compat/recvmsg.c b/compat/recvmsg.c
index 941249fef7..40ec935fc6 100644
--- a/compat/recvmsg.c
+++ b/compat/recvmsg.c
@@ -1,7 +1,10 @@
/*****************************************************************************
* recvmsg.c: POSIX recvmsg() replacement
*****************************************************************************
- * Copyright © 2016 Rémi Denis-Courmont
+ * Copyright © 2016-2017 VLC authors and VideoLAN
+ *
+ * Authors: Rémi Denis-Courmont
+ * Dennis Hamester <dhamester@jusst.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
@@ -79,3 +82,49 @@ ssize_t recvmsg(int fd, struct msghdr *msg, int flags)
return -1;
}
#endif
+
+#ifdef __native_client__
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+
+ssize_t recvmsg(int fd, struct msghdr *msg, int flags)
+{
+ if (msg->msg_controllen != 0)
+ {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ if (msg->msg_iovlen > IOV_MAX)
+ {</code></pre>
</blockquote>
<p>This check should include <code>msg->msg_iovlen <= 0</code> together with <code>> IOV_MAX</code>, and <code>errno</code> should be set to <code>EMSGSIZE</code> according to POSIX.</p>
<blockquote style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;color:#500050">
<pre><code> + errno = EINVAL;
+ return -1;
+ }
+
+ size_t full_size = 0;
+ for (int i = 0; i < msg->msg_iovlen; ++i)
+ full_size += msg->msg_iov[i].iov_len;</code></pre>
</blockquote>
<p>According to <em>POSIX</em>, if the total sum of <code>msg->msg_iov[i].iov_len</code> would overflow a <code>ssize_t</code> the function shall return <code>-1</code> and set <code>errno</code> to <code>EINVAL</code>.</p>
<blockquote style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;color:#500050">
<pre><code> +
+ char *data = malloc(full_size);
+ if (!data)</code></pre>
</blockquote>
<p><code>errno = ENOMEM</code> on allocation failure, also note that if <code>full_size == 0</code> it is <em>implementation-defined</em> whether <code>malloc</code> will return <code>NULL</code> or not.</p>
<blockquote style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;color:#500050">
<pre><code> + return -1;
+
+ ssize_t res;
+ if (msg->msg_name)
+ res = recvfrom(fd, data, full_size, flags, msg->msg_name, &msg->msg_namelen);
+ else
+ res = recv(fd, data, full_size, flags);
+</code></pre>
</blockquote>
<p>If less than <code>full_size</code> bytes of data is read you will <code>memcpy</code> garbage in the loop that follows, which is undesirable.</p>
<blockquote style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;color:#500050">
<pre><code> + size_t tmp = 0;
+ for (int i = 0; i < msg->msg_iovlen; ++i) {
+ memcpy(msg->msg_iov[i].iov_base, data + tmp, msg->msg_iov[i].iov_len);
+ tmp += msg->msg_iov[i].iov_len;
+ }
+
+ msg->msg_flags = 0;
+ free(data);
+ return res;
+}
+#endif
diff --git a/compat/sendmsg.c b/compat/sendmsg.c
index 451ba298bf..5bbe8c413b 100644
--- a/compat/sendmsg.c
+++ b/compat/sendmsg.c
@@ -1,7 +1,10 @@
/*****************************************************************************
* sendmsg.c: POSIX sendmsg() replacement
*****************************************************************************
- * Copyright © 2016 Rémi Denis-Courmont
+ * Copyright © 2016-2017 VLC authors and VideoLAN
+ *
+ * Authors: Rémi Denis-Courmont
+ * Dennis Hamester <dhamester@jusst.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
@@ -69,3 +72,48 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags)
return -1;
}
#endif
+
+#ifdef __native_client__
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+
+ssize_t sendmsg(int fd, const struct msghdr *msg, int flags)
+{
+ if (msg->msg_controllen != 0)
+ {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ if (msg->msg_iovlen > IOV_MAX)
+ {
+ errno = EINVAL;
+ return -1;
+ }</code></pre>
</blockquote>
<p>See comments regarding <code>recvmsg</code>.</p>
<blockquote style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;color:#500050">
<pre><code> + size_t full_size = 0;
+ for (int i = 0; i < msg->msg_iovlen; ++i)
+ full_size += msg->msg_iov[i].iov_len;
+
+ char *data = malloc(full_size);
+ if (!data)
+ return -1;
+
+ size_t tmp = 0;
+ for (int i = 0; i < msg->msg_iovlen; ++i) {
+ memcpy(data + tmp, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
+ tmp += msg->msg_iov[i].iov_len;
+ }
+
+ ssize_t res;
+ if (msg->msg_name)
+ res = sendto(fd, data, full_size, flags, msg->msg_name, msg->msg_namelen);
+ else
+ res = send(fd, data, full_size, flags);
+
+ free(data);
+ return res;
+}
+#endif
diff --git a/configure.ac b/configure.ac
index c9713970fd..787421810e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -300,6 +300,8 @@ case "${host_os}" in
*nacl*)
SYS=nacl
AC_DEFINE([_XOPEN_SOURCE], [700], [POSIX and XPG 7th edition])
+ AC_LIBOBJ([recvmsg])
+ AC_LIBOBJ([sendmsg])
;;
*)
SYS="${host_os}"
--
2.12.0</code></pre>
</blockquote>
</body>
</html>