diff libinterp/corefcn/oct-stream.cc @ 33124:9c08824262af stable

Fix duplicate final value in scanf function (bug #65390, bug #63467). * oct-stream.cc (octave_scan): Don't check whether input stream "is" has hit EOF after skipping whitespace. Instead, call read_value() and let error propagate up through "is" state to this function. Check state of stream and either pass on a correctly-read value, or clear EOF bit and propagate up failure status in stream status bits. * io.tst: Add regression indicator to solved bug #63383. Add BIST tests for bug #63467 and bug #65390
author John W. Eaton <jwe@octave.org>
date Sat, 02 Mar 2024 13:54:06 -0800
parents 2e484f9f1f18
children fc467370dacb
line wrap: on
line diff
--- a/libinterp/corefcn/oct-stream.cc	Thu Feb 29 08:18:25 2024 -0500
+++ b/libinterp/corefcn/oct-stream.cc	Sat Mar 02 13:54:06 2024 -0800
@@ -4400,8 +4400,6 @@
 octave_scan<>
 (std::istream& is, const scanf_format_elt& fmt, double *valptr)
 {
-  double& ref = *valptr;
-
   switch (fmt.type)
     {
     case 'e':
@@ -4411,19 +4409,24 @@
     case 'G':
       {
         is >> std::ws;  // skip through whitespace and advance stream pointer
-        if (is.good ())
+
+        std::streampos pos = is.tellg ();
+
+        double value = read_value<double> (is);
+
+        std::ios::iostate status = is.rdstate ();
+        if (! (status & std::ios::failbit))
           {
-            std::streampos pos = is.tellg ();
-
-            ref = read_value<double> (is);
-
-            std::ios::iostate status = is.rdstate ();
-            if (status & std::ios::failbit)
-              {
-                is.clear ();
-                is.seekg (pos);
-                is.setstate (status & ~std::ios_base::eofbit);
-              }
+            // Copy the converted value if the stream is in a good state
+            *valptr = value;
+          }
+        else
+          {
+            // True error.
+            // Reset stream to original position, clear eof bit, pass status on.
+            is.clear ();
+            is.seekg (pos);
+            is.setstate (status & ~std::ios_base::eofbit);
           }
       }
       break;