[flang-commits] [flang] cdd54cb - [flang][runtime] Catch decimal integer input overflow

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Tue May 24 14:15:21 PDT 2022


Author: Peter Klausler
Date: 2022-05-24T14:07:35-07:00
New Revision: cdd54cbdd937f7473e0ba065ecafc70742f3f1fd

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

LOG: [flang][runtime] Catch decimal integer input overflow

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

Added: 
    

Modified: 
    flang/include/flang/Runtime/iostat.h
    flang/runtime/edit-input.cpp
    flang/runtime/iostat.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Runtime/iostat.h b/flang/include/flang/Runtime/iostat.h
index 3395207468237..562efb73f96c9 100644
--- a/flang/include/flang/Runtime/iostat.h
+++ b/flang/include/flang/Runtime/iostat.h
@@ -72,6 +72,8 @@ enum Iostat {
   IostatBadScaleFactor,
   IostatBadAsynchronous,
   IostatBadWaitUnit,
+  IostatBOZInputOverflow,
+  IostatIntegerInputOverflow,
 };
 
 const char *IostatErrorString(int);

diff  --git a/flang/runtime/edit-input.cpp b/flang/runtime/edit-input.cpp
index 2e8ea3faa9e3e..7e53b54f59949 100644
--- a/flang/runtime/edit-input.cpp
+++ b/flang/runtime/edit-input.cpp
@@ -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;
   }
@@ -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') {
@@ -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;
   }

diff  --git a/flang/runtime/iostat.cpp b/flang/runtime/iostat.cpp
index de9658fd23d2b..5ab1ee435ef22 100644
--- a/flang/runtime/iostat.cpp
+++ b/flang/runtime/iostat.cpp
@@ -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;
   }


        


More information about the flang-commits mailing list