Skip to content

[flang] sanitize set_length in lowering #80412

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

Merged
merged 1 commit into from
Feb 2, 2024

Conversation

jeanPerier
Copy link
Contributor

In fortran, it is possible to give a negative "i" in "character(i)" in which case the standard says the length is zero. So the length must be sanitized as max(0, user_input) in lowering.

This is already done when lowering specification parts, but was not done when "character(i)" appears in array constructors. Sanitize the length when lowering SetLength in lowering.

Fixes #80270

In fortran, it is possible to give a negative "i" in "character(i)"
in which case the standard says the length is zero. So the length
must be sanitized as max(0, user_input) in lowering.

This is already done when lowering specification parts, but was not done
when "character(i)" appears in array constructors. Sanitize the length when
lowering SetLength in lowering.
@jeanPerier jeanPerier requested a review from tblah February 2, 2024 10:07
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:fir-hlfir labels Feb 2, 2024
@llvmbot
Copy link
Member

llvmbot commented Feb 2, 2024

@llvm/pr-subscribers-flang-fir-hlfir

Author: None (jeanPerier)

Changes

In fortran, it is possible to give a negative "i" in "character(i)" in which case the standard says the length is zero. So the length must be sanitized as max(0, user_input) in lowering.

This is already done when lowering specification parts, but was not done when "character(i)" appears in array constructors. Sanitize the length when lowering SetLength in lowering.

Fixes #80270


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

2 Files Affected:

  • (modified) flang/lib/Lower/ConvertExprToHLFIR.cpp (+4-1)
  • (modified) flang/test/Lower/HLFIR/array-ctor-character.f90 (+14)
diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index ba3acd8bba5f8..68ecaa19d2d5d 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -1219,8 +1219,11 @@ struct BinaryOp<Fortran::evaluate::SetLength<KIND>> {
                                          fir::FirOpBuilder &builder, const Op &,
                                          hlfir::Entity string,
                                          hlfir::Entity length) {
+    // The input length may be a user input and needs to be sanitized as per
+    // Fortran 2018 7.4.4.2 point 5.
+    mlir::Value safeLength = fir::factory::genMaxWithZero(builder, loc, length);
     return hlfir::EntityWithAttributes{
-        builder.create<hlfir::SetLengthOp>(loc, string, length)};
+        builder.create<hlfir::SetLengthOp>(loc, string, safeLength)};
   }
   static void
   genResultTypeParams(mlir::Location, fir::FirOpBuilder &, hlfir::Entity,
diff --git a/flang/test/Lower/HLFIR/array-ctor-character.f90 b/flang/test/Lower/HLFIR/array-ctor-character.f90
index 7304eb24a647f..85e6ed27fe077 100644
--- a/flang/test/Lower/HLFIR/array-ctor-character.f90
+++ b/flang/test/Lower/HLFIR/array-ctor-character.f90
@@ -86,3 +86,17 @@ subroutine takes_char(c)
   print *, "expect: abcdef"
   call test_dynamic_length()
 end
+
+subroutine test_set_length_sanitize(i, c1)
+  integer(8) :: i
+  character(*) :: c1
+  call takes_char([character(len=i):: c1])
+end subroutine
+! CHECK-LABEL:   func.func @_QPtest_set_length_sanitize(
+! CHECK:   %[[VAL_6:.*]]:2 = hlfir.declare {{.*}}Ec1
+! CHECK:   %[[VAL_9:.*]]:2 = hlfir.declare {{.*}}Ei
+! CHECK:   %[[VAL_25:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<i64>
+! CHECK:   %[[VAL_26:.*]] = arith.constant 0 : i64
+! CHECK:   %[[VAL_27:.*]] = arith.cmpi sgt, %[[VAL_25]], %[[VAL_26]] : i64
+! CHECK:   %[[VAL_28:.*]] = arith.select %[[VAL_27]], %[[VAL_25]], %[[VAL_26]] : i64
+! CHECK:   %[[VAL_29:.*]] = hlfir.set_length %[[VAL_6]]#0 len %[[VAL_28]] : (!fir.boxchar<1>, i64) -> !hlfir.expr<!fir.char<1,?>>

Copy link
Contributor

@tblah tblah left a comment

Choose a reason for hiding this comment

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

Thank you very much for picking this up. Looks good to me and this does fix my issue.

@jeanPerier jeanPerier merged commit 7a4570a into llvm:main Feb 2, 2024
@jeanPerier jeanPerier deleted the jpr-fix-neg-set-length branch February 2, 2024 13:08
tblah added a commit to tblah/llvm-test-suite that referenced this pull request Feb 2, 2024
char_length_2{0,1}.f90 were fixed in
llvm/llvm-project#80412.

Now that these successfully compile I thought I might as well
re-categorise the other tests in the same group too.
tblah added a commit to tblah/llvm-test-suite that referenced this pull request Feb 2, 2024
char_length_2{0,1}.f90 were fixed in
llvm/llvm-project#80412.

Now that these successfully compile I thought I might as well
re-categorise the other tests in the same group too.
agozillon pushed a commit to agozillon/llvm-project that referenced this pull request Feb 5, 2024
In fortran, it is possible to give a negative "i" in "character(i)" in
which case the standard says the length is zero. So the length must be
sanitized as max(0, user_input) in lowering.

This is already done when lowering specification parts, but was not done
when "character(i)" appears in array constructors. Sanitize the length
when lowering SetLength in lowering.

Fixes llvm#80270
tblah added a commit to llvm/llvm-test-suite that referenced this pull request Feb 6, 2024
char_length_2{0,1}.f90 were fixed in
llvm/llvm-project#80412.

Now that these successfully compile I thought I might as well
re-categorise the other tests in the same group too.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:fir-hlfir flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[flang] out of memory optimizing character with negative length
3 participants