Commit 43b03f25b9 for openssl.org
commit 43b03f25b9296df597fa1d29be1fb28d9efceb28
Author: Neil Horman <nhorman@openssl.org>
Date: Thu Mar 12 10:17:04 2026 -0400
Ensure that BIO_eof only returns 1, 0 or a negative value
Recently we uncovered the fact that some platforms (nonstop) return a
non-one positive value from feof to indicate end of file. This is in
compliance with posix standards, but we had some code that assumed 1
would always be the returned value for an EOF condition, causing various
failures.
Fix it by converting BIO_eof to only return 0 or 1 to reflect the EOF
state (or in the windows case -EINVAL if an invalid stream was passed
Fixes #30348
Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
MergeDate: Sun Mar 15 19:22:41 2026
(Merged from https://github.com/openssl/openssl/pull/30395)
diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c
index 77caf7ac77..b7d4bc549e 100644
--- a/crypto/bio/bio_lib.c
+++ b/crypto/bio/bio_lib.c
@@ -298,7 +298,7 @@ static int bio_read_intern(BIO *b, void *data, size_t dlen, size_t *readbytes)
* If method->bread() returned 0 when dlen>0, it can be either EOF or
* an error, and we should distinguish them
*/
- if (ret == 0 && dlen > 0 && BIO_eof(b) != 1)
+ if (ret == 0 && dlen > 0 && BIO_eof(b) == 0)
ret = -1;
if (HAS_CALLBACK(b))
diff --git a/crypto/bio/bss_file.c b/crypto/bio/bss_file.c
index 1cc4bc1206..75f163148e 100644
--- a/crypto/bio/bss_file.c
+++ b/crypto/bio/bss_file.c
@@ -193,10 +193,26 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr)
ret = (long)fseek(fp, num, 0);
break;
case BIO_CTRL_EOF:
+ /*
+ * NOTE feof returns 0 if we're not in an eof condition
+ * and a non-zero value if we are (i.e. any non-zero value
+ * so we map the 0:non-0 return value here to 0:1 with a
+ * double negation
+ */
if (b->flags & BIO_FLAGS_UPLINK_INTERNAL)
- ret = (long)UP_feof(fp);
+ ret = !!(long)UP_feof(fp);
else
- ret = (long)feof(fp);
+ ret = !!(long)feof(fp);
+#if defined(OPENSSL_SYS_WINDOWS)
+ /*
+ * Windows gives us an extra issue to contend with.
+ * In windows feof may return 0 if it is passed an invalid
+ * stream. In this event, feof sets errno to EINVAL.
+ * Check for that here, and set ret to -EINVAL if its the case.
+ */
+ if (ret == 0 && errno == EINVAL)
+ ret = -EINVAL;
+#endif
break;
case BIO_C_FILE_TELL:
case BIO_CTRL_INFO: