diff --git a/flang-rt/lib/runtime/namelist.cpp b/flang-rt/lib/runtime/namelist.cpp index e9c0b8ffa2da2..f30e615e8f0fa 100644 --- a/flang-rt/lib/runtime/namelist.cpp +++ b/flang-rt/lib/runtime/namelist.cpp @@ -170,7 +170,9 @@ static RT_API_ATTRS bool HandleSubscripts(IoStatementState &io, std::size_t byteCount{0}; common::optional ch{io.GetNextNonBlank(byteCount)}; char32_t comma{GetComma(io)}; - for (; ch && *ch != ')'; ++j) { + + // Read subscripts, but don't exceed rank to prevent buffer overrun. + for (int Rank = source.rank(); ch && *ch != ')' && j <= Rank; ++j) { SubscriptValue dimLower{0}, dimUpper{0}, dimStride{0}; if (j < maxRank && j < source.rank()) { const Dimension &dim{source.GetDimension(j)}; diff --git a/flang-rt/test/Runtime/bad_subscript_overrun01.f90 b/flang-rt/test/Runtime/bad_subscript_overrun01.f90 new file mode 100644 index 0000000000000..70cc84b168bab --- /dev/null +++ b/flang-rt/test/Runtime/bad_subscript_overrun01.f90 @@ -0,0 +1,50 @@ +! Test a buffer overrun when an illegal vector-valued subscript is used in +! namelist input. +! The error should be reported through the READ's IOSTAT value. +! RUN: %flang -L"%libdir" %s -o %t +! RUN: env LD_LIBRARY_PATH="$LD_LIBRARY_PATH:%libdir" %t | FileCheck %s +! CHECK-NOT: FAIL + +PROGRAM bad_subscript_overrun01 + IMPLICIT NONE + + INTEGER,DIMENSION(5) :: U, EXPECTU + INTEGER,DIMENSION(5) :: V, EXPECTV + CHARACTER(LEN=20) :: NAMELIST_RECORD + INTEGER :: IOS, ILOOP + + NAMELIST /SCORES/ U + NAMELIST /CHTEST/ NAMELIST_RECORD + + U = 8 + EXPECTU = U + V = 9 + EXPECTV = V + IOS = 0 + + NAMELIST_RECORD = " &SCORES U(V) = -1 /" + OPEN(UNIT=10, ACCESS='SEQUENTIAL', ACTION='READWRITE') + WRITE(10,'(A)') NAMELIST_RECORD + REWIND 10 + + ! This should fail because of the bad index. + READ(10, NML = SCORES, IOSTAT=IOS) + CLOSE(UNIT=10, STATUS='KEEP') + + ! Make sure the READ status was a failure. + IF(IOS.NE.0) THEN + PRINT *, "Test 1 - PASS" + ELSE + print *, "Test 1 - FAIL" + ENDIF + + ! Make sure the values of the array haven't changed. + DO ILOOP = 1,5 + IF(U(ILOOP).EQ.EXPECTU(ILOOP)) THEN + PRINT *, "Test 2 - PASS" + ELSE + PRINT *, "Test 2 - FAIL" + ENDIF + ENDDO + +END PROGRAM bad_subscript_overrun01