[flang-commits] [flang] c7fe5e8 - [flang][runtime] Handle endian-swapped record headers & footers on input

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Thu Aug 18 15:42:58 PDT 2022


Author: Peter Klausler
Date: 2022-08-18T15:36:32-07:00
New Revision: c7fe5e83dbb4eb164b370546303b111b3a62886d

URL: https://github.com/llvm/llvm-project/commit/c7fe5e83dbb4eb164b370546303b111b3a62886d
DIFF: https://github.com/llvm/llvm-project/commit/c7fe5e83dbb4eb164b370546303b111b3a62886d.diff

LOG: [flang][runtime] Handle endian-swapped record headers & footers on input

The runtime I/O library correctly handles endianness conversions on payload
data I/O and on the output of sequential record headers and footers, but
does not swap endianness when required when reading sequential record headers
and footers back in for READ and BACKSPACE statements.  Mea culpa.  Fix.

Fixes https://github.com/llvm/llvm-project/issues/57126

Differential Revision: https://reviews.llvm.org/D132168

Added: 
    

Modified: 
    flang/runtime/unit.cpp
    flang/runtime/unit.h

Removed: 
    


################################################################################
diff  --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index ff7b8938e833..be0791c19221 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -279,7 +279,7 @@ void ExternalFileUnit::FlushAll(IoErrorHandler &handler) {
   }
 }
 
-static void SwapEndianness(
+static inline void SwapEndianness(
     char *data, std::size_t bytes, std::size_t elementBytes) {
   if (elementBytes > 1) {
     auto half{elementBytes >> 1};
@@ -733,7 +733,7 @@ void ExternalFileUnit::BeginSequentialVariableUnformattedInputRecord(
               "record #%jd (file offset %jd): truncated record header";
     }
   } else {
-    std::memcpy(&header, Frame() + recordOffsetInFrame_, sizeof header);
+    header = ReadHeaderOrFooter(recordOffsetInFrame_);
     recordLength = sizeof header + header; // does not include footer
     need = recordOffsetInFrame_ + *recordLength + sizeof footer;
     got = ReadFrame(frameOffsetInFile_, need, handler);
@@ -742,8 +742,7 @@ void ExternalFileUnit::BeginSequentialVariableUnformattedInputRecord(
               "record #%jd (file offset %jd): hit EOF reading record with "
               "length %jd bytes";
     } else {
-      std::memcpy(&footer, Frame() + recordOffsetInFrame_ + *recordLength,
-          sizeof footer);
+      footer = ReadHeaderOrFooter(recordOffsetInFrame_ + *recordLength);
       if (footer != header) {
         error = "Unformatted variable-length sequential file input failed at "
                 "record #%jd (file offset %jd): record header has length %jd "
@@ -800,7 +799,7 @@ void ExternalFileUnit::BackspaceFixedRecord(IoErrorHandler &handler) {
 
 void ExternalFileUnit::BackspaceVariableUnformattedRecord(
     IoErrorHandler &handler) {
-  std::int32_t header{0}, footer{0};
+  std::int32_t header{0};
   auto headerBytes{static_cast<std::int64_t>(sizeof header)};
   frameOffsetInFile_ += recordOffsetInFrame_;
   recordOffsetInFrame_ = 0;
@@ -817,8 +816,7 @@ void ExternalFileUnit::BackspaceVariableUnformattedRecord(
     handler.SignalError(IostatShortRead);
     return;
   }
-  std::memcpy(&footer, Frame(), sizeof footer);
-  recordLength = footer;
+  recordLength = ReadHeaderOrFooter(0);
   if (frameOffsetInFile_ < *recordLength + 2 * headerBytes) {
     handler.SignalError(IostatBadUnformattedRecord);
     return;
@@ -835,7 +833,7 @@ void ExternalFileUnit::BackspaceVariableUnformattedRecord(
     handler.SignalError(IostatShortRead);
     return;
   }
-  std::memcpy(&header, Frame() + recordOffsetInFrame_, sizeof header);
+  header = ReadHeaderOrFooter(recordOffsetInFrame_);
   if (header != *recordLength) {
     handler.SignalError(IostatBadUnformattedRecord);
     return;
@@ -993,6 +991,16 @@ bool ExternalFileUnit::Wait(int id) {
   }
 }
 
+std::int32_t ExternalFileUnit::ReadHeaderOrFooter(std::int64_t frameOffset) {
+  std::int32_t word;
+  char *wordPtr{reinterpret_cast<char *>(&word)};
+  std::memcpy(wordPtr, Frame() + frameOffset, sizeof word);
+  if (swapEndianness_) {
+    SwapEndianness(wordPtr, sizeof word, sizeof word);
+  }
+  return word;
+}
+
 void ChildIo::EndIoStatement() {
   io_.reset();
   u_.emplace<std::monostate>();

diff  --git a/flang/runtime/unit.h b/flang/runtime/unit.h
index 535f3ba3f603..9f2b0bf3a986 100644
--- a/flang/runtime/unit.h
+++ b/flang/runtime/unit.h
@@ -134,6 +134,7 @@ class ExternalFileUnit : public ConnectionState,
   void CommitWrites();
   bool CheckDirectAccess(IoErrorHandler &);
   void HitEndOnRead(IoErrorHandler &);
+  std::int32_t ReadHeaderOrFooter(std::int64_t frameOffset);
 
   Lock lock_;
   // TODO: replace with a thread ID


        


More information about the flang-commits mailing list