0001-Fix-gai_strerror-thread-safety-on-Windows.patch
text/x-patch
Filename: 0001-Fix-gai_strerror-thread-safety-on-Windows.patch
Type: text/x-patch
Part: 0
Patch
Format: format-patch
Series: patch 0001
Subject: Fix gai_strerror() thread-safety on Windows.
| File | + | − |
|---|---|---|
| configure | 6 | 0 |
| configure.ac | 1 | 0 |
| src/include/port/win32/sys/socket.h | 8 | 0 |
| src/port/meson.build | 1 | 0 |
| src/port/win32gai_strerror.c | 34 | 0 |
| src/tools/msvc/Mkvcbuild.pm | 1 | 0 |
From 09aedd60882686f85517d8698e03bbcd342338d5 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Mon, 4 Dec 2023 14:52:57 +1300
Subject: [PATCH] Fix gai_strerror() thread-safety on Windows.
Commit 5579388d removed code that supplied a fallback implementation of
getaddrinfo(), which was dead code on modern systems. One tiny piece of
the removed code was still doing something useful on Windows, though:
that OS's own gai_strerror()/gai_strerrorA() function returns a pointer
to a static buffer that it overwrites each time, so it's not
thread-safe. In rare circumstances, a multi-threaded client program
could get an incorrect or corrupted error message.
Restore the replacement function, though now that it's only for Windows
we can put it into a win32-specific file and cut it down to the errors
that Windows documents.
Back-patch to 16.
---
configure | 6 +++++
configure.ac | 1 +
src/include/port/win32/sys/socket.h | 8 +++++++
src/port/meson.build | 1 +
src/port/win32gai_strerror.c | 34 +++++++++++++++++++++++++++++
src/tools/msvc/Mkvcbuild.pm | 1 +
6 files changed, 51 insertions(+)
create mode 100644 src/port/win32gai_strerror.c
diff --git a/configure b/configure
index 217704e9ca..1d4cd5caf3 100755
--- a/configure
+++ b/configure
@@ -16354,6 +16354,12 @@ esac
;;
esac
+ case " $LIBOBJS " in
+ *" win32gai_strerror.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS win32gai_strerror.$ac_objext"
+ ;;
+esac
+
case " $LIBOBJS " in
*" win32getrusage.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS win32getrusage.$ac_objext"
diff --git a/configure.ac b/configure.ac
index e49de9e4f0..a7a6b9a0ba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1878,6 +1878,7 @@ if test "$PORTNAME" = "win32"; then
AC_LIBOBJ(win32env)
AC_LIBOBJ(win32error)
AC_LIBOBJ(win32fdatasync)
+ AC_LIBOBJ(win32gai_strerror)
AC_LIBOBJ(win32getrusage)
AC_LIBOBJ(win32link)
AC_LIBOBJ(win32ntdll)
diff --git a/src/include/port/win32/sys/socket.h b/src/include/port/win32/sys/socket.h
index 0c32c0f7b2..f2b475df5e 100644
--- a/src/include/port/win32/sys/socket.h
+++ b/src/include/port/win32/sys/socket.h
@@ -23,4 +23,12 @@
#define ERROR PGERROR
#endif
+/*
+ * We don't use the Windows gai_strerror[A] function because it is not
+ * thread-safe. We define our own in src/port/win32gai_strerror.c.
+ */
+#undef gai_strerror
+
+extern const char *gai_strerror(int ecode);
+
#endif /* WIN32_SYS_SOCKET_H */
diff --git a/src/port/meson.build b/src/port/meson.build
index 576a48b48c..c559c732e7 100644
--- a/src/port/meson.build
+++ b/src/port/meson.build
@@ -35,6 +35,7 @@ if host_system == 'windows'
'win32error.c',
'win32fdatasync.c',
'win32fseek.c',
+ 'win32gai_strerror.c',
'win32getrusage.c',
'win32link.c',
'win32ntdll.c',
diff --git a/src/port/win32gai_strerror.c b/src/port/win32gai_strerror.c
new file mode 100644
index 0000000000..962e1659c1
--- /dev/null
+++ b/src/port/win32gai_strerror.c
@@ -0,0 +1,34 @@
+#include <sys/socket.h>
+
+/*
+ * Windows has gai_strerrorA(), but it is not thread-safe.
+ *
+ * These are the error values documented by:
+ *
+ * https://learn.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfo
+ */
+const char *
+gai_strerror(int errcode)
+{
+ switch (errcode)
+ {
+ case EAI_AGAIN:
+ return "A temporary failure in name resolution occurred";
+ case EAI_BADFLAGS:
+ return "An invalid value was provided for ai_flags";
+ case EAI_FAIL:
+ return "A nonrecoverable failure in name resolution occurred";
+ case EAI_FAMILY:
+ return "Address family not supported";
+ case EAI_MEMORY:
+ return "Not enough memory";
+ case EAI_NONAME:
+ return "Unknown host";
+ case EAI_SERVICE:
+ return "Class type not found";
+ case EAI_SOCKTYPE:
+ return "Socket type not supported";
+ default:
+ return "Unknown server error";
+ }
+}
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index 46df01cc8d..c51296bdb6 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -113,6 +113,7 @@ sub mkvcbuild
win32env.c win32error.c
win32fdatasync.c
win32fseek.c
+ win32gai_strerror.c
win32getrusage.c
win32gettimeofday.c
win32link.c
--
2.39.2