https://gcc.gnu.org/g:680af0e1e90d4b80260d173636dfe15654fd470d

commit r15-516-g680af0e1e90d4b80260d173636dfe15654fd470d
Author: Gaius Mulley <gaiusm...@gmail.com>
Date:   Wed May 15 16:58:21 2024 +0100

    PR modula2/115057 TextIO.ReadRestLine raises an exception when buffer is 
exceeded
    
    TextIO.ReadRestLine will raise an "attempting to read beyond end of file"
    exception if the buffer is exceeded.  This bug is caused by the
    TextIO.ReadRestLine calling IOChan.Skip without a preceeding IOChan.Look.
    The Look procedure will update the status result whereas
    Skip always sets read result to allRight.
    
    gcc/m2/ChangeLog:
    
            PR modula2/115057
            * gm2-libs-iso/TextIO.mod (ReadRestLine): Use ReadChar to
            skip unwanted characters as this calls IOChan.Look and updates
            the cid result status.  A Skip without a Look does not update
            the status.  Skip always sets read result to allRight.
            * gm2-libs-iso/TextUtil.def (SkipSpaces): Improve comments.
            (CharAvailable): Improve comments.
            * gm2-libs-iso/TextUtil.mod (SkipSpaces): Improve comments.
            (CharAvailable): Improve comments.
    
    gcc/testsuite/ChangeLog:
    
            PR modula2/115057
            * gm2/isolib/run/pass/testrestline.mod: New test.
            * gm2/isolib/run/pass/testrestline2.mod: New test.
            * gm2/isolib/run/pass/testrestline3.mod: New test.
    
    Signed-off-by: Gaius Mulley <gaiusm...@gmail.com>

Diff:
---
 gcc/m2/gm2-libs-iso/TextIO.mod                      | 13 ++++++++-----
 gcc/m2/gm2-libs-iso/TextUtil.def                    |  6 +++++-
 gcc/m2/gm2-libs-iso/TextUtil.mod                    |  6 +++++-
 gcc/testsuite/gm2/isolib/run/pass/testrestline.mod  | 20 ++++++++++++++++++++
 gcc/testsuite/gm2/isolib/run/pass/testrestline2.mod | 17 +++++++++++++++++
 gcc/testsuite/gm2/isolib/run/pass/testrestline3.mod | 16 ++++++++++++++++
 6 files changed, 71 insertions(+), 7 deletions(-)

diff --git a/gcc/m2/gm2-libs-iso/TextIO.mod b/gcc/m2/gm2-libs-iso/TextIO.mod
index 78d67187b799..5204467b1921 100644
--- a/gcc/m2/gm2-libs-iso/TextIO.mod
+++ b/gcc/m2/gm2-libs-iso/TextIO.mod
@@ -114,13 +114,19 @@ PROCEDURE ReadRestLine (cid: IOChan.ChanId; VAR s: ARRAY 
OF CHAR);
   *)
 VAR
    i, h    : CARDINAL ;
+   ignore  : CHAR ;
    finished: BOOLEAN ;
 BEGIN
    h := HIGH(s) ;
    i := 0 ;
    finished := FALSE ;
-   WHILE (i<=h) AND CharAvailable (cid) AND (NOT finished) DO
-      ReadChar (cid, s[i]) ;
+   WHILE CharAvailable (cid) AND (NOT finished) DO
+      IF i <= h
+      THEN
+         ReadChar (cid, s[i])
+      ELSE
+         ReadChar (cid, ignore)
+      END ;
       IF EofOrEoln (cid)
       THEN
          finished := TRUE
@@ -128,9 +134,6 @@ BEGIN
          INC (i)
       END
    END ;
-   WHILE CharAvailable (cid) DO
-      IOChan.Skip (cid)
-   END ;
    SetNul (cid, i, s, TRUE)
 END ReadRestLine ;
 
diff --git a/gcc/m2/gm2-libs-iso/TextUtil.def b/gcc/m2/gm2-libs-iso/TextUtil.def
index ead045617233..7e6b3ed07dce 100644
--- a/gcc/m2/gm2-libs-iso/TextUtil.def
+++ b/gcc/m2/gm2-libs-iso/TextUtil.def
@@ -45,11 +45,15 @@ IMPORT IOChan ;
 PROCEDURE SkipSpaces (cid: IOChan.ChanId) ;
 
 
-(* The following procedures do not read past line marks.  *)
+(* CharAvailable returns TRUE if IOChan.ReadResult is notKnown or
+   allRight.  *)
 
 PROCEDURE CharAvailable (cid: IOChan.ChanId) : BOOLEAN ;
 
 
+(* EofOrEoln returns TRUE if IOChan.ReadResult is endOfLine or
+   endOfInput.  *)
+
 PROCEDURE EofOrEoln (cid: IOChan.ChanId) : BOOLEAN ;
 
 
diff --git a/gcc/m2/gm2-libs-iso/TextUtil.mod b/gcc/m2/gm2-libs-iso/TextUtil.mod
index 44dbd1c69f8b..ad5786ca2fb2 100644
--- a/gcc/m2/gm2-libs-iso/TextUtil.mod
+++ b/gcc/m2/gm2-libs-iso/TextUtil.mod
@@ -23,7 +23,8 @@ BEGIN
 END SkipSpaces ;
 
 
-(* The following procedures do not read past line marks.  *)
+(* CharAvailable returns TRUE if IOChan.ReadResult is notKnown or
+   allRight.  *)
 
 PROCEDURE CharAvailable (cid: IOChan.ChanId) : BOOLEAN ;
 BEGIN
@@ -32,6 +33,9 @@ BEGIN
 END CharAvailable ;
 
 
+(* EofOrEoln returns TRUE if IOChan.ReadResult is endOfLine or
+   endOfInput.  *)
+
 PROCEDURE EofOrEoln (cid: IOChan.ChanId) : BOOLEAN ;
 BEGIN
    RETURN( (IOChan.ReadResult (cid) = IOConsts.endOfLine) OR
diff --git a/gcc/testsuite/gm2/isolib/run/pass/testrestline.mod 
b/gcc/testsuite/gm2/isolib/run/pass/testrestline.mod
new file mode 100644
index 000000000000..7702e88bdd95
--- /dev/null
+++ b/gcc/testsuite/gm2/isolib/run/pass/testrestline.mod
@@ -0,0 +1,20 @@
+MODULE testrestline ;
+
+IMPORT SeqFile, TextIO ;
+
+VAR
+   chan    : SeqFile.ChanId ;
+   line    : ARRAY [0..5] OF CHAR ;
+   results : SeqFile.OpenResults ;
+BEGIN
+   SeqFile.OpenWrite (chan, "test.input", SeqFile.write, results) ;
+   TextIO.WriteString (chan, "a line of text exceeding 6 chars") ;
+   TextIO.WriteLn (chan) ;
+   TextIO.WriteString (chan, "a second lineline of text exceeding 6 chars") ;
+   TextIO.WriteLn (chan) ;
+   SeqFile.Close (chan) ;
+
+   (* Now see if we can read the first line.  *)
+   SeqFile.OpenRead (chan, "test.input", SeqFile.read, results) ;
+   TextIO.ReadRestLine (chan, line)
+END testrestline.
\ No newline at end of file
diff --git a/gcc/testsuite/gm2/isolib/run/pass/testrestline2.mod 
b/gcc/testsuite/gm2/isolib/run/pass/testrestline2.mod
new file mode 100644
index 000000000000..00e5c8091e18
--- /dev/null
+++ b/gcc/testsuite/gm2/isolib/run/pass/testrestline2.mod
@@ -0,0 +1,17 @@
+MODULE testrestline2 ;
+
+IMPORT SeqFile, TextIO ;
+
+VAR
+   chan    : SeqFile.ChanId ;
+   line    : ARRAY [0..5] OF CHAR ;
+   results : SeqFile.OpenResults ;
+BEGIN
+   SeqFile.OpenWrite (chan, "test.input", SeqFile.write, results) ;
+   TextIO.WriteString (chan, "a line of text exceeding 6 chars") ;
+   TextIO.WriteLn (chan) ;
+
+   (* Now see if we can read the first line.  *)
+   SeqFile.OpenRead (chan, "test.input", SeqFile.read, results) ;
+   TextIO.ReadRestLine (chan, line)
+END testrestline2.
\ No newline at end of file
diff --git a/gcc/testsuite/gm2/isolib/run/pass/testrestline3.mod 
b/gcc/testsuite/gm2/isolib/run/pass/testrestline3.mod
new file mode 100644
index 000000000000..04fbad42f2db
--- /dev/null
+++ b/gcc/testsuite/gm2/isolib/run/pass/testrestline3.mod
@@ -0,0 +1,16 @@
+MODULE testrestline3 ;
+
+IMPORT SeqFile, TextIO ;
+
+VAR
+   chan    : SeqFile.ChanId ;
+   line    : ARRAY [0..5] OF CHAR ;
+   results : SeqFile.OpenResults ;
+BEGIN
+   SeqFile.OpenWrite (chan, "test.input", SeqFile.write, results) ;
+   TextIO.WriteString (chan, "a line of text exceeding 6 chars") ;
+
+   (* Now see if we can read the first line.  *)
+   SeqFile.OpenRead (chan, "test.input", SeqFile.read, results) ;
+   TextIO.ReadRestLine (chan, line)
+END testrestline3.
\ No newline at end of file

Reply via email to