On macOS and FreeBSD read(2) system call can return EINVAL for large
sizes, so limit the maximum that we try to read. The calling code in
filebuf::xsgetn will loop until it gets the size it wants, so we don't
need to loop here.
libstdc++-v3/ChangeLog:
PR libstdc++/102259
* config/io/basic_file_stdio.cc (basic_file::xsgetn): Limit n to
INT_MAX-1 when _GLIBCXX_READ_RETURNS_EINVAL_OVER_INT_MAX is
defined.
* config/os/bsd/darwin/os_defines.h
(_GLIBCXX_READ_RETURNS_EINVAL_OVER_INT_MAX):
Define.
* config/os/bsd/freebsd/os_defines.h
(_GLIBCXX_READ_RETURNS_EINVAL_OVER_INT_MAX):
Define.
---
Any suggestions for a better name for the new macro?
I haven't tested this, but I'll ask the bug submitter to do so. If they
don't do so, I'll ask Iain or try a FreeBSD VM next week some time.
libstdc++-v3/config/io/basic_file_stdio.cc | 6 ++++++
libstdc++-v3/config/os/bsd/darwin/os_defines.h | 3 +++
libstdc++-v3/config/os/bsd/freebsd/os_defines.h | 3 +++
3 files changed, 12 insertions(+)
diff --git a/libstdc++-v3/config/io/basic_file_stdio.cc
b/libstdc++-v3/config/io/basic_file_stdio.cc
index 9b529490f08..508e2d2a469 100644
--- a/libstdc++-v3/config/io/basic_file_stdio.cc
+++ b/libstdc++-v3/config/io/basic_file_stdio.cc
@@ -338,6 +338,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__ret == 0 && ferror(this->file()))
__ret = -1;
#else
+
+#ifdef _GLIBCXX_READ_RETURNS_EINVAL_OVER_INT_MAX
+ if (__builtin_expect(__n >= __INT_MAX__, 0))
+ __n = __INT_MAX__ - 1;
+#endif
+
do
__ret = read(this->fd(), __s, __n);
while (__ret == -1L && errno == EINTR);
diff --git a/libstdc++-v3/config/os/bsd/darwin/os_defines.h
b/libstdc++-v3/config/os/bsd/darwin/os_defines.h
index 6bc7930bdba..826c863e481 100644
--- a/libstdc++-v3/config/os/bsd/darwin/os_defines.h
+++ b/libstdc++-v3/config/os/bsd/darwin/os_defines.h
@@ -54,4 +54,7 @@
// No support for referencing weak symbols without a definition.
#define _GLIBCXX_USE_WEAK_REF 0
+// read(2) can return EINVAL for n > INT_MAX.
+#define _GLIBCXX_READ_RETURNS_EINVAL_OVER_INT_MAX 1
+
#endif
diff --git a/libstdc++-v3/config/os/bsd/freebsd/os_defines.h
b/libstdc++-v3/config/os/bsd/freebsd/os_defines.h
index 125dfdc1888..4889bb4ec00 100644
--- a/libstdc++-v3/config/os/bsd/freebsd/os_defines.h
+++ b/libstdc++-v3/config/os/bsd/freebsd/os_defines.h
@@ -50,4 +50,7 @@
#define _GLIBCXX_USE_C99_FLOAT_TRANSCENDENTALS_DYNAMIC 0
#endif
+// read(2) can return EINVAL for n > INT_MAX.
+#define _GLIBCXX_READ_RETURNS_EINVAL_OVER_INT_MAX 1
+
#endif
--
2.47.1