Skip to content

Commit

Permalink
[flang][runtime] Catch decimal integer input overflow
Browse files Browse the repository at this point in the history
B/O/Z input overflow is already caught, and real input overflow
is signalled as an IEEE arithmetic exception, but regular decimal
integer overflow was silent.

Differential Revision: https://reviews.llvm.org/D126155
  • Loading branch information
klausler committed May 24, 2022
1 parent 0a79113 commit cdd54cb
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 1 deletion.
2 changes: 2 additions & 0 deletions flang/include/flang/Runtime/iostat.h
Expand Up @@ -72,6 +72,8 @@ enum Iostat {
IostatBadScaleFactor,
IostatBadAsynchronous,
IostatBadWaitUnit,
IostatBOZInputOverflow,
IostatIntegerInputOverflow,
};

const char *IostatErrorString(int);
Expand Down
16 changes: 15 additions & 1 deletion flang/runtime/edit-input.cpp
Expand Up @@ -47,7 +47,7 @@ static bool EditBOZInput(
}
auto significantBytes{static_cast<std::size_t>(digits * LOG2_BASE + 7) / 8};
if (significantBytes > bytes) {
io.GetIoErrorHandler().SignalError(
io.GetIoErrorHandler().SignalError(IostatBOZInputOverflow,
"B/O/Z input of %d digits overflows %zd-byte variable", digits, bytes);
return false;
}
Expand Down Expand Up @@ -140,6 +140,7 @@ bool EditIntegerInput(
bool negate{ScanNumericPrefix(io, edit, next, remaining)};
common::UnsignedInt128 value{0};
bool any{negate};
bool overflow{false};
for (; next; next = io.NextInField(remaining, edit)) {
char32_t ch{*next};
if (ch == ' ' || ch == '\t') {
Expand All @@ -157,10 +158,23 @@ bool EditIntegerInput(
"Bad character '%lc' in INTEGER input field", ch);
return false;
}
static constexpr auto maxu128{~common::UnsignedInt128{0}};
static constexpr auto maxu128OverTen{maxu128 / 10};
static constexpr int maxLastDigit{
static_cast<int>(maxu128 - (maxu128OverTen * 10))};
overflow |= value >= maxu128OverTen &&
(value > maxu128OverTen || digit > maxLastDigit);
value *= 10;
value += digit;
any = true;
}
auto maxForKind{common::UnsignedInt128{1} << ((8 * kind) - 1)};
overflow |= value >= maxForKind && (value > maxForKind || !negate);
if (overflow) {
io.GetIoErrorHandler().SignalError(IostatIntegerInputOverflow,
"Decimal input overflows INTEGER(%d) variable", kind);
return false;
}
if (negate) {
value = -value;
}
Expand Down
4 changes: 4 additions & 0 deletions flang/runtime/iostat.cpp
Expand Up @@ -88,6 +88,10 @@ const char *IostatErrorString(int iostat) {
"OPEN(ASYNCHRONOUS='YES')";
case IostatBadWaitUnit:
return "WAIT(ID=nonzero) for a bad unit number";
case IostatBOZInputOverflow:
return "B/O/Z input value overflows variable";
case IostatIntegerInputOverflow:
return "Integer input value overflows variable";
default:
return nullptr;
}
Expand Down

0 comments on commit cdd54cb

Please sign in to comment.