CON04-F. Do not use out-of-dimension subscripts in multithreaded code
Developers shall ensure that all array subscripts remain within the bounds of their respective dimensions. Using an out-of-bounds index to access adjacent memory or "overflow" into another dimension is prohibited, as it introduces undefined behavior and hidden data races in multithreaded environments.
In Fortran, data is stored in column-major order, meaning elements of a column are contiguous in memory. Although a subscript outside a dimension's declared bounds may sometimes reference a valid memory location, this practice is unsafe. For example, accessing A(0, j) on a 2D array with lower bounds 1 could inadvertently reference A(max_rows, j-1) .
In a multithreaded context, such out-of-bounds accesses create latent data races: multiple threads may read or write overlapping memory simultaneously, violating thread safety. Compilers are free to assume that programs do not rely on undefined behavior; optimizations can therefore invalidate assumptions, resulting in incorrect results or memory corruption. If the memory is uninitialized, this also introduces indeterminate and potential security vulnerabilities.
Noncompliant Code Example
In this noncompliant example, the inner loop iterates from i=1 to N , but references A(i + 1, j) . When i = N , the subscript becomes N + 1 , which Fortran interprets as the first element of the next column.
If the outer loop is parallelized by columns, the thread processing column j may read A(1, j+1) while another thread writes to it, causing a data race and undefined behavior.
subroutine example(A, N, M)
implicit none
integer, intent(in) :: N, M
real, intent(inout) :: A(N, M)
integer :: i, j
! Noncompliant: when i = N, A(i+1, j accesses A(1, j+1)
!$omp parallel do private(i, j) shared(A)
do j = 1, M - 1
do i = 1, N
A(i, j) = (A(i, j) + A(i+1, j)) / 2.0
end do
end do
end subroutine example
Compliant Solution
To comply with this rule and safety principles, the loop bounds must be strictly confined to ensure all subscripts remain within the current dimension's limits. This ensures that each thread operates only on its assigned contiguous memory segment.
subroutine example(A, N, M)
implicit none
integer, intent(in) :: N, M
real, intent(inout) :: A(N, M)
integer :: i, j
! Compliant: the row loop is restricted to N-1
! ensuring A(i+1, j) never leaves the current column j
!$omp parallel do private(i, j) shared(A)
do j = 1, M - 1
do i = 1, N - 1
A(i, j) = (A(i, j) + A(i+1, j)) / 2.0
end do
end do
end subroutine example
Risk Assessment
Writing to out-of-range subscripts can lead to arbitrary code execution, while reading from them can result in information disclosure. In parallel Fortran code, the specific risk is undefined behavior arising from non-deterministic data races, which can be further exacerbated if compilers optimize out safety checks by assuming such out-of-bounds accesses never occur.
| Recommendation | Severity | Likelihood | Detectable | Repairable | Priority | Level |
| CON04-F | High | Likely | Yes | Yes | P27 | L1 |
Attachments:
button_arrow_left.png (image/png)
button_arrow_up.png (image/png)
button_arrow_right.png (image/png)


