Skip to content

Commit 9a8d45f

Browse files
authored
[Flang][OpenMP] Fix crash when block.end() is missed (#147519)
As reported in #145917 and #147309, there are situation's where flang may crash. This is because `nextIt` in `RewriteOpenMPLoopConstruct` gets re-assigned when an iterator is erased from the block. If this is missed, Flang may attempt to access a location in memory that is not accessable and cause a compiler crash. This adds protection where the crash can occur, and a test with a reproducer that can trigger the crash. Fixes #147309
1 parent b4b150f commit 9a8d45f

File tree

2 files changed

+82
-5
lines changed

2 files changed

+82
-5
lines changed

flang/lib/Semantics/canonicalize-omp.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,13 @@ class CanonicalizationOfOmp {
151151
std::move(*doCons);
152152
nextIt = block.erase(nextIt);
153153
// try to match OmpEndLoopDirective
154-
if (auto *endDir{
155-
GetConstructIf<parser::OmpEndLoopDirective>(*nextIt)}) {
156-
std::get<std::optional<parser::OmpEndLoopDirective>>(x.t) =
157-
std::move(*endDir);
158-
nextIt = block.erase(nextIt);
154+
if (nextIt != block.end()) {
155+
if (auto *endDir{
156+
GetConstructIf<parser::OmpEndLoopDirective>(*nextIt)}) {
157+
std::get<std::optional<parser::OmpEndLoopDirective>>(x.t) =
158+
std::move(*endDir);
159+
nextIt = block.erase(nextIt);
160+
}
159161
}
160162
} else {
161163
messages_.Say(dir.source,
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
! This reproducer hit an issue where when finding directive's, and end directive's would iterate over the block.end()
2+
! so Flang would crash. We should be able to parse this subroutine without flang crashing.
3+
! Reported in https://github.com/llvm/llvm-project/issues/147309 and https://github.com/llvm/llvm-project/pull/145917#issuecomment-3041570824
4+
5+
!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=51 %s | FileCheck %s --check-prefix=CHECK-PARSE
6+
!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=51 %s | FileCheck %s --check-prefix=CHECK-UNPARSE
7+
8+
subroutine loop_transformation_construct7
9+
implicit none
10+
real(kind=8), dimension(1:10, 2) :: a
11+
integer :: b,c
12+
13+
!$omp target teams distribute parallel do collapse(2) private(b)
14+
do b = 1, 10
15+
do c = 1, 10
16+
a(b, 2) = a(c, 1)
17+
end do
18+
end do
19+
end subroutine
20+
21+
!CHECK-PARSE: | ExecutionPart -> Block
22+
!CHECK-PARSE-NEXT: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct
23+
!CHECK-PARSE-NEXT: | | | OmpBeginLoopDirective
24+
!CHECK-PARSE-NEXT: | | | | OmpLoopDirective -> llvm::omp::Directive = target teams distribute parallel do
25+
!CHECK-PARSE-NEXT: | | | | OmpClauseList -> OmpClause -> Collapse -> Scalar -> Integer -> Constant -> Expr = '2_4'
26+
!CHECK-PARSE-NEXT: | | | | | LiteralConstant -> IntLiteralConstant = '2'
27+
!CHECK-PARSE-NEXT: | | | | OmpClause -> Private -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'b'
28+
!CHECK-PARSE-NEXT: | | | DoConstruct
29+
!CHECK-PARSE-NEXT: | | | | NonLabelDoStmt
30+
!CHECK-PARSE-NEXT: | | | | | LoopControl -> LoopBounds
31+
!CHECK-PARSE-NEXT: | | | | | | Scalar -> Name = 'b'
32+
!CHECK-PARSE-NEXT: | | | | | | Scalar -> Expr = '1_4'
33+
!CHECK-PARSE-NEXT: | | | | | | | LiteralConstant -> IntLiteralConstant = '1'
34+
!CHECK-PARSE-NEXT: | | | | | | Scalar -> Expr = '10_4'
35+
!CHECK-PARSE-NEXT: | | | | | | | LiteralConstant -> IntLiteralConstant = '10'
36+
!CHECK-PARSE-NEXT: | | | | Block
37+
!CHECK-PARSE-NEXT: | | | | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct
38+
!CHECK-PARSE-NEXT: | | | | | | NonLabelDoStmt
39+
!CHECK-PARSE-NEXT: | | | | | | | LoopControl -> LoopBounds
40+
!CHECK-PARSE-NEXT: | | | | | | | | Scalar -> Name = 'c'
41+
!CHECK-PARSE-NEXT: | | | | | | | | Scalar -> Expr = '1_4'
42+
!CHECK-PARSE-NEXT: | | | | | | | | | LiteralConstant -> IntLiteralConstant = '1'
43+
!CHECK-PARSE-NEXT: | | | | | | | | Scalar -> Expr = '10_4'
44+
!CHECK-PARSE-NEXT: | | | | | | | | | LiteralConstant -> IntLiteralConstant = '10'
45+
!CHECK-PARSE-NEXT: | | | | | | Block
46+
!CHECK-PARSE-NEXT: | | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt = 'a(int(b,kind=8),2_8)=a(int(c,kind=8),1_8)'
47+
!CHECK-PARSE-NEXT: | | | | | | | | Variable = 'a(int(b,kind=8),2_8)'
48+
!CHECK-PARSE-NEXT: | | | | | | | | | Designator -> DataRef -> ArrayElement
49+
!CHECK-PARSE-NEXT: | | | | | | | | | | DataRef -> Name = 'a'
50+
!CHECK-PARSE-NEXT: | | | | | | | | | | SectionSubscript -> Integer -> Expr = 'b'
51+
!CHECK-PARSE-NEXT: | | | | | | | | | | | Designator -> DataRef -> Name = 'b'
52+
!CHECK-PARSE-NEXT: | | | | | | | | | | SectionSubscript -> Integer -> Expr = '2_4'
53+
!CHECK-PARSE-NEXT: | | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '2'
54+
!CHECK-PARSE-NEXT: | | | | | | | | Expr = 'a(int(c,kind=8),1_8)'
55+
!CHECK-PARSE-NEXT: | | | | | | | | | Designator -> DataRef -> ArrayElement
56+
!CHECK-PARSE-NEXT: | | | | | | | | | | DataRef -> Name = 'a'
57+
!CHECK-PARSE-NEXT: | | | | | | | | | | SectionSubscript -> Integer -> Expr = 'c'
58+
!CHECK-PARSE-NEXT: | | | | | | | | | | | Designator -> DataRef -> Name = 'c'
59+
!CHECK-PARSE-NEXT: | | | | | | | | | | SectionSubscript -> Integer -> Expr = '1_4'
60+
!CHECK-PARSE-NEXT: | | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '1'
61+
!CHECK-PARSE-NEXT: | | | | | | EndDoStmt ->
62+
!CHECK-PARSE-NEXT: | | | | EndDoStmt ->
63+
!CHECK-PARSE-NEXT: | EndSubroutineStmt ->
64+
65+
!CHECK-UNPARSE: SUBROUTINE loop_transformation_construct7
66+
!CHECK-UNPARSE-NEXT: IMPLICIT NONE
67+
!CHECK-UNPARSE-NEXT: REAL(KIND=8_4), DIMENSION(1_4:10_4,2_4) :: a
68+
!CHECK-UNPARSE-NEXT: INTEGER b, c
69+
!CHECK-UNPARSE-NEXT: !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2_4) PRIVATE(b)
70+
!CHECK-UNPARSE-NEXT: DO b=1_4,10_4
71+
!CHECK-UNPARSE-NEXT: DO c=1_4,10_4
72+
!CHECK-UNPARSE-NEXT: a(int(b,kind=8),2_8)=a(int(c,kind=8),1_8)
73+
!CHECK-UNPARSE-NEXT: END DO
74+
!CHECK-UNPARSE-NEXT: END DO
75+
!CHECK-UNPARSE-NEXT: END SUBROUTINE

0 commit comments

Comments
 (0)