[flang-commits] [flang] d0caf0d - [flang] Avoid undefined behaviour when parsing format expressions (#147539)

via flang-commits flang-commits at lists.llvm.org
Wed Jul 9 07:31:50 PDT 2025


Author: David Spickett
Date: 2025-07-09T15:31:45+01:00
New Revision: d0caf0d4857c2b00ba988f86703663685ec8697f

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

LOG: [flang] Avoid undefined behaviour when parsing format expressions (#147539)

The test flang/test/Semantics/io08.f90 was failing when UBSAN was
enabled:
```
/home/david.spickett/llvm-project/flang/include/flang/Common/format.h:224:26: runtime error: signed integer overflow: 10 * 987654321098765432 cannot be represented in type 'int64_t' (aka 'long')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /home/david.spickett/llvm-project/flang/include/flang/Common/format.h:224:26
```
This is because the code was effectively:
* Take the risk of UB happening
* Check whether it happened or not

Which UBSAN is obviously not going to like. Instead of checking after
the fact, use llvm's helpers that catch overflow without actually doing
it.

Added: 
    

Modified: 
    flang/include/flang/Common/format.h

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Common/format.h b/flang/include/flang/Common/format.h
index 1650f56140b4d..11aa6f2c07797 100644
--- a/flang/include/flang/Common/format.h
+++ b/flang/include/flang/Common/format.h
@@ -11,6 +11,7 @@
 
 #include "Fortran-consts.h"
 #include "enum-set.h"
+#include "llvm/Support/MathExtras.h"
 #include <cstring>
 
 // Define a FormatValidator class template to validate a format expression
@@ -214,16 +215,18 @@ 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_) {
-        overflow = true;
+      if (LLVM_LIKELY(!overflow)) {
+        overflow = llvm::MulOverflow(
+            static_cast<int64_t>(10), integerValue_, integerValue_);
+      }
+      if (LLVM_LIKELY(!overflow)) {
+        overflow = llvm::AddOverflow(
+            integerValue_, static_cast<int64_t>(c - '0'), integerValue_);
       }
       c = NextChar();
     } while (c >= '0' && c <= '9');


        


More information about the flang-commits mailing list