Skip to content

Commit 4f9cb79

Browse files
authored
[flang][runtime] Fix octal input of REAL(10) (#74658)
The overflow check didn't work for a 27-digit octal field containing an 80-bit x87 extended precision real value. The count of bytes required was too large because the leading digit (1) was assumed to require a full three bits. And the actual transmission of the octal input digits to the output buffer was incorrect, too. Fixes llvm-test-suite/Fortran/gfortran/regression/boz_15.f90.
1 parent c94f780 commit 4f9cb79

File tree

1 file changed

+32
-10
lines changed

1 file changed

+32
-10
lines changed

flang/runtime/edit-input.cpp

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,15 @@ static bool EditBOZInput(
6464
}
6565
// Count significant digits after any leading white space & zeroes
6666
int digits{0};
67+
int significantBits{0};
6768
for (; next; next = io.NextInField(remaining, edit)) {
6869
char32_t ch{*next};
6970
if (ch == ' ' || ch == '\t') {
70-
continue;
71+
if (edit.modes.editingFlags & blankZero) {
72+
ch = '0'; // BZ mode - treat blank as if it were zero
73+
} else {
74+
continue;
75+
}
7176
}
7277
if (ch >= '0' && ch <= '1') {
7378
} else if (LOG2_BASE >= 3 && ch >= '2' && ch <= '7') {
@@ -79,9 +84,22 @@ static bool EditBOZInput(
7984
"Bad character '%lc' in B/O/Z input field", ch);
8085
return false;
8186
}
82-
++digits;
87+
if (digits++ == 0) {
88+
significantBits = 4;
89+
if (ch >= '0' && ch <= '1') {
90+
significantBits = 1;
91+
} else if (ch >= '2' && ch <= '3') {
92+
significantBits = 2;
93+
} else if (ch >= '4' && ch <= '7') {
94+
significantBits = 3;
95+
} else {
96+
significantBits = 4;
97+
}
98+
} else {
99+
significantBits += LOG2_BASE;
100+
}
83101
}
84-
auto significantBytes{static_cast<std::size_t>(digits * LOG2_BASE + 7) / 8};
102+
auto significantBytes{static_cast<std::size_t>(significantBits + 7) / 8};
85103
if (significantBytes > bytes) {
86104
io.GetIoErrorHandler().SignalError(IostatBOZInputOverflow,
87105
"B/O/Z input of %d digits overflows %zd-byte variable", digits, bytes);
@@ -96,12 +114,17 @@ static bool EditBOZInput(
96114
auto *data{reinterpret_cast<unsigned char *>(n) +
97115
(isHostLittleEndian ? significantBytes - 1 : 0)};
98116
int shift{((digits - 1) * LOG2_BASE) & 7};
99-
if (shift + LOG2_BASE > 8) {
100-
shift -= 8; // misaligned octal
101-
}
102117
while (digits > 0) {
103118
char32_t ch{*io.NextInField(remaining, edit)};
104119
int digit{0};
120+
if (ch == ' ' || ch == '\t') {
121+
if (edit.modes.editingFlags & blankZero) {
122+
ch = '0'; // BZ mode - treat blank as if it were zero
123+
} else {
124+
continue;
125+
}
126+
}
127+
--digits;
105128
if (ch >= '0' && ch <= '9') {
106129
digit = ch - '0';
107130
} else if (ch >= 'A' && ch <= 'F') {
@@ -111,12 +134,11 @@ static bool EditBOZInput(
111134
} else {
112135
continue;
113136
}
114-
--digits;
115137
if (shift < 0) {
116-
shift += 8;
117-
if (shift + LOG2_BASE > 8) { // misaligned octal
118-
*data |= digit >> (8 - shift);
138+
if (shift + LOG2_BASE > 0) { // misaligned octal
139+
*data |= digit >> -shift;
119140
}
141+
shift += 8;
120142
data += increment;
121143
}
122144
*data |= digit << shift;

0 commit comments

Comments
 (0)