[vlc-devel] [PATCH 1/2] compat: Workaround sendmsg bug on some ArmV8 Android devices
Hugo Beauzée-Luyssen
hugo at beauzee.fr
Fri Mar 29 11:35:16 CET 2019
On some devices (at least up to Android 6) sendmsg will return its error
code on 32bits instead of 64.
Most likely some code is storing the ssize_t on a size_t, getting rid of
the sign bit and therefore of the sign extension afterward.
This causes us to use 0xFFFFFFFF as a very large number of bytes instead
of an error.
This patch works around the issue and assumes that 0xFFFFFFFF with a non
0 errno is an error and forces it to be returned on 64bits.
---
compat/sendmsg.c | 24 ++++++++++++++++++++++++
configure.ac | 3 +++
include/vlc_network.h | 6 ++++++
3 files changed, 33 insertions(+)
diff --git a/compat/sendmsg.c b/compat/sendmsg.c
index 0b08ce0942..2ef542eb7b 100644
--- a/compat/sendmsg.c
+++ b/compat/sendmsg.c
@@ -133,6 +133,30 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags)
free(data);
return res;
}
+#elif defined(__ANDROID__) && defined(__aarch64__)
+
+#undef sendmsg
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+/**
+ * Since we bumped the NDK version from 14 to 18, some devices (at least up to
+ * Android 6) are returning errors on 4 bytes, even though ssize_t is actually
+ * 8 bytes. This causes `value < 0` checks to yield false, and consider the value
+ * as a non error.
+ * As the patch lies in either the NDK or the Android kernel, or the device libc
+ * we can only work around it. If errno is not 0 & we receive -1, on 32bits or
+ * 64bits, we assume an error was returned.
+ */
+ssize_t vlc_sendmsg(int fd, const struct msghdr *msg, int flags)
+{
+ errno = 0;
+ ssize_t ret = sendmsg(fd, msg, flags);
+ if ((ret < 0 || ret == 0xFFFFFFFF) && errno != 0)
+ return -1;
+ return ret;
+}
#else
#error sendmsg not implemented on your platform!
diff --git a/configure.ac b/configure.ac
index 1bd42678b8..0bb12f4305 100644
--- a/configure.ac
+++ b/configure.ac
@@ -402,6 +402,9 @@ AS_IF([test "$SYS" = linux],[
],[
HAVE_ANDROID="1"
AC_MSG_RESULT([yes])
+ AS_IF([test "${host_cpu}" = "aarch64"], [
+ AC_LIBOBJ([sendmsg])
+ ])
],[
AC_MSG_RESULT([no])
])
diff --git a/include/vlc_network.h b/include/vlc_network.h
index 7cc384587a..d75905ea3f 100644
--- a/include/vlc_network.h
+++ b/include/vlc_network.h
@@ -280,6 +280,12 @@ static inline int net_GetPeerAddress( int fd, char *address, int *port )
VLC_API char *vlc_getProxyUrl(const char *);
+#if defined(__ANDROID__) && defined(__aarch64__)
+struct msghdr;
+ssize_t vlc_sendmsg(int fd, const struct msghdr *msg, int flags);
+#define sendmsg(a, b, c) vlc_sendmsg(a,b,c)
+#endif
+
# ifdef __cplusplus
}
# endif
--
2.20.1
More information about the vlc-devel
mailing list