[flang-commits] [flang] 461b6fe - [flang] Expose error recovery cases in external I/O
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Mon Mar 21 12:46:25 PDT 2022
Author: Peter Klausler
Date: 2022-03-21T12:46:16-07:00
New Revision: 461b6fe470f72637e226ee7ff2722c1d76ebc549
URL: https://github.com/llvm/llvm-project/commit/461b6fe470f72637e226ee7ff2722c1d76ebc549
DIFF: https://github.com/llvm/llvm-project/commit/461b6fe470f72637e226ee7ff2722c1d76ebc549.diff
LOG: [flang] Expose error recovery cases in external I/O
Some I/O error situations are current handled with fatal
runtime asserts, but should be exposed for user program
error recovery.
Differential Revision: https://reviews.llvm.org/D122049
Added:
Modified:
flang/include/flang/Runtime/iostat.h
flang/runtime/iostat.cpp
flang/runtime/unit.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Runtime/iostat.h b/flang/include/flang/Runtime/iostat.h
index 06d6fe7ae3dd4..0c0b3f4b3f7f3 100644
--- a/flang/include/flang/Runtime/iostat.h
+++ b/flang/include/flang/Runtime/iostat.h
@@ -63,6 +63,9 @@ enum Iostat {
IostatFormattedChildOnUnformattedParent,
IostatChildInputFromOutputParent,
IostatChildOutputToInputParent,
+ IostatShortRead,
+ IostatMissingTerminator,
+ IostatBadUnformattedRecord,
};
const char *IostatErrorString(int);
diff --git a/flang/runtime/iostat.cpp b/flang/runtime/iostat.cpp
index 994af4f2a4f78..f6305eaca6559 100644
--- a/flang/runtime/iostat.cpp
+++ b/flang/runtime/iostat.cpp
@@ -69,6 +69,12 @@ const char *IostatErrorString(int iostat) {
return "Child input from output parent unit";
case IostatChildOutputToInputParent:
return "Child output to input parent unit";
+ case IostatShortRead:
+ return "Read from external unit returned insufficient data";
+ case IostatMissingTerminator:
+ return "Sequential record missing its terminator";
+ case IostatBadUnformattedRecord:
+ return "Erroneous unformatted sequential file record structure";
default:
return nullptr;
}
diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index 87b11820609a3..23e5b6292621b 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -762,10 +762,16 @@ void ExternalFileUnit::BackspaceVariableUnformattedRecord(
// checked informatively in NextSequentialVariableUnformattedInputRecord().
std::size_t got{
ReadFrame(frameOffsetInFile_ - headerBytes, headerBytes, handler)};
- RUNTIME_CHECK(handler, got >= sizeof footer);
+ if (static_cast<std::int64_t>(got) < headerBytes) {
+ handler.SignalError(IostatShortRead);
+ return;
+ }
std::memcpy(&footer, Frame(), sizeof footer);
recordLength = footer;
- RUNTIME_CHECK(handler, frameOffsetInFile_ >= *recordLength + 2 * headerBytes);
+ if (frameOffsetInFile_ < *recordLength + 2 * headerBytes) {
+ handler.SignalError(IostatBadUnformattedRecord);
+ return;
+ }
frameOffsetInFile_ -= *recordLength + 2 * headerBytes;
if (frameOffsetInFile_ >= headerBytes) {
frameOffsetInFile_ -= headerBytes;
@@ -774,9 +780,15 @@ void ExternalFileUnit::BackspaceVariableUnformattedRecord(
auto need{static_cast<std::size_t>(
recordOffsetInFrame_ + sizeof header + *recordLength)};
got = ReadFrame(frameOffsetInFile_, need, handler);
- RUNTIME_CHECK(handler, got >= need);
+ if (got < need) {
+ handler.SignalError(IostatShortRead);
+ return;
+ }
std::memcpy(&header, Frame() + recordOffsetInFrame_, sizeof header);
- RUNTIME_CHECK(handler, header == *recordLength);
+ if (header != *recordLength) {
+ handler.SignalError(IostatBadUnformattedRecord);
+ return;
+ }
}
// There's no portable memrchr(), unfortunately, and strrchr() would
@@ -816,9 +828,15 @@ void ExternalFileUnit::BackspaceVariableFormattedRecord(
frameOffsetInFile_ -= std::min<std::int64_t>(frameOffsetInFile_, 1024);
auto need{static_cast<std::size_t>(prevNL + 1 - frameOffsetInFile_)};
auto got{ReadFrame(frameOffsetInFile_, need, handler)};
- RUNTIME_CHECK(handler, got >= need);
+ if (got < need) {
+ handler.SignalError(IostatShortRead);
+ return;
+ }
+ }
+ if (Frame()[recordOffsetInFrame_ + *recordLength] != '\n') {
+ handler.SignalError(IostatMissingTerminator);
+ return;
}
- RUNTIME_CHECK(handler, Frame()[recordOffsetInFrame_ + *recordLength] == '\n');
if (*recordLength > 0 &&
Frame()[recordOffsetInFrame_ + *recordLength - 1] == '\r') {
--*recordLength;
More information about the flang-commits
mailing list