From 23f258cebbeedd270154521ec3cef7e3b1035431 Mon Sep 17 00:00:00 2001 From: Peter Klausler Date: Tue, 17 Jan 2023 13:30:09 -0800 Subject: [PATCH] [flang] Don't fold REPEAT() when the result would be too large A test program shouldn't be able to crash the compiler by getting it to fold REPEAT() with an absurdly large repetition count. Differential Revision: https://reviews.llvm.org/D142770 --- flang/lib/Evaluate/character.h | 1 + flang/lib/Evaluate/fold-character.cpp | 13 ++++++++++--- flang/test/Evaluate/errors01.f90 | 4 ++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/flang/lib/Evaluate/character.h b/flang/lib/Evaluate/character.h index 7948726..9742e87 100644 --- a/flang/lib/Evaluate/character.h +++ b/flang/lib/Evaluate/character.h @@ -106,6 +106,7 @@ public: static Character REPEAT(const Character &str, ConstantSubscript ncopies) { Character result; if (!str.empty()) { + result.reserve(ncopies * str.size()); while (ncopies-- > 0) { result += str; } diff --git a/flang/lib/Evaluate/fold-character.cpp b/flang/lib/Evaluate/fold-character.cpp index 56214ea..3aec77b 100644 --- a/flang/lib/Evaluate/fold-character.cpp +++ b/flang/lib/Evaluate/fold-character.cpp @@ -97,9 +97,16 @@ Expr> FoldIntrinsicFunction( } else if (name == "repeat") { // not elemental if (auto scalars{GetScalarConstantArguments( context, funcRef.arguments())}) { - return Expr{Constant{ - CharacterUtils::REPEAT(std::get>(*scalars), - std::get>(*scalars).ToInt64())}}; + auto str{std::get>(*scalars)}; + auto n{std::get>(*scalars).ToInt64()}; + if (static_cast(n) * str.size() > + (1 << 20)) { // sanity limit of 1MiB + context.messages().Say( + "Result of REPEAT() is too large to compute at compilation time (%g characters)"_port_en_US, + static_cast(n) * str.size()); + } else { + return Expr{Constant{CharacterUtils::REPEAT(str, n)}}; + } } } else if (name == "trim") { // not elemental if (auto scalar{ diff --git a/flang/test/Evaluate/errors01.f90 b/flang/test/Evaluate/errors01.f90 index d2fcc95..72ad988 100644 --- a/flang/test/Evaluate/errors01.f90 +++ b/flang/test/Evaluate/errors01.f90 @@ -137,6 +137,10 @@ module m !CHERK: error: Must be a constant value integer, parameter :: bad2 = storage_size(y) end subroutine + subroutine s13 + !CHECK: portability: Result of REPEAT() is too large to compute at compilation time (1.1259e+15 characters) + print *, repeat(repeat(' ', 2**20), 2**30) + end subroutine subroutine warnings real, parameter :: ok1 = scale(0.0, 99999) ! 0.0 real, parameter :: ok2 = scale(1.0, -99999) ! 0.0 -- 2.7.4