Skip to content

Commit d0caf0d

Browse files
[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.
1 parent 18ea6fc commit d0caf0d

File tree

1 file changed

+8
-5
lines changed

1 file changed

+8
-5
lines changed

flang/include/flang/Common/format.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "Fortran-consts.h"
1313
#include "enum-set.h"
14+
#include "llvm/Support/MathExtras.h"
1415
#include <cstring>
1516

1617
// Define a FormatValidator class template to validate a format expression
@@ -214,16 +215,18 @@ template <typename CHAR> void FormatValidator<CHAR>::NextToken() {
214215
case '7':
215216
case '8':
216217
case '9': {
217-
int64_t lastValue;
218218
const CHAR *lastCursor;
219219
integerValue_ = 0;
220220
bool overflow{false};
221221
do {
222-
lastValue = integerValue_;
223222
lastCursor = cursor_;
224-
integerValue_ = 10 * integerValue_ + c - '0';
225-
if (lastValue > integerValue_) {
226-
overflow = true;
223+
if (LLVM_LIKELY(!overflow)) {
224+
overflow = llvm::MulOverflow(
225+
static_cast<int64_t>(10), integerValue_, integerValue_);
226+
}
227+
if (LLVM_LIKELY(!overflow)) {
228+
overflow = llvm::AddOverflow(
229+
integerValue_, static_cast<int64_t>(c - '0'), integerValue_);
227230
}
228231
c = NextChar();
229232
} while (c >= '0' && c <= '9');

0 commit comments

Comments
 (0)