Skip to main content
GitHub

ARR04-F. Ensure arrays ranges mapped to devices cover all accessed elements

Developers shall ensure that any array section or range explicitly mapped to a device memory space (e.g., GPU) fully encompasses all indices accessed within the offloaded region to prevent out-of-bounds access and undefined behavior.

In heterogeneous computing, it is common to map only the array portion required for a computation to reduce data transfer overhead. However, if an offloaded block accesses indices outside the explicitly mapped range, this results in undefined behavior, which can manifest as invalid memory access on the device, hardware traps, segmentation faults, or program crashes.

An "apparently accessible" subscript is invalid if the corresponding memory has not been mapped to the device. While the Fortran standard requires subscripts to stay within declared bounds for safety, the programmer must additionally ensure consistency between data mapping directives and the loop boundaries executed on the device.

Noncompliant Code Example

In this noncompliant example, the developer attempts to optimize a vector addition by mapping only the first 50 elements of arrays A , B , and sum to the devide (e.g., GPU). However, the DO loop iterates through the entire size of the arrays, from 1 to 100. The GPU kernel will attempt to access elements 51 through 100, which have not been mapped, leading to a memory violation.

Non-compliant code
subroutine partial_copy(A, B, sum)
  use iso_fortran_env, only: real32
  implicit none
  real(real32), intent(in)  :: A(100), B(100)
  real(real32), intent(out) :: sum(100)
  integer                   :: i

  ! Noncompliant: the mapped range 1:50 does not cover the range 1:100 used in the loop
  !$omp target map(to: A(1:50), B(1:50)) map(from: sum(1:50))
  !$omp parallel do private(i)
  do i = 1, 100
    sum(i) = A(i) + B(i)
  end do
  !$omp end target
end subroutine

Compliant Solution

In the compliant solution, the mapped range 1:100 is updated to match the actual usage in the loop.

Compliant code
subroutine partial_copy(A, B, sum)
  use iso_fortran_env, only: real32
  implicit none
  real(real32), intent(in)  :: A(100), B(100)
  real(real32), intent(out) :: sum(100)
  integer                   :: i

  ! Compliant: the mapped range 1:100 covers the range 1:100 used in the loop
  !$omp target map(to: A(1:100), B(1:100)) map(from: sum(1:100))
  !$omp parallel do private(i)
  do i = 1, 100
    sum(i) = A(i) + B(i)
  end do
  !$omp end target
end subroutine

Risk Assessment

Failing to map the used range of an array results in out-of-bounds device memory access. This can lead to information exposure if the device reads unmapped memory, arbitrary code execution if an unmapped write operation is exploited, or program crashes or hardware faults due to invalid memory access.

RecommendationSeverityLikelihoodDetectableRepairablePriorityLevel
ARR04-FHighLikelyYesYesP27L1

Attachments: