re PR libfortran/81937 (stack-buffer-overflow on memcpy in libgfortran/io/unix.c...
authorJerry DeLisle <jvdelisle@gcc.gnu.org>
Sat, 16 Dec 2017 19:50:42 +0000 (19:50 +0000)
committerJerry DeLisle <jvdelisle@gcc.gnu.org>
Sat, 16 Dec 2017 19:50:42 +0000 (19:50 +0000)
2017-12-16  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

        PR libgfortran/81937
        * io/list_read.c (next_char_internal): Don't attempt to read
        from the internal unit stream if no bytes are left. Decrement
        bytes_left in the right place.

From-SVN: r255750

libgfortran/ChangeLog
libgfortran/io/list_read.c

index ee2f7a6fd2b0b7294281e6b1eca8a13623a63cc9..aa2a0f7f673d9b46cbb90b459f490a98ededc820 100644 (file)
@@ -1,3 +1,10 @@
+2017-12-16  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
+
+       PR libgfortran/81937
+       * io/list_read.c (next_char_internal): Don't attempt to read
+       from the internal unit stream if no bytes are left. Decrement
+       bytes_left in the right place.
+
 2017-12-12  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
        PR libgfortran/78549
index 379050cecad650f216d9714e9e278bb6a1e91dbe..037f2daa647e11292ebf538a3c4899f59d7e5c9b 100644 (file)
@@ -266,15 +266,19 @@ next_char_internal (st_parameter_dt *dtp)
     }
 
   /* Get the next character and handle end-of-record conditions.  */
-
-  if (is_char4_unit(dtp)) /* Check for kind=4 internal unit.  */
-   length = sread (dtp->u.p.current_unit->s, &c, 1);
+  if (likely (dtp->u.p.current_unit->bytes_left > 0))
+    {
+      if (unlikely (is_char4_unit(dtp))) /* Check for kind=4 internal unit.  */
+       length = sread (dtp->u.p.current_unit->s, &c, 1);
+      else
+       {
+        char cc;
+        length = sread (dtp->u.p.current_unit->s, &cc, 1);
+        c = cc;
+       }
+    }
   else
-   {
-     char cc;
-     length = sread (dtp->u.p.current_unit->s, &cc, 1);
-     c = cc;
-   }
+    length = 0;
 
   if (unlikely (length < 0))
     {
@@ -290,7 +294,6 @@ next_char_internal (st_parameter_dt *dtp)
          generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
          return '\0';
        }
-      dtp->u.p.current_unit->bytes_left--;
     }
   else
     {
@@ -302,6 +305,7 @@ next_char_internal (st_parameter_dt *dtp)
          dtp->u.p.at_eof = 1;
        }
     }
+  dtp->u.p.current_unit->bytes_left--;
 
 done:
   dtp->u.p.at_eol = (c == '\n' || c == EOF);