[flang][runtime] Fix overflow detection for REAL input
authorPeter Klausler <pklausler@nvidia.com>
Thu, 9 Jun 2022 18:39:18 +0000 (11:39 -0700)
committerPeter Klausler <pklausler@nvidia.com>
Mon, 13 Jun 2022 23:05:11 +0000 (16:05 -0700)
The test for an overflow during decimal->binary conversion was taking
place too late, causing the data not to be rescanned from the beginning.

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

flang/runtime/edit-input.cpp
flang/runtime/io-stmt.h

index 3c8630cebc5968f799f73e860f642abe586c38e4..cfcb98b68144b820209fa13783e4e577a461cfda 100644 (file)
@@ -297,7 +297,9 @@ static int ScanRealInput(char *buffer, int bufferSize, IoStatementState &io,
       }
       for (exponent = 0; next; next = io.NextInField(remaining, edit)) {
         if (*next >= '0' && *next <= '9') {
-          exponent = 10 * exponent + *next - '0';
+          if (exponent < 10000) {
+            exponent = 10 * exponent + *next - '0';
+          }
         } else if (*next == ' ' || *next == '\t') {
           if (bzMode) {
             exponent = 10 * exponent;
@@ -392,7 +394,7 @@ static bool TryFastPathRealInput(
   const char *limit{str + maxConsume};
   decimal::ConversionToBinaryResult<PRECISION> converted{
       decimal::ConvertToBinary<PRECISION>(p, edit.modes.round, limit)};
-  if (converted.flags & decimal::Invalid) {
+  if (converted.flags & (decimal::Invalid | decimal::Overflow)) {
     return false;
   }
   if (edit.digits.value_or(0) != 0) {
@@ -428,9 +430,6 @@ static bool TryFastPathRealInput(
   io.HandleRelativePosition(p - str);
   // Set FP exception flags
   if (converted.flags != decimal::ConversionResultFlags::Exact) {
-    if (converted.flags & decimal::ConversionResultFlags::Overflow) {
-      return false; // let slow path deal with it
-    }
     RaiseFPExceptions(converted.flags);
   }
   return true;
index aa9f018dafbc095ecdf44afc168b4b5ae29717ca..5e3209b7acab6746ab5d722a7f443cf2a47a98b8 100644 (file)
@@ -136,7 +136,7 @@ public:
   std::optional<char32_t> PrepareInput(
       const DataEdit &edit, std::optional<int> &remaining) {
     remaining.reset();
-    if (edit.descriptor == DataEdit::ListDirected) {
+    if (edit.IsListDirected()) {
       std::size_t byteCount{0};
       GetNextNonBlank(byteCount);
     } else {