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: