[flang-commits] [flang] [flang][runtime] Fix integer overflow check in FORMAT (PR #79368)

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Wed Jan 24 15:07:52 PST 2024


https://github.com/klausler updated https://github.com/llvm/llvm-project/pull/79368

>From 7b222da489dfbe88d2175daad4e48c2f70671d17 Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Wed, 24 Jan 2024 12:52:25 -0800
Subject: [PATCH] [flang][runtime] Fix integer overflow check in FORMAT

The integer overflow check used for repeat counts &c. in FORMAT
specifications was incorrect; fix it.

Fixes https://github.com/llvm/llvm-project/issues/79255.
---
 flang/include/flang/Common/format.h   | 5 ++---
 flang/runtime/format-implementation.h | 9 ++++-----
 flang/test/Semantics/io08.f90         | 2 +-
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/flang/include/flang/Common/format.h b/flang/include/flang/Common/format.h
index 2374ff6983cf41..9bb3f708edaa38 100644
--- a/flang/include/flang/Common/format.h
+++ b/flang/include/flang/Common/format.h
@@ -12,6 +12,7 @@
 #include "enum-set.h"
 #include "flang/Common/Fortran.h"
 #include <cstring>
+#include <limits>
 
 // Define a FormatValidator class template to validate a format expression
 // of a given CHAR type.  To enable use in runtime library code as well as
@@ -214,15 +215,13 @@ template <typename CHAR> void FormatValidator<CHAR>::NextToken() {
   case '7':
   case '8':
   case '9': {
-    int64_t lastValue;
     const CHAR *lastCursor;
     integerValue_ = 0;
     bool overflow{false};
     do {
-      lastValue = integerValue_;
       lastCursor = cursor_;
       integerValue_ = 10 * integerValue_ + c - '0';
-      if (lastValue > integerValue_) {
+      if (integerValue_ > std::numeric_limits<int>::max()) {
         overflow = true;
       }
       c = NextChar();
diff --git a/flang/runtime/format-implementation.h b/flang/runtime/format-implementation.h
index c54ac062c7beab..0bad3c735cc24e 100644
--- a/flang/runtime/format-implementation.h
+++ b/flang/runtime/format-implementation.h
@@ -63,7 +63,7 @@ FormatControl<CONTEXT>::FormatControl(const Terminator &terminator,
 }
 
 template <typename CONTEXT>
-int FormatControl<CONTEXT>::GetIntField(
+std::int32_t FormatControl<CONTEXT>::GetIntField(
     IoErrorHandler &handler, CharType firstCh, bool *hadError) {
   CharType ch{firstCh ? firstCh : PeekNext()};
   if (ch != '-' && ch != '+' && (ch < '0' || ch > '9')) {
@@ -74,7 +74,7 @@ int FormatControl<CONTEXT>::GetIntField(
     }
     return 0;
   }
-  int result{0};
+  std::int64_t result{0};
   bool negate{ch == '-'};
   if (negate || ch == '+') {
     if (firstCh) {
@@ -85,8 +85,8 @@ int FormatControl<CONTEXT>::GetIntField(
     ch = PeekNext();
   }
   while (ch >= '0' && ch <= '9') {
-    if (result >
-        std::numeric_limits<int>::max() / 10 - (static_cast<int>(ch) - '0')) {
+    result = 10 * result + ch - '0';
+    if (result > std::numeric_limits<int>::max()) {
       handler.SignalError(
           IostatErrorInFormat, "FORMAT integer field out of range");
       if (hadError) {
@@ -94,7 +94,6 @@ int FormatControl<CONTEXT>::GetIntField(
       }
       return result;
     }
-    result = 10 * result + ch - '0';
     if (firstCh) {
       firstCh = '\0';
     } else {
diff --git a/flang/test/Semantics/io08.f90 b/flang/test/Semantics/io08.f90
index f6038b471759f3..b1685e754192f3 100644
--- a/flang/test/Semantics/io08.f90
+++ b/flang/test/Semantics/io08.f90
@@ -36,7 +36,7 @@
   write(*,'("a""""bc", 2x)')
   write(*,'(3Habc)')
   write(*,'(3Habc, 2X, 3X)')
-  write(*,'(987654321098765432X)')
+  write(*,'(2147483647X)')
   write(*,'($)')
   write(*,'(\)')
   write(*,'(RZ,RU,RP,RN,RD,RC,SS,SP,S,3G15.3e2)')



More information about the flang-commits mailing list