Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[flang][runtime] Fix integer overflow check in FORMAT #79368

Closed
wants to merge 1 commit into from

Conversation

klausler
Copy link
Contributor

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

Fixes #79255.

@llvmbot llvmbot added flang:runtime flang Flang issues not falling into any other category labels Jan 24, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Jan 24, 2024

@llvm/pr-subscribers-flang-semantics

@llvm/pr-subscribers-flang-runtime

Author: Peter Klausler (klausler)

Changes

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

Fixes #79255.


Full diff: https://github.com/llvm/llvm-project/pull/79368.diff

1 Files Affected:

  • (modified) flang/runtime/format-implementation.h (+3-2)
diff --git a/flang/runtime/format-implementation.h b/flang/runtime/format-implementation.h
index c54ac062c7beab9..e475508b9ba58a7 100644
--- a/flang/runtime/format-implementation.h
+++ b/flang/runtime/format-implementation.h
@@ -85,8 +85,9 @@ int FormatControl<CONTEXT>::GetIntField(
     ch = PeekNext();
   }
   while (ch >= '0' && ch <= '9') {
-    if (result >
-        std::numeric_limits<int>::max() / 10 - (static_cast<int>(ch) - '0')) {
+    if (result > std::numeric_limits<int>::max() / 10 ||
+        std::numeric_limits<int>::max() - 10 * result <
+            static_cast<int>(ch) - '0') {
       handler.SignalError(
           IostatErrorInFormat, "FORMAT integer field out of range");
       if (hadError) {

@vdonaldson
Copy link
Contributor

Compare format.h lines 206-236. Would that code work here? Does that code also need to be changed?

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

Fixes llvm#79255.
@klausler
Copy link
Contributor Author

Compare format.h lines 206-236. Would that code work here? Does that code also need to be changed?

Good point. I've reworked the change.

lastCursor = cursor_;
integerValue_ = 10 * integerValue_ + c - '0';
if (lastValue > integerValue_) {
if (integerValue_ > std::numeric_limits<int>::max()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How will this new condition ever be true?

The idea is that an n+1 digit unsigned number should always be larger than an n digit unsigned number. With bounded computer arithmetic that fails if the number overflows.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

integerValue_ is std::int64_t

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. So what should be a positive value becomes negative on overflow. If the type were unsigned, the overflow value would be positive but smaller. I think both signed and unsigned underlying types have this property. (It's been a long time since I looked at this in detail.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

integerValue_ hasn't overflowed its 64-bit range, and can be compared to the max 32-bit value safely.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why restrict values to 32 bits? Don't we accommodate 64 bit values by "default"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The checker in format-implementation.h limited things to 32 bits already. That seems sufficient to me for repeat counts, field widths, &c. in FORMAT strings.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the two cases are not then strictly comparable. Maybe the best choice is to leave the compile time format.h code as is and go with new code in the runtime.

@klausler klausler closed this Jan 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:runtime flang:semantics flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Flang] Execution error of a large number as a repeat specification
3 participants