Several software systems are polyglot; that is, they comprise programs implemented in a combination of programming languages. Verifiers that directly run on mainstream programming languages are currently customized for single languages. Thus, to verify polyglot systems, one usually translates them into a common verification language or formalism on which the verifier runs. In this paper, we present an alternative approach, PolyVer, which employs abstraction, compositional reasoning, and synthesis to directly perform polyglot verification. PolyVer constructs a formal model of the original polyglot system as a transition system where the update functions associated with transitions are implemented in target languages such as C or Rust. To perform verification, PolyVer then connects a model checker for transition systems with language-specific verifiers (e.g., for C or Rust) using pre/post-condition contracts for the update functions. These contracts are automatically generated by synthesis oracles based on syntax-guided synthesis or large language models (LLMs), and checked by the language-specific verifiers. The contracts form abstractions of the update functions using which the model checker verifies the overall system-level property on the polyglot system model. PolyVer iterates between counterexample-guided abstraction-refinement (CEGAR) and counterexample-guided inductive synthesis (CEGIS) until the property is verified or a true system-level counterexample is found. We demonstrate the utility of PolyVer for verifying programs in the Lingua Franca polyglot language using the UCLID5 model checker connected with the CBMC and Kani verifiers for C and Rust respectively.
- ID Articolo: 2503.03207
- Titolo: PolyVer: A Compositional Approach for Polyglot System Modeling and Verification
- Autori: Pei-Wei Chen, Shaokai Lin, Adwait Godbole, Ramneet Singh, Elizabeth Polgreen, Edward A. Lee, Sanjit A. Seshia
- Classificazione: cs.PL (Linguaggi di Programmazione)
- Data di Pubblicazione/Conferenza: Formal Methods in Computer-Aided Design 2025
- Link Articolo: https://arxiv.org/abs/2503.03207
I sistemi software poliglotta (polyglot systems) sono composti da programmi implementati in molteplici linguaggi di programmazione, tuttavia i verificatori di programmi esistenti sono tipicamente personalizzati per un singolo linguaggio. Per verificare sistemi poliglotta, è generalmente necessario tradurli in un linguaggio di verifica comune o in una rappresentazione formale. Questo articolo propone PolyVer, un approccio alternativo che esegue la verifica poliglotta direttamente utilizzando tecniche di astrazione, ragionamento composizionale e sintesi. PolyVer modella sistemi poliglotta come modelli formali di sistemi di transizione, dove le funzioni di aggiornamento relative alle transizioni sono implementate nel linguaggio target (come C o Rust). Per eseguire la verifica, PolyVer connette il model checker del sistema di transizione con verificatori specifici del linguaggio attraverso contratti di precondizione/postcondizione delle funzioni di aggiornamento. Questi contratti vengono generati automaticamente tramite sintesi guidata dalla sintassi o oracoli di sintesi basati su modelli linguistici di grandi dimensioni, e verificati dai verificatori specifici del linguaggio.
I sistemi software moderni adottano sempre più frequentemente architetture poliglotta, come i framework ROS2 e Lingua Franca che consentono agli sviluppatori di scegliere il linguaggio di programmazione più appropriato per ciascun componente. Tuttavia, questa flessibilità introduce sfide di verifica:
- Differenze Semantiche tra Linguaggi: Diversi linguaggi di programmazione possiedono sintassi e semantica differenti, come la funzione
saturating_add di Rust che satura al valore massimo in caso di overflow, mentre l'addizione in C può causare wrapping. - Limitazioni dei Verificatori Esistenti: La maggior parte dei verificatori di programmi (come CBMC per C, Kani per Rust) sono progettati specificamente per un singolo linguaggio e non possono gestire direttamente sistemi poliglotta.
- Complessità della Traduzione: Tradurre un intero sistema poliglotta in un singolo linguaggio di verifica richiede il supporto della sintassi e della semantica complete di tutti i linguaggi, il che è proibitivo per i linguaggi moderni.
La crescente complessità dei sistemi poliglotta aumenta il rischio di difetti software, e nei settori critici per la sicurezza (come i veicoli autonomi e l'aerospaziale), è necessaria la verifica formale per fornire garanzie forti, piuttosto che affidarsi esclusivamente a metodi incompleti come i test.
- Metodi di Traduzione Monolitica: Richiedono lo sviluppo di un'infrastruttura compilatore completa per ogni linguaggio
- Difficoltà nel Preservare la Semantica: È difficile catturare fedelmente tutte le costruzioni specifiche del linguaggio sorgente nel linguaggio di verifica target
- Problemi di Scalabilità: I problemi di verifica generati possono diventare eccessivamente grandi
- Formalizzazione del Problema di Verifica Poliglotta: Formalizzazione sistematica per la prima volta del problema di verifica poliglotta, con proposta di una soluzione composizionale che integra molteplici verificatori specifici del linguaggio.
- Sintesi Automatica di Contratti: Proposta di un metodo automatico per la sintesi e il raffinamento di contratti di precondizione/postcondizione utilizzando un linguaggio intermedio e cicli CEGIS-CEGAR, con supporto per sintesi guidata dalla sintassi e oracoli di sintesi basati su modelli linguistici di grandi dimensioni.
- Implementazione dello Strumento: Implementazione dello strumento PolyVer basato su UCLID5, con supporto per C e Rust attraverso i verificatori CBMC e Kani, dimostrando che gli oracoli di sintesi basati su LLM superano i metodi di sintesi puramente simbolici.
- Studi di Caso e Valutazione: Sviluppo di un verificatore per il linguaggio di coordinamento Lingua Franca, verifica di sistemi poliglotta contenenti processi C e Rust, nonché frammenti di linguaggio C non supportati da lavori precedenti.
Input: Modello poliglotta M = (Q,V,I₀,T,F) e proprietà del sistema φ
Output: Risultato di verifica (pass/fail) e possibile traccia di controsempio
Obiettivo: Determinare se M ⊨ φ è valido
Dove:
- Q: Insieme di stati
- V: Insieme di variabili tipizzate
- I₀: Insieme di stati iniziali
- T: Insieme di transizioni di stato
- F: Insieme di procedure
PolyVer modella sistemi poliglotta come macchine a stati estese, dove:
- Gli stati sono composti da stati e assegnazioni di variabili
- Le transizioni sono associate a condizioni di guardia e relazioni di aggiornamento
- Le relazioni di aggiornamento sono specializzate in sequenze di chiamate di procedure
L'innovazione chiave è l'introduzione del linguaggio intermedio L* come "collante" tra diversi linguaggi:
- I contratti sono scritti in L*
- Vengono trasformati in linguaggi concreti attraverso la compilazione semantica-preservante compL
- Evita la complessità della traduzione completa del linguaggio
Il nucleo dell'algoritmo è un ciclo iterativo a due livelli:
Ciclo CEGAR Esterno:
- Costruisce un modello astratto M' utilizzando i contratti correnti
- Il model checker verifica M' ⊨ φ
- Se fallisce, controlla se il controsempio è spurio
- Se spurio, raffina il contratto; altrimenti segnala il controsempio reale
Ciclo CEGIS Interno:
- L'oracolo di sintesi genera contratti candidati
- Il verificatore di oracolo controlla la validità del contratto
- Se non valido, aggiunge esempi positivi e risintesi
A differenza della traduzione monolitica, PolyVer adotta una strategia "divide et impera":
- Utilizza contratti per astrarre procedure individuali
- I verificatori specifici del linguaggio verificano la validità dei contratti
- Il model checker verifica le proprietà a livello di sistema
Supporta molteplici oracoli di sintesi:
- Sintetizzatore Basato su LLM: Utilizza prompt con catena di pensiero e DSL Python
- Sintetizzatore SyGuS/SyMO: Codifica il problema come problema di programmazione per esempi
Controlla la raggiungibilità della traccia di controsempio verificando {V = d} C {V' ≠ d'}, distinguendo tra controsempi reali e spuri.
- Benchmark LFVerifier: 22 programmi Lingua Franca con sintassi C limitata
- Esempi LF Completi: Controllore LED, robot arrampicatore, controllore di assetto satellitare e altri sistemi embedded
- Sistemi Poliglotta: Programmi LF misti C/Rust, applicazioni ROS2, programmi con chiamate FFI
- Numero di iterazioni di sintesi (IS: iterazioni CEGIS, AR: iterazioni CEGAR)
- Tempo di esecuzione (SOT: tempo oracolo di sintesi, VOT: tempo verificatore oracolo, UT: tempo UCLID5)
- Tasso di successo della verifica
Confronto con LFVerifier15, l'unico strumento noto per la verifica automatica end-to-end di programmi LF.
- Utilizzo di OpenAI o1-mini come sintetizzatore LLM, con 3 query parallele per procedura
- CBMC-6.3.1, Kani-0.56.0, z3-4.8.7 come backend di verifica
- Macchina Intel Core i9 a 3.7GHz con 62GB RAM
Su 22 benchmark:
- PolyVer verifica con successo tutti i benchmark, mentre LFVerifier non riesce a verificare l'esempio TrafficLight
- 18 benchmark sintetizzano correttamente i contratti in un singolo ciclo CEGIS, con tempo medio di 37 secondi
- Sebbene il tempo di esecuzione totale sia più lento (principalmente dominato dal tempo di sintesi dei contratti), fornisce miglioramenti qualitativi significativi
Verifica con successo sistemi embedded contenenti codice C completo:
- Controllore LED: 1 procedura, 123 righe di codice C, 31.0 secondi di tempo di sintesi
- Robot Arrampicatore: 12 procedure, 75 righe di codice C/Rust, 685.4 secondi di tempo di sintesi
- Controllore Satellitare: 6 procedure, 424 righe di codice C, 729.0 secondi di tempo di sintesi
Verifica di veri sistemi poliglotta:
- Programmi LF misti C/Rust
- Applicazioni di servizi ROS2
- Programmi con chiamate FFI tra linguaggi
- LLM Superiore ai Metodi Simbolici: I risolutori SyGuS/SyMO richiedono numerose iterazioni CEGAR e spesso non terminano
- Sfide nella Sintesi di Contratti: Le procedure con flusso di controllo complesso e dipendenze di dati richiedono più iterazioni
- Verifica Pratica: Capace di gestire codice implementativo reale piuttosto che esempi giocattolo
- Metodi di Traduzione Manuale: Cook et al. traducono codice assembly in C per verificare l'hypervisor Xen
- Traduzione Automatica di Frammenti: LFVerifier traduce automaticamente frammenti C in linguaggio di verifica
- Metodi Black-Box: Inferiscono riassunti dal comportamento di input-output
- La verifica composizionale basata sulla logica di Hoare è ampiamente applicata a programmi monolingue su larga scala
- Utilizza interpretazione astratta e CEGAR per automatizzare l'apprendimento di precondizioni/postcondizioni
- Metodi di inferenza di contratti guidati da proprietà
- Risolutori di clausole Horn vincolate
- Applicazioni recenti di LLM nell'apprendimento di specifiche
- PolyVer risolve con successo le sfide chiave della verifica di sistemi poliglotta
- L'approccio composizionale evita la complessità della traduzione completa del linguaggio
- La sintesi automatica di contratti rende il metodo pratico
- Gli oracoli di sintesi basati su LLM superano i metodi simbolici tradizionali
- Terminazione: L'algoritmo non garantisce la terminazione, dipendendo dalla qualità dell'oracolo di sintesi
- Supporto Linguistico: Attualmente supporta solo C e Rust, richiedendo lo sviluppo di oracoli di verifica per altri linguaggi
- Espressività dei Contratti: L'espressività del linguaggio intermedio L* limita la complessità delle proprietà verificabili
- Scalabilità: Il tempo di sintesi dei contratti per sistemi di grandi dimensioni potrebbe diventare un collo di bottiglia
- Estensione a altri sistemi software distribuiti poliglotta e sistemi robotici
- Applicazione alla verifica formale della traduzione di codice (come la traduzione da C a Rust)
- Miglioramento dell'efficienza e dell'accuratezza della sintesi di contratti
- Supporto per proprietà di logica temporale più complesse
- Importanza del Problema: La verifica di sistemi poliglotta è un problema pratico e importante
- Innovazione del Metodo: La combinazione di verifica composizionale e sintesi automatica di contratti è innovativa
- Fondamenti Teorici: Definizioni formali chiare e garanzie di correttezza esplicite
- Valore Pratico: Capace di gestire sistemi reali piuttosto che esempi giocattolo
- Implementazione dello Strumento: Fornisce un'implementazione dello strumento utilizzabile
- Overhead di Prestazioni: Il tempo di sintesi dei contratti è considerevole, potendo limitare l'applicazione pratica
- Copertura Linguistica: Attualmente supporta solo C e Rust, con estensibilità ancora da verificare
- Benchmark Limitati: Sebbene includa esempi reali, la scala è relativamente piccola
- Dipendenza da LLM: Dipende da servizi LLM commerciali, potendo influenzare la riproducibilità
- Contributo Accademico: Apre una nuova direzione di ricerca per la verifica di sistemi poliglotta
- Valore Pratico: Fornisce uno strumento di verifica per sistemi poliglotta critici per la sicurezza
- Ispirazione Tecnica: L'idea di utilizzare contratti come interfaccia tra linguaggi ha valore universale
- Sistemi Embedded: Sistemi real-time misti C/Rust
- Sistemi Distribuiti: Framework multilingue come ROS2 e gRPC
- Applicazioni Critiche per la Sicurezza: Sistemi che richiedono garanzie di verifica formale
- Integrazione di Sistemi Legacy: Sistemi con codice nuovo e vecchio mescolato
L'articolo cita 50 lavori correlati, coprendo molteplici aree di ricerca inclusi sistemi poliglotta, verifica formale, inferenza di contratti e sintesi guidata dalla sintassi, fornendo una base teorica solida per la ricerca.
Valutazione Complessiva: Questo è un articolo di ricerca di alta qualità che affronta un problema importante e pratico. Il metodo è innovativo, gli esperimenti sono completi e l'implementazione dello strumento è completa. Sebbene ci sia ancora spazio per miglioramenti in termini di prestazioni e scalabilità, l'articolo fornisce contributi significativi al campo della verifica di sistemi poliglotta.