[flang-commits] [flang] [flang] Avoid signed integer overflow in GetNonNegativeExtent (PR #222207)
via flang-commits
flang-commits at lists.llvm.org
Tue Sep 8 19:13:19 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics
Author: Eugene Epshteyn (eugeneepshteyn)
<details>
<summary>Changes</summary>
`GetNonNegativeExtent()` computes a dimension's extent from constant bounds as `ub - lb + 1` in `ConstantSubscript` (`int64_t`) arithmetic. For an oversized dimension such as `integer(1) :: a(0_8:9223372036854775807_8)`, whose extent is 2\*\*63, that computation overflows — undefined behavior, and the ubsan failure reported in #<!-- -->221940.
The wrapped result has to be preserved: storage sequences that are too large are diagnosed later, while offsets are computed, and that code tells a genuinely empty dimension from one whose extent wrapped around by cross-checking the original bounds (`IsEmptyDimension()` in `Semantics/compute-offsets.cpp`). This patch therefore computes the same two's complement result with `llvm::SubOverflow()` and `llvm::AddOverflow()`, which are defined for every input. Subtracting first also covers bounds of mixed sign, where `ub - lb` can overflow before the increment.
Fixes #<!-- -->221940
Assisted-by: AI
---
Full diff: https://github.com/llvm/llvm-project/pull/222207.diff
1 Files Affected:
- (modified) flang/lib/Evaluate/shape.cpp (+10-1)
``````````diff
diff --git a/flang/lib/Evaluate/shape.cpp b/flang/lib/Evaluate/shape.cpp
index 924b6cbdddd5e..f0fba61a25bde 100644
--- a/flang/lib/Evaluate/shape.cpp
+++ b/flang/lib/Evaluate/shape.cpp
@@ -18,6 +18,7 @@
#include "flang/Parser/message.h"
#include "flang/Semantics/semantics.h"
#include "flang/Semantics/symbol.h"
+#include "llvm/Support/MathExtras.h"
#include <functional>
using namespace std::placeholders; // _1, _2, &c. for std::bind()
@@ -464,7 +465,15 @@ static MaybeExtentExpr GetNonNegativeExtent(
if (*uval < *lval) {
return ExtentExpr{0};
} else {
- return ExtentExpr{*uval - *lval + 1};
+ // The extent of an oversized dimension, e.g. integer(1)::a(0:huge(0_8)),
+ // does not fit and wraps around; storage sequences that are too large
+ // are diagnosed later, where the original bounds distinguish a wrapped
+ // extent from an empty one. Compute the same two's complement result
+ // here without signed integer overflow.
+ ConstantSubscript extent;
+ (void)llvm::SubOverflow(*uval, *lval, extent);
+ (void)llvm::AddOverflow(extent, ConstantSubscript{1}, extent);
+ return ExtentExpr{extent};
}
} else if (lbound && ubound && lbound->Rank() == 0 && ubound->Rank() == 0 &&
(!invariantOnly ||
``````````
</details>
https://github.com/llvm/llvm-project/pull/222207
More information about the flang-commits
mailing list