F-IKOS: An Abstract Interpretation-based Static Analyzer for Fortran Programs

F-IKOS: An Abstract Interpretation-based Static Analyzer for Fortran Programs
by Sheng Zou, Liqian Chen, Guangsheng Fan, Renjie Huang, and Banghu Yin
presented at the workshop Quantitative Approaches to Software Quality 2024

Abstract: The Fortran programming language is widely utilized in numerical computation and scientific computing. Fortran programs are prone to potential runtime errors related to numerical properties due to the large number of numerical operations. In this paper, we present F-IKOS, an abstract interpretation-based static analyzer for Fortran programs on top of IKOS, which soundly handles floating-point types in Fortran programs. Firstly, we translate Fortran programs to LLVM IR using compiler front-end Flang. After that, we extend IKOS to support sound floating-point analysis and then employ it to analyze the translated LLVM IR. Particularly, when analyzing f loating-point types in programs, we first abstract floating-point expressions into real-number expressions with interval coefficients, and then linearize these expressions into real-number expressions with scalar coefficients. These linear expressions are subsequently handled by abstract domains originally designed for real-number types to produce sound analysis results. We have conducted experiments on representative Fortran programs to show the efficiency and effectiveness of F-IKOS. The experimental results are encouraging: F-IKOS soundly analyzes runtime errors in complex programs, outperforming other analyzers.
Keywords Fortran, Static Analysis, Abstract Interpretation, Floating-point Program Analysis

I don’t know how to obtain F-IKOS, but it is an offshoot of

They tested their tool on the FortranTip codes :slight_smile: (among other codes).

3 Likes

The project is now on GitHub.

1 Like

The readme of the repo now has an example of the floating point analysis f-ikos can do. Given the code

real function cap(x)
implicit none
real, intent(in) :: x
real :: y
y = x
! Cap the value of y based on certain conditions
if (10.0 > y) then
  y = 10.0
else if (15.0 < y) then
  y = 20.0
else
  y = y / (y - x)
end if
cap = y
end function cap

it says

# Summary:
Total number of checks                : 18
Total number of unreachable checks    : 0
Total number of safe checks           : 17
Total number of definite unsafe checks: 1
Total number of warnings              : 0

The program is definitely UNSAFE

# Results
cap.f90: In function 'cap_':
cap.f90:12:1: error: division by zero
  y = y / (y - x)
^

Just out of curiosity, what is the report if you change β€œy = x” to β€œy = x + 0.1”? (I assume you can run the program - the prerequisites looked rather daunting, but I merely glanced at the list :slight_smile: )
And what happens if you do: y = x + 1.0e-10?
It does look interesting …

Hello, thank you for your interest. My static analysis tool, F-IKOS, is continuously evolving and offers various options to support different levels of analysis precision.

I have tried the test case you provided and here are the analysis results. As I am currently writing my master’s thesis, I will update my README.md for one-click installation once I’m finished.

Currently, F-IKOS can also analyze Fortran projects; below, I will provide a few examples.

Example 1: change β€œy = x” to β€œy = x + 0.1”

real function cap(x)
implicit none
real, intent(in) :: x
real :: y
y = x + 0.1
! Cap the value of y based on certain conditions
if (10.0 > y) then
  y = 10.0
else if (15.0 < y) then
  y = 20.0
else
  y = y / (y - x)
end if
cap = y
end function cap

program main
implicit none
real,external :: cap
real :: a
real :: x
x = 13.3
! Cap the value of x by calling the cap function
a = cap(x)
end program main

Output

$ ikos hello.ll --entry-point=MAIN_ -a='*,-sound,-upa' -fpd=apron-polka-polyhedra-f
[*] Running ikos preprocessor
[*] Running ikos analyzer
[*] Translating LLVM bitcode to AR
[*] Running liveness analysis
[*] Running widening hint analysis
[*] Running interprocedural value analysis
[*] Analyzing entry point 'MAIN_'
[*] Checking properties for entry point 'MAIN_'

# Time stats:
ikos-analyzer: 0.010 sec
ikos-pp      : 0.007 sec

# Summary:
Total number of checks                : 19
Total number of unreachable checks    : 0
Total number of safe checks           : 19
Total number of definite unsafe checks: 0
Total number of warnings              : 0

The program is SAFE

# Results
No entries.

Example 2: change β€œy = x” to β€œy = x + 1.0e-10”

real function cap(x)
implicit none
real, intent(in) :: x
real :: y
y = x + 1.0e-10
! Cap the value of y based on certain conditions
if (10.0 > y) then
  y = 10.0
else if (15.0 < y) then
  y = 20.0
else
  y = y / (y - x)
end if
cap = y
end function cap

program main
implicit none
real,external :: cap
real :: a
real :: x
x = 13.3
! Cap the value of x by calling the cap function
a = cap(x)
end program main

Output

$ ikos hello.ll --entry-point=MAIN_ -a='*,-sound,-upa' -fpd=apron-polka-polyhedra-f
[*] Running ikos preprocessor
[*] Running ikos analyzer
[*] Translating LLVM bitcode to AR
[*] Running liveness analysis
[*] Running widening hint analysis
[*] Running interprocedural value analysis
[*] Analyzing entry point 'MAIN_'
[*] Checking properties for entry point 'MAIN_'

# Time stats:
ikos-analyzer: 0.011 sec
ikos-pp      : 0.007 sec

# Summary:
Total number of checks                : 19
Total number of unreachable checks    : 0
Total number of safe checks           : 18
Total number of definite unsafe checks: 0
Total number of warnings              : 1

The program is potentially UNSAFE

# Results
hello.f90: In function 'cap_':
hello.f90:12:1: warning: divisor might be zero ()
  y = y / (y - x)
^

Example 3: Analyze runtime errors in Fortran project (this is preliminary work)
Structure of project

$ tree ./
./
β”œβ”€β”€ configure
β”œβ”€β”€ include
β”‚   └── math_operations.h
β”œβ”€β”€ main.f90
β”œβ”€β”€ Makefile
└── math_operations.f90

1 directory, 5 files

Use f-ikos to detect runtime errors

$ ikos-scan ./configure 
Nothing to analyze.

$ ikos-scan make
ikos-scan-fc -I./include -c main.f90 -o main.o
clang-14: warning: argument unused during compilation: '-Xflang -disable-O0-optnone' [-Wunused-command-line-argument]
ikos-scan-fc -I./include -c math_operations.f90 -o math_operations.o
clang-14: warning: argument unused during compilation: '-Xflang -disable-O0-optnone' [-Wunused-command-line-argument]
ikos-scan-fc main.o math_operations.o -o my_program
Analyze my_program? [Y/n] n

New structure of project: files produced by frontend β€˜Flang’

$ tree ./
./
β”œβ”€β”€ configure
β”œβ”€β”€ include
β”‚   └── math_operations.h
β”œβ”€β”€ main.f90
β”œβ”€β”€ main.o
β”œβ”€β”€ main.o.bc
β”œβ”€β”€ Makefile
β”œβ”€β”€ math_operations.f90
β”œβ”€β”€ math_operations.mod
β”œβ”€β”€ math_operations.o
β”œβ”€β”€ math_operations.o.bc
β”œβ”€β”€ my_program
└── my_program.bc

1 directory, 12 files

Begin to analyze all files, and the output shows that

$ ikos main.o.bc --entry-point=MAIN_ -fpd=apron-polka-polyhedra-f -a='*,-sound,-upa'
[*] Running ikos preprocessor
[*] Running ikos analyzer
[*] Translating LLVM bitcode to AR
[*] Running liveness analysis
[*] Running widening hint analysis
[*] Running interprocedural value analysis
[*] Analyzing entry point 'MAIN_'
[*] Checking properties for entry point 'MAIN_'

# Time stats:
ikos-analyzer: 0.010 sec
ikos-pp      : 0.009 sec

# Summary:
Total number of checks                : 24
Total number of unreachable checks    : 5
Total number of safe checks           : 18
Total number of definite unsafe checks: 1
Total number of warnings              : 0

The program is definitely UNSAFE

# Results
main.f90: In function 'MAIN_':
main.f90:18:1: error: division by zero
    r = c / d

3 Likes

Thanks for your answer. I will have to get a closer look at the results :). However, the article that describes F-IKOS gave rise to a few questions as well:

  • While complex numbers are - from a porgramming point of view - β€œjust” combinations of two real numbers, the article does not mention them at all. Does F-IKOS handle these?
  • On page 31 I found the statement β€œThe reason for these false positives lies in the differences between Fortran arrays and common high-level language arrays.” Could you explain that in some detail? Besides syntax (which should be solved prior to F-IKOS’s analysis) and the flexibility in indices I cannot think of any difference that comes into play.
  • In the past I have come across interval arithmetic as a means to analyse the accuracy of program results. One drawback was that these intervals would grow and grow during the course of the calculation and ultimately would lead to so large intervals that the result was meaningless. I guess that is different for static analyses?
  • Have you tried F-IKOS on such commonly used packages like BLAS and LAPACK and others/

Hello, We plan to publish another new paper in the coming months, conducting more experiments to showcase our latest achievements.

If you’re interested, please follow the F-IKOS GitHub repository f-ikos. We plan to release an easy-to-install and user-friendly version by July 2025. The installation instructions will be prioritized and updated as soon as possible. If you encounter any issues in the future, feel free to open an issue on GitHub.

  • This is a toy example that shows how to use our analyzer F-IKOS. This paper presents the preliminary work we have done, and we would like to carry out more experiments on Fortran programs.
  • Because we translate Fortran programs to LLVM IR, which may introduce more positive false. But we would like to try to reduce these alarms.
  • We haven’t tried BLAS and LAPACK, and need some time to empower our analyzer.
  • Interval arithmetic doesn’t consider relations between variables, we have used some techniques to consider relations between variables. Our analyzer has different analysis precision, which uses different techniques, such as interval arithmetic, affine arithmetic, and so on. We used different domains (interval, zonotope, octagon, polyhedra) that achieve this goal.
1 Like