Skip to main content
GitHub

ARR01-F. Do not use out-of-bounds arrays subscripts

Program units shall not reference an array element using a subscript that is outside the declared bounds of that dimension.

In Fortran, array bounds strictly define the valid index range for each dimension. By default, arrays are indexed from 1 to size , unlike many other programming languages that use zero-based indexing. Even though arrays are stored in column-major order, relying on memory layout to access elements outside the defined range is non-conforming and produces undefined behavior.

Accessing an array out of bounds results in undefined behavior, even if the calculated memory address falls within the total allocated storage of the array.

Violation may lead to:

  1. Memory corruption: writing to an out-of-bounds index may overwrite adjacent variables, return addresses, or internal runtime descriptors.
  2. Program termination: the operating system may terminate the program with a segmentation fault or access violation.
  3. Data races: in parallel execution, out-of-bounds access can inadvertently modify data owned by other threads or images, leading to race conditions.

Noncompliant Code Example

In this noncompliant example, the programmer attempts to initialize a standard 1-based array. However, the loop variable i iterates from 0 to 10. The access A(0) violates the lower bound of the array (which defaults to 1).

Non-compliant code
program main
  implicit none
  integer :: i
  real    :: A(10)

  ! Noncompliant: Loop starts at 0, but A has implicit lower bound 1
  do i = 0, 10
    A(i) = real(i)
  end do
end program main

Compliant Solution

In this compliant solution, the loop bounds are adjusted to match the array declaration.

Compliant code
program main
  implicit none
  integer :: i
  real    :: A(10)

  ! Compliant: Loop iterates from 1 to 10.
  do i = 1, 10
    A(i) = real(i)
  end do
end program main

Noncompliant Code Example

In this noncompliant example, while matrix(6, 1) and matrix(1, 2) might occupy adjacent memory addresses in a contiguous storage sequence, the Fortran standard dictates that each subscript must be within its declared bounds. Accessing matrix(6, 1) is a violation of the standard and is unsafe.

Non-compliant code
subroutine init_matrix(matrix)
  implicit none
  real, intent(out) :: matrix(5, 5)
  integer           :: i, j

  ! Noncompliant: Inner loop iterates i from 1 to 6.
  do j = 1, 4
    do i = 1, 6
      matrix(i, j) = 0.0
    end do
  end do
end subroutine init_matrix

Compliant Solution

The compliant solution iterates strictly within the defined bounds of each dimension. If the intent is to initialize the memory linearly, the code should treat the array as a whole or use RESHAPE , rather than relying on out-of-bounds indexing.

Compliant code
subroutine init_matrix(matrix)
  implicit none
  real, intent(out) :: matrix(5, 5)
  integer           :: i, j

  ! Compliant: Both indices stay within declared bounds (1:5)
  do j = 1, 5
    do i = 1, 5
      matrix(i, j) = 0.0
    end do
  end do
end subroutine init_matrix

Noncompliant Code Example

Stencil operations are a common source of out-of-bounds errors in scientific computing. In this noncompliant example, the calculation for B(i, j) attempts to access A(i, j-1) . When j=1 , this accesses A(i, 0) , which is out of bounds.

Non-compliant code
subroutine stencil_calc(n, A, B)
  implicit none
  integer, intent(in) :: n
  real, intent(in)    :: A(n, n)
  real, intent(out)   :: B(n, n)
  integer             :: i, j

  do j = 1, n
    do i = 1, n
      ! Noncompliant: When j=1, A(i, j-1) becomes A(i, 0).
      B(i, j) = A(i, j) + A(i, j-1)
    end do
  end do
end subroutine stencil_calc

Compliant Solution

The compliant solution handles the boundary condition explicitly.

Compliant code
subroutine stencil_calc(n, A, B)
  implicit none
  integer, intent(in) :: n
  real, intent(in)    :: A(n, n)
  real, intent(out)   :: B(n, n)
  integer             :: i, j

  do j = 1, n
    do i = 1, n
      if (j > 1) then
        ! Compliant: Access is guarded by check.
        B(i, j) = A(i, j) + A(i, j-1)
      else
        B(i,j) = A(i, j)
      end if
    end do
  end do
end subroutine stencil_calc

Risk Assessment

Reading or writing array elements outside their defined bounds is a critical vulnerability. It defeats memory safety mechanisms and can lead to the execution of arbitrary code if control structures or return addresses are overwritten.

RecommendationSeverityLikelihoodDetectableRepairablePriorityLevel
ARR01-FHighLikelyYesYesP27L1

Bibliography

[ Fortran 2023 Interpretation Document ]Section 9.5.3

Attachments: