Skip to main content
GitHub

TYP01-F. Use Intrinsic Assignment for Character Entities

Programmers should use intrinsic assignment ( = ) rather than explicit loops to copy character strings to ensure correct padding, truncation, and memory safety.

In Fortran, manual character-by-character copying via loops is error-prone. If the source string is longer than the destination, a manual loop using the source length as the bound will result in an out-of-bounds write (buffer overflow). If the source is shorter, a manual loop will leave the remainder of the destination undefined.

Noncompliant Code Example

In this noncompliant code example, if len(b) is greater than len(a) , the assignment a(i:i) = b(i:i) will access memory outside the bounds of a . This is an out-of-memory-bounds array access. If len(b) is less than len(a) , the remaining characters in a are not cleared, potentially leaving sensitive data or garbage values.

Non-compliant code
subroutine example(a, b)
  implicit none
  character(len=*), intent(out) :: a
  character(len=*), intent(in)  :: b
  integer                       :: i

  do i = 1, len(b)
    a(i:i) = b(i:i)
  end do
end subroutine example

Compliant Solution

To correct this problem, use default assignment with character entities. Default assignment of character entities of different lengths will blank-fill or truncate the value as appropriate. In this compliant solution, it a will have the value of b . The assignment will blank-fill (if len(b) < len(a) ), or it will truncate the value of b to fit into a (if len(b) > len(a) ). If the lengths are important, protect the assignment with conditional code and handle the case where the lengths are problematic.

Compliant code
subroutine example(a, b)
  implicit none
  character(len=*), intent(out) :: a
  character(len=*), intent(in)  :: b

  ! Compliant: Handles truncation and padding automatically and safely.
  a = b
end subroutine example

Compliant Solution

If the intent is for a to become an exact copy of b (preserving b's length exactly, rather than truncating or padding), a should be declared as an allocatable, deferred-length character entity. Upon assignment, the processor automatically reallocates a to have the same length as b .

Compliant code
subroutine example(a, b)
  implicit none
  character(len=:), allocatable, intent(out) :: a
  character(len=*), intent(in)               :: b

  a = b
end subroutine example

Risk Assessment

Manual character loops bypass the safety mechanisms built into the language. Writing past the end of a character buffer can corrupt adjacent memory, leading to incorrect calculations or arbitrary code execution. Reading uninitialized parts of a character buffer (when the source is shorter) can lead to information leakage.

RuleSeverityLikelihoodDetectableRepairablePriorityLevel
TYP01-FHighLikelyNoNoP18L1

Automated Detection

Tool

Version

Checker

Description

Compass/ROSE



can detect violations of this rule. In particular, Rose ensures that any pointer returned by malloc() , calloc() , or realloc() is first checked for NULL before being used (otherwise it is free() -d). Rose does not handle cases where an allocation is assigned to an lvalue that is not a variable (such as a struct member or C++ function call returning a reference.)

CERT C++ Secure Coding Standard : EXP34-CPP. Ensure a null pointer is not dereferenced

ISO/IEC 9899:1999 Section 6.3.2.3, "Pointers"

ISO/IEC TR 24772 "HFC Pointer casting and pointer type changes" and "XYH Null Pointer Dereference"

MITRE CWE : CWE-476 , "NULL Pointer Dereference"

Bibliography

[ Fortran 2023 Interpretation Document ]Sections 10.2.1.3
[ Goodin 2009 ]
[ Jack 2007 ]
[ Liu 2009 ]
[ van Sprundel 2006 ]
[ Viega 2005 ]Section 5.2.18, "Null-pointer dereference"

Attachments: