2026-07-06ยท10 min readยทsota.io team

Deploy VeriFast to Europe โ€” Bart Jacobs ๐Ÿ‡ง๐Ÿ‡ช + KU Leuven (2008), the Separation Logic Verifier for C and Java with Symbolic Execution and Fractional Permissions, on EU Infrastructure in 2026

Verifying C and Java programs requires reasoning about heap aliasing. Two pointers may refer to the same memory location; a function may mutate data structures through a pointer that the caller still holds. Classic Hoare logic has no clean way to express "this function only modifies the subgraph it owns." Separation logic, introduced by John Reynolds and Peter O'Hearn in the early 2000s, solved this with a new connective: the separating conjunction P * Q asserts that P and Q hold for disjoint portions of the heap. VeriFast brings separation logic to practice.

VeriFast is a modular deductive verifier for C and Java programs, developed at KU Leuven ๐Ÿ‡ง๐Ÿ‡ช (Katholieke Universiteit Leuven) by Bart Jacobs and Frank Piessens, first presented at iFM 2008 (Integrated Formal Methods, Toulouse ๐Ÿ‡ซ๐Ÿ‡ท). VeriFast combines separation logic specifications with a symbolic execution engine: the verifier executes a symbolic program state through the code, consuming and producing heap predicates at each step, and emits proof obligations that an SMT solver (Z3) discharges automatically.

KU Leuven is one of Europe's oldest and most distinguished research universities โ€” founded in 1425 in Leuven, Belgium, it has been a centre of scientific excellence for six centuries. The VeriFast group works alongside Frank Piessens' security research team, which produced landmark work on Spectre and Meltdown CPU vulnerabilities. Both projects share the same institutional commitment: building trustworthy systems software on EU soil.

Specification Language โ€” Contract Comments

VeriFast specifications live in C and Java comments, invisible to the standard compiler but parsed by the VeriFast front-end. For C:

//@ requires integer(p, ?v) &*& integer(q, ?w);
//@ ensures  integer(p, w) &*& integer(q, v);
void swap(int *p, int *q)
{
  int tmp = *p;
  *p = *q;
  *q = tmp;
}

The ?v syntax introduces a pattern variable: "there exists some value v such that *p == v at entry." The &*& operator is the separating conjunction โ€” integer(p, v) &*& integer(q, w) asserts that p and q point to distinct integers with values v and w. The postcondition asserts the swap has occurred and the two permissions are returned.

For Java, specifications use /*@ ... @*/ blocks:

/*@ requires integer(p.value, ?v) &*& p != null;
  @ ensures  integer(p.value, v + 1);
  @*/
void increment(Counter p) {
    p.value++;
}

Heap Predicates

VeriFast defines several built-in predicates for common heap structures:

integer(p, v) โ€” pointer p holds the integer value v. Full (exclusive) ownership: reading and writing permitted.

// Reading requires and produces integer permission
int read(int *p)
//@ requires integer(p, ?v);
//@ ensures  integer(p, v) &*& result == v;
{ return *p; }

chars(p, n, cs) โ€” n characters starting at pointer p form the list cs. Used for string and byte-array reasoning.

void zero_fill(char *buf, int n)
//@ requires chars(buf, n, _);
//@ ensures  chars(buf, n, repeat('\0', n));
{ for (int i = 0; i < n; i++) buf[i] = '\0'; }

malloc_block(ptr, n) โ€” the heap block at ptr was allocated with size n and may be freed. VeriFast tracks allocation ownership statically โ€” free(ptr) requires malloc_block(ptr, n) &*& ... in the precondition, preventing double-free and use-after-free by proof.

int *alloc_int(int v)
//@ requires true;
//@ ensures  malloc_block(result, sizeof(int)) &*& integer(result, v);
{
  int *p = malloc(sizeof(int));
  //@ assume(p != 0);
  *p = v;
  return p;
}

Abstract Predicates โ€” open/close

User-defined predicates encapsulate heap invariants for data structures. A linked list node owns its data and the recursive tail:

/*@
predicate node(struct Node *n; int val, list<int> rest) =
  n != 0 &*& n->val |-> val &*& n->next |-> ?nxt &*&
  (nxt == 0 ? rest == nil : node(nxt, _, ?t) &*& rest == cons(_, t));
@*/

The open and close commands fold and unfold predicates during symbolic execution โ€” analogous to Viper's fold/unfold:

void push(struct Node **head, int v)
//@ requires *head |-> ?h &*& (h == 0 ? true : node(h, _, _));
//@ ensures  *head |-> ?newh &*& node(newh, v, _);
{
  struct Node *n = malloc(sizeof(struct Node));
  n->val = v;
  n->next = *head;
  *head = n;
  //@ close node(n, v, _);
}

Fractional Permissions โ€” Shared Read Access

VeriFast supports fractional permissions for concurrent read sharing. A fractional permission [1/2]integer(p, v) grants read-only access with half ownership โ€” two threads can each hold [1/2] for a total of [1/1] (full ownership):

// Reader: requires [1/2] permission, returns same fraction
int read_shared(int *p)
//@ requires [1/2]integer(p, ?v);
//@ ensures  [1/2]integer(p, v) &*& result == v;
{ return *p; }

// Writer: requires full [1/1] permission
void write_exclusive(int *p, int v)
//@ requires integer(p, _);
//@ ensures  integer(p, v);
{ *p = v; }

This models the standard reader/writer discipline: multiple readers can coexist (each holds a fraction), but a writer requires exclusive ownership (sum of all fractions = 1). The permission model prevents data races by proof โ€” no dynamic race detector, no runtime overhead.

Lemma Functions โ€” Ghost Code

Lemma functions contain ghost code: proof steps that have no runtime execution but establish logical facts used in verification. They allow inductive reasoning about recursive data structures:

/*@
lemma void list_length_nonneg(list<int> xs)
  requires true;
  ensures  length(xs) >= 0;
{
  switch (xs) {
    case nil: break;
    case cons(h, t): list_length_nonneg(t); break;
  }
}
@*/

Lemmas are verified against their own pre/postconditions. Calling a lemma in a proof context is safe because its correctness is machine-checked โ€” no axiom gaps. This allows complex data structure invariants (red-black trees, AVL trees, circular buffers) to be verified modularly.

Inductive Datatypes and Fixpoint Functions

VeriFast's ghost language includes ML-style inductive datatypes and fixpoint functions for pure recursive computation over heap structures:

/*@
inductive intlist = nil | cons(int, intlist);

fixpoint int sum(intlist xs) {
  switch (xs) {
    case nil: return 0;
    case cons(h, t): return h + sum(t);
  }
}

fixpoint intlist append(intlist xs, intlist ys) {
  switch (xs) {
    case nil: return ys;
    case cons(h, t): return cons(h, append(t, ys));
  }
}
@*/

These datatypes appear in predicate definitions and specifications, enabling fully verified algorithms over recursive structures โ€” linked lists, trees, graphs โ€” without approximation.

Java Verification

VeriFast supports Java programs with the same specification language adapted to object-oriented idioms. Class invariants, interface contracts, and inheritance are handled via Java-specific predicates:

/*@
predicate Counter_valid(Counter c; int v) =
  c.value |-> v &*& v >= 0;
@*/

class Counter {
  int value;

  /*@ requires Counter_valid(this, ?v);
    @ ensures  Counter_valid(this, v + 1);
    @*/
  void increment() {
    value++;
  }

  /*@ requires Counter_valid(this, ?v);
    @ ensures  Counter_valid(this, 0);
    @*/
  void reset() {
    value = 0;
  }
}

Java interfaces get verified contracts that all implementing classes must satisfy โ€” enabling compositional verification of object-oriented systems where implementations are verified independently of callers.

Industrial Applications โ€” Medical Devices and Automotive

VeriFast targets the safety-critical embedded software ecosystem where C dominates:

IEC 62304 (Medical Device Software) โ€” the EU Medical Device Regulation (MDR 2017/745) mandates lifecycle safety for software in Class IIb and III medical devices. VeriFast-verified C libraries for signal processing (ECG algorithms, insulin pump control, infusion pump logic) provide machine-checked freedom from memory errors โ€” zero null dereferences, zero buffer overflows, zero use-after-free โ€” as formal evidence for IEC 62304 compliance artifacts. Belgian medtech companies (e.g., Agfa HealthCare ๐Ÿ‡ง๐Ÿ‡ช, Materialise ๐Ÿ‡ง๐Ÿ‡ช) develop embedded C software on KU Leuven's doorstep.

AUTOSAR and ISO 26262 โ€” automotive Basic Software (BSW) modules written in AUTOSAR Classic C (MCAL layers, COM/RTE stacks) are natural VeriFast targets. ISO 26262 ASIL D demands exhaustive evidence for absence of systematic software faults; VeriFast separation logic proofs provide this evidence for memory safety properties โ€” pointer arithmetic, DMA buffer ownership, interrupt handler isolation โ€” that neither static analysis nor testing can exhaust.

IMEC / imec ๐Ÿ‡ง๐Ÿ‡ช (Holst Centre, Leuven) โ€” Europe's leading nanoelectronics research institute, adjacent to KU Leuven, develops C firmware for energy-harvesting sensor nodes, IoT edge processors, and medical implantables. VeriFast has been used in imec projects for verifying C-based protocol stacks on microcontrollers where heap usage must be precisely bounded.

EU Ecosystem Position

VeriFast occupies a distinctive position in the EU formal verification landscape:

ToolOriginLanguageApproach
VeriFastKU Leuven ๐Ÿ‡ง๐Ÿ‡ชC, JavaSeparation logic + symbolic execution
Frama-C/WPCEA/INRIA ๐Ÿ‡ซ๐Ÿ‡ทCACSL + weakest preconditions + Why3
KeYTU Darmstadt ๐Ÿ‡ฉ๐Ÿ‡ช + KIT ๐Ÿ‡ฉ๐Ÿ‡ชJavaDynamic Logic + sequent calculus
PrustiETH Zurich ๐Ÿ‡จ๐Ÿ‡ญRustViper/IDF + Silicon/Z3
GobraETH Zurich ๐Ÿ‡จ๐Ÿ‡ญGoViper/IDF + Silicon/Z3
NaginiETH Zurich ๐Ÿ‡จ๐Ÿ‡ญPythonViper/IDF + Silicon/Z3

VeriFast's separation logic approach directly inspired the Implicit Dynamic Frames (IDF) model used in Viper (ETH Zurich ๐Ÿ‡จ๐Ÿ‡ญ, VMCAI 2016) โ€” the infrastructure behind Prusti, Gobra, and Nagini. The conceptual lineage runs: Reynolds/O'Hearn separation logic โ†’ VeriFast (KU Leuven ๐Ÿ‡ง๐Ÿ‡ช, 2008) โ†’ Viper IDF (ETH Zurich ๐Ÿ‡จ๐Ÿ‡ญ, 2016) โ†’ Prusti/Gobra/Nagini front-ends. All EU institutions, all publicly funded, all building on each other's research.

EU Regulatory Alignment

EU AI Act Art. 9 (Technical Documentation for High-Risk Systems): VeriFast-verified C inference code (neural network forward passes, signal classifiers, medical decision support) provides machine-checked functional correctness certificates โ€” preconditions define valid input domains, postconditions bound output ranges, separation logic proofs guarantee memory isolation between patient data records.

EU AI Act Art. 10 (Data Governance): VeriFast separation logic proofs on C data processing pipelines demonstrate that memory regions containing personal health data are accessed only through verified accessors โ€” no pointer arithmetic bypasses the separation logic frame conditions.

GDPR Art. 25 (Data Protection by Design): malloc_block ownership tracking proves that dynamically allocated patient records are freed exactly once and not readable after deallocation โ€” no dangling pointer access to personal data is possible under the verified execution model.

Cyber Resilience Act (CRA, 2027): CRA Article 13 requires manufacturers of products with digital elements to document that products are designed and developed without known exploitable vulnerabilities. VeriFast proofs for C libraries provide formal evidence for memory safety (no buffer overflow, no use-after-free, no double-free) โ€” the root cause of the majority of CVEs in C-based embedded systems.

IEC 62304 Class C Software: VeriFast-verified C module test evidence complements unit tests for medical device software classification, satisfying the "software safety requirements specification" traceability requirement.

Deploy VeriFast on EU Infrastructure with sota.io

VeriFast runs on Java (JVM), requires no cloud connectivity during verification, and produces verification reports locally. Deploy a VeriFast-integrated C/Java CI pipeline on sota.io โ€” the EU-native PaaS on German infrastructure, GDPR-compliant by default, with managed PostgreSQL for storing verification audit trails:

# Install VeriFast
wget https://github.com/verifast/verifast/releases/latest/download/verifast-linux.tar.gz
tar xf verifast-linux.tar.gz
export PATH=$PATH:$(pwd)/verifast/bin

# Verify a C file
verifast -c mylib.c

# Verify all C files in project
find src/ -name "*.c" | xargs verifast -c

sota.io provides:

# sota.io deploy
sota deploy --region eu-central

Free tier available. No credit card required to start.

See Also