Deploy VerCors to Europe โ Marieke Huisman ๐ณ๐ฑ + University of Twente (2011), the Viper-Based Concurrent Program Verifier for Java, C, and OpenCL, on EU Infrastructure in 2026
Concurrent software is notoriously hard to verify. Race conditions, deadlocks, and atomicity violations surface at thread interleavings that neither testing nor single-threaded reasoning reaches. Formal verification of concurrent programs requires a permission model that tracks which thread owns which heap location at each program point โ and an encoding that discharges concurrent proof obligations automatically.
VerCors โ Verification of Concurrent and Distributed Systems โ is an open-source deductive program verifier developed at the University of Twente ๐ณ๐ฑ by Marieke Huisman and collaborators including Wytse Oortwijn, Pieter Bos, and Petra van den Bos, with a tool paper published at ICFEM 2017 (International Conference on Formal Engineering Methods). VerCors accepts annotated Java, C, and OpenCL programs, together with its own research language PVL (Prototypal Verification Language), and discharges proof obligations using Viper (ETH Zurich ๐จ๐ญ) as a backend via Silicon and Z3.
The result is a verifier that handles the full concurrency stack: sequential heap reasoning, multi-threaded Java programs with monitors and locks, parallel arrays with data races excluded by permissions, and OpenCL/CUDA GPU kernels with work-group isolation guarantees. All built on EU-native research infrastructure โ University of Twente (NWO-funded), ETH Zurich (SNSF-funded), with no US Cloud Act dependency.
Specification Language โ Annotated Java and C
VerCors specifications appear as structured comment annotations in the source language, requiring no separate specification file:
Java Method Contracts
class BankAccount {
int balance;
/*@
requires Perm(balance, 1);
ensures Perm(balance, 1);
ensures balance == \old(balance) + amount;
ensures balance >= 0;
@*/
void deposit(int amount) {
balance += amount;
}
/*@
requires Perm(balance, 1);
ensures Perm(balance, 1);
ensures balance == \old(balance) - amount;
context amount <= \old(balance);
@*/
void withdraw(int amount) {
balance -= amount;
}
}
Perm(x.f, p) is the VerCors notation for heap ownership: Perm(balance, 1) means full (exclusive) ownership of the balance field. \old(expr) refers to the pre-state value. context is shorthand for requires and ensures combined โ a permission that must be held before and after the method.
C Function Contracts
VerCors supports the same annotation style for C:
/*@
requires \pointer_block(arr, n);
ensures \pointer_block(arr, n);
ensures (\forall int i; 0 <= i && i < n; arr[i] >= 0);
@*/
void abs_array(int *arr, int n) {
/*@ loop_invariant \pointer_block(arr, n);
@ loop_invariant 0 <= i && i <= n;
@ loop_invariant (\forall int j; 0 <= j && j < i; arr[j] >= 0);
@*/
for (int i = 0; i < n; i++) {
if (arr[i] < 0) arr[i] = -arr[i];
}
}
\pointer_block(arr, n) asserts ownership of all n elements of the array. The loop_invariant annotation establishes the invariant that VerCors proves is maintained by each loop iteration.
Permission Model โ Viper IDF in Java and C
VerCors uses the same Implicit Dynamic Frames permission model as Viper, Prusti, Gobra, and Nagini, but exposes it through Java/C annotation syntax rather than Silver IL directly.
Fractional Permissions โ Shared Read Access
class Config {
int maxConnections;
/*@
requires Perm(maxConnections, 1\2);
ensures Perm(maxConnections, 1\2);
ensures \result == maxConnections;
@*/
int getMax() {
return maxConnections;
}
}
Perm(maxConnections, 1\2) โ a half-permission โ allows reading maxConnections but not writing it. Multiple threads can simultaneously hold half-permissions for the same field, enabling safe concurrent reads without requiring synchronisation. This is the same fractional permission arithmetic as VeriFast's [1/2]integer(p, v) and Viper's acc(x.f, 1/2).
Resource Invariants โ Predicate Abstractions
/*@
resource valid() = Perm(x, 1) ** Perm(y, 1) ** x + y == 100;
@*/
class Pair {
int x;
int y;
/*@
requires valid();
ensures valid();
ensures x == newX ** y == 100 - newX;
@*/
void setX(int newX) {
//@ unfold valid();
x = newX;
y = 100 - newX;
//@ fold valid();
}
}
resource defines a named permission predicate โ the VerCors equivalent of Viper's predicate. ** is separating conjunction: both Perm(x, 1) and Perm(y, 1) are required simultaneously, and their conjunction also asserts the invariant x + y == 100. unfold/fold make the predicate transparent at the verification point where structural reasoning is needed.
Concurrent Verification โ Threads, Locks, and Atomics
VerCors's primary strength is verifying concurrent programs. The permission model precisely tracks heap ownership transfer between threads, making data races statically impossible under the verified execution model.
Thread Fork/Join
class Worker implements Runnable {
int[] data;
int result;
/*@
context Perm(result, 1);
context (\forall* int i; 0 <= i && i < data.length; Perm(data[i], 1\2));
ensures result == (\sum int i; 0 <= i && i < data.length; data[i]);
@*/
public void run() {
result = 0;
for (int i = 0; i < data.length; i++) {
result += data[i];
}
}
}
class Main {
/*@
requires (\forall* int i; 0 <= i && i < arr.length; Perm(arr[i], 1));
ensures (\forall* int i; 0 <= i && i < arr.length; Perm(arr[i], 1));
@*/
static int parallelSum(int[] arr) {
Worker w = new Worker();
w.data = arr;
//@ share w.result; // transfer full permission to new thread
Thread t = new Thread(w);
t.start();
t.join();
//@ unshare w.result; // reclaim permission after join
return w.result;
}
}
(\forall* int i; ... ; Perm(arr[i], 1\2)) is an iterated separating conjunction over the array โ each element has its own independent half-permission. share/unshare are permission-transfer ghost annotations: the forking thread gives away write permission, the joining thread reclaims it. Between start() and join(), the main thread provably cannot access w.result โ the permission is held by the worker thread.
Lock Invariants
/*@
given resource lock_invariant() = Perm(count, 1) ** count >= 0;
@*/
class Counter {
int count;
Object lock;
/*@
requires held(lock);
ensures held(lock);
ensures count == \old(count) + 1;
@*/
void increment() {
//@ acquire lock;
count++;
//@ release lock;
}
}
Lock invariants specify what heap state is protected by a given lock object. held(lock) in the contract means the calling thread holds the lock. acquire/release ghost annotations transfer heap ownership between the thread and the lock invariant โ acquiring the lock gives the thread access to Perm(count, 1), releasing it hands ownership back to the invariant.
OpenCL Kernel Verification
VerCors extends its permission model to OpenCL GPU kernels โ a unique capability among EU formal verification tools:
/*@
context_everywhere \ltid < 256;
requires Perm(input[\gtid], 1\2);
requires Perm(output[\gtid], 1);
ensures Perm(input[\gtid], 1\2);
ensures Perm(output[\gtid], 1);
ensures output[\gtid] == input[\gtid] * 2;
@*/
__kernel void scale(
__global int* input,
__global int* output
) {
int id = get_global_id(0);
output[id] = input[id] * 2;
}
\gtid is the global thread ID, \ltid the local thread ID within a work-group. The permission Perm(input[\gtid], 1\2) โ a half-permission on the thread's own input element โ statically prevents any kernel from writing another thread's input slot. VerCors verifies the absence of data races across the entire work-group without requiring dynamic race detection.
This makes VerCors the only EU-native verifier targeting GPU/accelerator code โ directly relevant to HPC and AI workloads under the EU AI Act's high-risk system requirements.
Prototypal Verification Language (PVL)
For research and teaching, VerCors includes PVL โ a minimal imperative language with first-class verification constructs:
class Stack {
seq<int> elements;
resource inv() = Perm(elements, 1);
requires inv();
ensures inv();
ensures |elements| == \old(|elements|) + 1;
ensures elements[|elements|-1] == v;
void push(int v) {
unfold inv();
elements = elements + [v];
fold inv();
}
requires inv();
requires |elements| > 0;
ensures inv();
ensures |elements| == \old(|elements|) - 1;
int pop() {
unfold inv();
int result = elements[|elements|-1];
elements = elements[..|elements|-1];
fold inv();
return result;
}
}
PVL uses seq<T> (mathematical sequences), |elements| (length), and slice notation elements[..n] โ pure functional data structures that make postconditions straightforward to state and verify. PVL programs are not compiled to machine code; they exist solely for verification research and course exercises.
Industrial Applications โ Dutch High-Tech
The University of Twente is located in Enschede, embedded in the eastern Netherlands high-tech corridor. VerCors targets the verification needs of Dutch and European industrial partners:
ASML ๐ณ๐ฑ (Veldhoven) โ the world's only supplier of EUV lithography machines, used in every advanced semiconductor fab globally. ASML's embedded software controls nanometre-precision optical systems under hard real-time constraints. VerCors has been used in ASML-adjacent research for verifying concurrent Java middleware in lithography control systems โ where a race condition in exposure sequencing cannot be discovered by testing and must be excluded formally.
NXP Semiconductors ๐ณ๐ฑ (Eindhoven) โ NXP develops automotive microcontrollers (S32K series, i.MX RT) where AUTOSAR Classic C software runs concurrent tasks on multicore hardware under ISO 26262 ASIL D. VerCors C contract verification directly targets this domain.
Philips Healthcare ๐ณ๐ฑ (Best) โ medical imaging systems (MRI, CT, ultrasound) run concurrent Java pipelines for signal reconstruction. IEC 62304 Class C demands software lifecycle evidence; VerCors thread-safety proofs for Java imaging pipelines provide formal evidence complementing unit tests.
EU Funding and Institutional Context
University of Twente (Enschede, founded 1961) โ the Netherlands' only campus university, located 20 km from the German border in the Twente technology region. The Software Engineering group (led by Marieke Huisman) holds a chair in Formal Methods for Parallel Programming. VerCors development has been funded by:
- NWO (Dutch Research Council) โ national science foundation funding the VerCors core tool
- EU Horizon 2020 / EuroHPC โ concurrent and distributed verification research
- VICI grant โ Marieke Huisman's personal research program on concurrent program verification
- TU Eindhoven collaboration โ mCRL2 process algebra group, shared verification ecosystem
TU Twente formal methods lineage: Ed Brinksma (E-LOTOS, ISO 15437) โ Jan Tretmans (ioco conformance testing, TorX/JTorX) โ Marieke Huisman (VerCors concurrent verification). The same institution contributed E-LOTOS to the ISO process algebra standardisation and now leads concurrent program verification for industrial-scale Java.
EU Ecosystem Position โ Viper Front-End Cluster
VerCors is the fifth major Viper front-end in the EU formal methods cluster, alongside Prusti (Rust), Gobra (Go), Nagini (Python), and VeriFast (C/Java). But VerCors adds a dimension the others do not cover: multi-language concurrent verification and GPU kernel contracts.
| Tool | Origin | Language | Concurrency |
|---|---|---|---|
| VerCors | University of Twente ๐ณ๐ฑ | Java, C, OpenCL | Threads, locks, atomics, GPU |
| Prusti | ETH Zurich ๐จ๐ญ | Rust | Ownership (sequential) |
| Gobra | ETH Zurich ๐จ๐ญ | Go | Goroutines, channels |
| Nagini | ETH Zurich ๐จ๐ญ | Python | Lock/Thread annotations |
| VeriFast | KU Leuven ๐ง๐ช | C, Java | Fractional permissions |
| Viper | ETH Zurich ๐จ๐ญ | Silver IL | Backend IVL |
The geographic spread: Netherlands ๐ณ๐ฑ + Switzerland ๐จ๐ญ + Belgium ๐ง๐ช โ three EU/EFTA countries, all with NWO/SNSF/FWO public science funding, none subject to US Cloud Act. The entire Viper front-end ecosystem is EU-native.
EU Regulatory Alignment
EU AI Act Art. 9 (High-Risk System Technical Documentation): VerCors thread-safety proofs for Java AI inference pipelines (concurrent prediction servers, shared model state) demonstrate that concurrent data access to model weights and patient records is governed by verified lock invariants โ not just by tests that cannot exhaustively cover thread interleavings.
EU AI Act Art. 10 (Data Governance for High-Risk Systems): VerCors permission proofs for concurrent ETL pipelines show that personal data flowing through parallel Java processing stages is not aliased between threads โ each thread owns its exclusive slice of the data, preventing unauthorised sharing across processing boundaries.
GDPR Art. 25 (Data Protection by Design): Iterated separating conjunctions over patient record arrays โ (\forall* int i; 0 <= i && i < records.length; Perm(records[i], 1)) โ formally encode that no two concurrent threads can simultaneously access the same patient record. This is data protection by design expressed as a machine-checked formal proof.
IEC 61508 SIL 3/4 (Functional Safety of E/E/PE Systems): Concurrent safety-critical software (reactor control, railway interlocking, industrial robot coordination) runs on multicore hardware where RTOS scheduling creates thread-interleaving non-determinism. VerCors lock invariant verification eliminates the class of concurrent faults that sequential analysis misses.
NIS2 Directive (Network and Information Security): Network-facing concurrent Java services (REST APIs, WebSocket handlers, concurrent message processors) are primary NIS2 targets. VerCors permission-based thread isolation proofs demonstrate that concurrent request handlers cannot corrupt shared session state โ addressing the class of concurrency vulnerabilities (TOCTOU, broken access control under race conditions) that NIS2 Article 21 mandates be systematically addressed.
Deploy VerCors on EU Infrastructure with sota.io
VerCors runs as a self-contained JVM tool with no external cloud dependencies โ verification happens locally against the Z3 SMT solver. Deploy a VerCors-integrated Java CI pipeline on sota.io โ the EU-native PaaS on German infrastructure, GDPR-compliant by default:
# Install VerCors (requires JDK 17+)
wget https://github.com/utwente-fmt/vercors/releases/latest/download/vercors.zip
unzip vercors.zip
export PATH=$PATH:$(pwd)/vercors/bin
# Verify a Java file
vct --silicon BankAccount.java
# Verify a C file with Silicon backend
vct --silicon abs_array.c
# Verify an OpenCL kernel
vct --silicon scale_kernel.cl
--silicon selects the Viper Silicon backend (symbolic execution + Z3). --carbon selects the Carbon backend (VCGen + Boogie + Z3) โ the same two backends as all other Viper front-ends.
sota.io provides:
- EU data residency โ VerCors verification results, proof statistics, and audit trails stay in Germany. No US Cloud Act exposure for ASML, NXP, or Philips Healthcare source code.
- Managed PostgreSQL โ store verification history, proof obligation counts, and correctness evidence per commit โ traceable for IEC 62304 / IEC 61508 compliance artifacts.
- Zero DevOps โ push your VerCors CI container and sota.io handles deployment, scaling, and database backups.
- GDPR compliance โ data processed in EU jurisdiction. Medical and industrial source code never leaves European infrastructure.
# sota.io deploy
sota deploy --region eu-central
Free tier available. No credit card required to start.
See Also
- Deploy Viper to Europe โ โ Permission-based IVL (ETH Zurich ๐จ๐ญ), the backend powering Prusti, Gobra, Nagini, and VerCors
- Deploy Prusti to Europe โ โ Viper-based Rust verifier (ETH Zurich ๐จ๐ญ), sequential ownership verification
- Deploy Gobra to Europe โ โ Viper-based Go verifier (ETH Zurich ๐จ๐ญ), goroutine/channel permission transfer
- Deploy Nagini to Europe โ โ Viper-based Python verifier (ETH Zurich ๐จ๐ญ), thread safety via Lock/Thread annotations
- Deploy VeriFast to Europe โ โ Separation logic C/Java verifier (KU Leuven ๐ง๐ช), fractional permissions
- Deploy E-LOTOS to Europe โ โ ISO process algebra (University of Twente ๐ณ๐ฑ), predecessor to VerCors's home institution's formal methods tradition