https://gcc.gnu.org/g:a276bd12e11faa2c6765b1641ba6416a46396b1e
commit r14-12599-ga276bd12e11faa2c6765b1641ba6416a46396b1e Author: Jonathan Wakely <[email protected]> Date: Fri Dec 6 17:41:01 2024 +0000 libstdc++: Add workaround for read(2) EINVAL on macOS and FreeBSD [PR102259] On macOS and FreeBSD the read(2) system call can return EINVAL for large sizes, so limit the maximum that we try to read. The calling code in basic_filebuf::xsgetn will loop until it gets the size it wants, so we don't need to loop in basic_file::xsgetn, just limit the maximum size. libstdc++-v3/ChangeLog: PR libstdc++/102259 * config/io/basic_file_stdio.cc (basic_file::xsgetn): Limit n to _GLIBCXX_MAX_READ_SIZE if that macro is defined. * config/os/bsd/darwin/os_defines.h (_GLIBCXX_MAX_READ_SIZE): Define to INT_MAX-1. * config/os/bsd/freebsd/os_defines.h (_GLIBCXX_MAX_READ_SIZE): Likewise. (cherry picked from commit 4065bf7c2c61dd6eb19fdccbcda99000d8e44b7a) Diff: --- 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 9b529490f089..95e6905b3adf 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_MAX_READ_SIZE + if (__builtin_expect(__n > _GLIBCXX_MAX_READ_SIZE, 0)) + __n = _GLIBCXX_MAX_READ_SIZE; +#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 6bc7930bdba0..a9cbdbb557bf 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_MAX_READ_SIZE (__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 6c931821329e..261a80c4e4ac 100644 --- a/libstdc++-v3/config/os/bsd/freebsd/os_defines.h +++ b/libstdc++-v3/config/os/bsd/freebsd/os_defines.h @@ -40,4 +40,7 @@ #define _GLIBCXX_USE_C99_FLOAT_TRANSCENDENTALS_CHECK 1 #define _GLIBCXX_USE_C99_FLOAT_TRANSCENDENTALS_DYNAMIC defined _XOPEN_SOURCE +// read(2) can return EINVAL for n >= INT_MAX. +#define _GLIBCXX_MAX_READ_SIZE (__INT_MAX__ - 1) + #endif
