Skip to content

Commit c7fe5e8

Browse files
committed
[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 #57126 Differential Revision: https://reviews.llvm.org/D132168
1 parent cc180f4 commit c7fe5e8

File tree

2 files changed

+17
-8
lines changed

2 files changed

+17
-8
lines changed

flang/runtime/unit.cpp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ void ExternalFileUnit::FlushAll(IoErrorHandler &handler) {
279279
}
280280
}
281281

282-
static void SwapEndianness(
282+
static inline void SwapEndianness(
283283
char *data, std::size_t bytes, std::size_t elementBytes) {
284284
if (elementBytes > 1) {
285285
auto half{elementBytes >> 1};
@@ -733,7 +733,7 @@ void ExternalFileUnit::BeginSequentialVariableUnformattedInputRecord(
733733
"record #%jd (file offset %jd): truncated record header";
734734
}
735735
} else {
736-
std::memcpy(&header, Frame() + recordOffsetInFrame_, sizeof header);
736+
header = ReadHeaderOrFooter(recordOffsetInFrame_);
737737
recordLength = sizeof header + header; // does not include footer
738738
need = recordOffsetInFrame_ + *recordLength + sizeof footer;
739739
got = ReadFrame(frameOffsetInFile_, need, handler);
@@ -742,8 +742,7 @@ void ExternalFileUnit::BeginSequentialVariableUnformattedInputRecord(
742742
"record #%jd (file offset %jd): hit EOF reading record with "
743743
"length %jd bytes";
744744
} else {
745-
std::memcpy(&footer, Frame() + recordOffsetInFrame_ + *recordLength,
746-
sizeof footer);
745+
footer = ReadHeaderOrFooter(recordOffsetInFrame_ + *recordLength);
747746
if (footer != header) {
748747
error = "Unformatted variable-length sequential file input failed at "
749748
"record #%jd (file offset %jd): record header has length %jd "
@@ -800,7 +799,7 @@ void ExternalFileUnit::BackspaceFixedRecord(IoErrorHandler &handler) {
800799

801800
void ExternalFileUnit::BackspaceVariableUnformattedRecord(
802801
IoErrorHandler &handler) {
803-
std::int32_t header{0}, footer{0};
802+
std::int32_t header{0};
804803
auto headerBytes{static_cast<std::int64_t>(sizeof header)};
805804
frameOffsetInFile_ += recordOffsetInFrame_;
806805
recordOffsetInFrame_ = 0;
@@ -817,8 +816,7 @@ void ExternalFileUnit::BackspaceVariableUnformattedRecord(
817816
handler.SignalError(IostatShortRead);
818817
return;
819818
}
820-
std::memcpy(&footer, Frame(), sizeof footer);
821-
recordLength = footer;
819+
recordLength = ReadHeaderOrFooter(0);
822820
if (frameOffsetInFile_ < *recordLength + 2 * headerBytes) {
823821
handler.SignalError(IostatBadUnformattedRecord);
824822
return;
@@ -835,7 +833,7 @@ void ExternalFileUnit::BackspaceVariableUnformattedRecord(
835833
handler.SignalError(IostatShortRead);
836834
return;
837835
}
838-
std::memcpy(&header, Frame() + recordOffsetInFrame_, sizeof header);
836+
header = ReadHeaderOrFooter(recordOffsetInFrame_);
839837
if (header != *recordLength) {
840838
handler.SignalError(IostatBadUnformattedRecord);
841839
return;
@@ -993,6 +991,16 @@ bool ExternalFileUnit::Wait(int id) {
993991
}
994992
}
995993

994+
std::int32_t ExternalFileUnit::ReadHeaderOrFooter(std::int64_t frameOffset) {
995+
std::int32_t word;
996+
char *wordPtr{reinterpret_cast<char *>(&word)};
997+
std::memcpy(wordPtr, Frame() + frameOffset, sizeof word);
998+
if (swapEndianness_) {
999+
SwapEndianness(wordPtr, sizeof word, sizeof word);
1000+
}
1001+
return word;
1002+
}
1003+
9961004
void ChildIo::EndIoStatement() {
9971005
io_.reset();
9981006
u_.emplace<std::monostate>();

flang/runtime/unit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ class ExternalFileUnit : public ConnectionState,
134134
void CommitWrites();
135135
bool CheckDirectAccess(IoErrorHandler &);
136136
void HitEndOnRead(IoErrorHandler &);
137+
std::int32_t ReadHeaderOrFooter(std::int64_t frameOffset);
137138

138139
Lock lock_;
139140
// TODO: replace with a thread ID

0 commit comments

Comments
 (0)