19CSE205 Program Reasoning Lab
FRAMA-C
Frama-C = Framework for Modular Analysis of C Programs
• Frama-C is a platform dedicated to the analysis of
C programs
It is a collection of plug-ins that perform a variety of
static program analysis, e.g., program slicing, impact
analysis and so on.
One such plug-in is WP, for weakest preconditions.
In order to enhance automated verification, Frama-C
can make use of a variety of theorem provers:
Alt-Ergo, QED, Coq, Why3 …
Frama-C Installation
The preferred method of installation for Frama-C is using
OPAM (v1.2 or newer).
First you need to install OPAM, then you may install Frama-C using
OPAM:
opam install frama-c
Note: make sure your OPAM version is >= 1.2.
Frama-C Requirements
• OCaml 4.xx (incompatible with versions 4.02.2, 4.02.0 and
4.00.0)
• A C compiler (gcc, clang, CompCert, etc.)
• GNU Make
Installing OPAM
Several Linux distributions already include an opam package.
A Windows OPAM is currently being developed, but it is not yet
stable.
If your system does not have an OPAM package, you can compile it
from source, or use the provided OPAM binaries available at:
http://opam.ocaml.org/doc/Install.html
Installing Frama-C from OPAM
There are two Frama-C packages in OPAM:
• frama-c-base: minimal Frama-C installation, without GUI;
few dependencies
• frama-c: includes all GUI-related dependencies, plus other
recommended packages.
The frama-c package recommends the installation of optional
packages, e.g.
external provers for WP, such as why3 and coq.
To install frama-c, you may need to install Gtk, GtkSourceView
and GnomeCanvas separately.
These are C libraries with OCaml bindings used by the GUI.
To get the exact list of packages that are needed, use:
opam install depext
opam depext frama-c
and install the packages listed as missing.
Once everything is ready.
1) Use an editor (vi or gedit) to type the program and save the file with .c
extension.
2) Use either gui mode or command prompt mode to run your program
using Frama-c
Commands:
frama-c -wp filename.c
frama-c-gui -wp filename.c
frama-c -wp -rte filename.c
wp - weakest precondition, rte – runtime environment
3) Results
Proved Goal
Sample programs:
1) Maximum function with postcondition
//max.c
/*@ ensures \result == a && \result > b
|| \result ==b && \result > a
|| \result == a && \result == b;
*/
int max(int a, int b)
{
return a > b ? a : b ;
}
2) Maximum function with precondition and
postcondition
//max.c
/*@ requires a != b;
ensures \result == a && \result > b
|| \result ==b && \result > a;
*/
int max(int a, int b)
{
return a > b ? a : b ;
}
3) Increment function with precondition and
postcondition.
/*@ requires a > 0;
ensures \result > 1;
*/
int incr(int a)
{
return ++a;
}
4) Increment function with precondition and
postcondition.
/*@ requires a > 0 && a < 100000;
ensures \result > 1;
*/
int incr(int a)
{
return ++a;
}
5) Swap function with postcondition
/*@
ensures a == \old(b) && b == \old(a);
*/
void swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
}
Result: will not prove the goal as a and b are
local.
6) Swap function using references with
postcondition
/*@
ensures *a == \old(*b) && *b == \old(*a);
*/
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
Results: will prove the goal
Runtime goals will not be satisfied
7) To compute the absolute value without arithmetic overflow.
Include precondition and postcondition.
8) Absolute value with different input
10) Absolute value with postcondition
11) Sum of first n numbers using while loop with
precondition and postcondition
#include <stdio.h>
/*@
requires n >= 1;
ensures \result == n*(n+1)/2;
assigns \nothing ;
*/
int sum(int n) {
int s = 0;
int i = 1;
/*@
loop invariant s == i*(i-1)/2 &&
1 <= i <= n+1;
loop assigns i, s;
*/
while (i<=n) {
s = s + i;
i = i + 1;
}
return s;
}
12) Compute the factorial
#include <stdio.h>
/*@
axiomatic Factorial {
logic integer fact(integer n);
axiom case_n:
\forall integer n;
n >= 1 ==> fact(n) == n*fact(n-1);
axiom case_0:
fact(0) == 1;
}
*/
/*@
requires n >= 0;
ensures \result == fact(n);
assigns \nothing ;
*/
int factorial(int n) {
int i = 1;
int f = 1;
/*@
loop invariant f == fact(i-1);
loop invariant 0 < i;
loop invariant i <= n+1;
loop assigns i, f; // other variables are
invariant
*/
while (i <= n) {
f = f * i;
i = i + 1;
}
return f;
}
13) To compute the GCD of two numbers
#include <stdio.h>
/*@
axiomatic GCD {
logic integer Gcd(integer p, integer q);
axiom Gcd1:
\forall integer m, n;
m > n ==> Gcd(m,n) == Gcd(m-n, n);
axiom Gcd2:
\forall integer m, n;
n > m ==> Gcd(m,n) == Gcd(m, n-m);
axiom Gcd3:
\forall integer m, n;
m == n ==> Gcd(m,n) == m;
}
*/
/*@
requires p >= 1;
requires p >= 1;
ensures \result == Gcd(\old(p), \old(q));
assigns \nothing;
*/
int gcd(int p, int q) {
/*@ loop invariant Gcd(p,q) ==
Gcd(\at(p,Pre), \at(q,Pre));
loop assigns p, q;
*/
while (p != q) {
if (p > q)
p = p - q;
if (q > p)
q = q - p;
}
return p;
}