]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Ensure that BIO_eof only returns 1, 0 or a negative value
authorNeil Horman <nhorman@openssl.org>
Thu, 12 Mar 2026 14:17:04 +0000 (10:17 -0400)
committerNeil Horman <nhorman@openssl.org>
Sun, 15 Mar 2026 19:22:38 +0000 (15:22 -0400)
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)

crypto/bio/bio_lib.c
crypto/bio/bss_file.c

index 77caf7ac7779ae29ca8e35c7bd8139af4a6598ac..b7d4bc549e88363499611499529b2904347916bb 100644 (file)
@@ -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))
index 1cc4bc12065fb198e4ecdbee20be0ee0457d92ff..75f163148e91daff72740ea4d7ad8077d130fe1c 100644 (file)
@@ -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: