Self-Spec Verifiable Code Generation
Organizations: School of Computer Science, Peking University · Beijing Key Laboratory of Trustworthy Code Large Language Models · Key Laboratory of High Confidence Software Technologies, Peking University, Ministry of Education · aiXcoder · Shanghai Jiao Tong University · Beijing Institute of Control Engineering
Abstract
Large language models (LLMs) may generate unreliable code on corner cases missed by testing, while formal verification can provide machine-checkable guarantees. Recently, researchers have proposed several benchmarks to evaluate the capabilities of LLMs in generating formally verifiable code, where LLMs need to formulate formal specifications, generate the corresponding code, and verify its correctness. However, existing benchmarks have two key limitations: (I) They primarily evaluate specification and code generation stage-wise, with code generation typically conditioned on an oracle specification. This setup overlooks whether strong stage-wise performance translates into end-to-end success. (II)They mainly focus on a single proof-oriented language and mathematically structured tasks, offering limited coverage of tasks common in software development. In this paper, we introduce VeriCodeBench, a benchmark for self-spec verifiable code generation, where the LLM relies solely on its own generated specification and code throughout the entire process. VeriCodeBench contains 400 language-native problems across C, Java, Rust, and Python, covering practical concerns in software development. We evaluate specification coverage, code validity, and joint problem-level success. We further introduce CodeNova to enhance the capabilities of LLMs in self-spec verifiable code generation. CodeNova makes requirements explicit through constraint-guided specification and uses verifier feedback to guide targeted implementation repairs. Experimental results reveal that self-generated specifications remain a major bottleneck, while providing more sophisticated specifications may not necessarily lead to higher verification success rates. CodeNova substantially improves performance across all evaluation metrics, enabling Claude Sonnet 5 to achieve the strongest results under the self-spec protocol.
Figures & tables
| Method / Benchmark | Joint Generation | Self-Spec | Multilingual | Language | Size |
| nl2spec ( Cosler et al., 2023 ) | LTL | 36 | |||
| AutoSpec ( Wen et al., 2024 ) | C | 251 | |||
| SpecGen ( Ma et al., 2025 ) | Java | 385 | |||
| ClassInvGen ( Sun et al., 2025 ) | C++ | 9 | |||
| PropertyGPT ( Liu et al., 2024 ) | Solidity | 23 | |||
| SLD-Spec ( Chen et al., 2025 ) | C | 62 |
| Language | Specification | Verifier | Size | Native coverage |
|---|---|---|---|---|
| C | ACSL | Frama-C/WP | 100 | Pointers and aliasing, arrays and slices, loops, byte/string buffers, structs, frame conditions, and bounded C arithmetic |
| Java | JML | OpenJML ESC | 100 | Arrays, scalar and Boolean APIs, strings, nullability, object invariants, object/field frames, mutation, and exceptional behavior |
| Rust | Verus | Verus | 100 | Scalar arithmetic, Option / Result , vectors and slices, ownership and borrowing, unique mutation, bounds, and panic freedom |
| Python | Nagini specifications | Nagini | 100 | Typed scalar functions, Optional / None , lists and dictionaries, predicate permissions, mutation, and exception freedom |
| Base LLM | Method | C (100) | Java (100) | Rust (100) | Python (100) | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Joint | Req. cov. | Valid | Joint | Req. cov. | Valid | Joint | Req. cov. | Valid | Joint | Req. cov. | Valid | ||
| DeepSeek V3.2 | Direct | 8 | 0.3247 | 34 | 30 | 0.7113 | 76 | 33 | 0.5522 | 44 | 46 | 0.8267 | 68 |
| +VGCR | 11 | 0.3247 | 60 | 31 | 0.7113 | 82 | 45 | 0.5522 | 68 | 46 | 0.8267 | 71 | |
| +CGS | 12 | 0.5215 | 30 | 36 | 0.7810 | 56 | 30 | 0.5572 | 49 | 51 | 0.8593 | 65 | |
| CodeNova | 17 | 0.5215 | 54 | 38 | 0.7810 | 66 | 35 | 0.5572 | 58 | 52 | 0.8593 | 68 | |
| Kimi-K2.7-Code | Direct | 16 | 0.5856 | 68 | 56 | 0.8250 | 77 | 57 | 0.6965 | 91 | 76 | 0.9327 | 86 |
| Base LLM | Method | C (100) | Java (100) | Rust (100) | Python (100) | ||||
|---|---|---|---|---|---|---|---|---|---|
| Self | Oracle | Self | Oracle | Self | Oracle | Self | Oracle | ||
| DeepSeek V3.2 | Direct | 34 | 69_{\color[rgb]{0,0.65,0.31}\uparrow 25} | 76 | 94_{\color[rgb]{0,0.65,0.31}\uparrow 18} | 44 | 70_{\color[rgb]{0,0.65,0.31}\uparrow 26} | 68 | 90_{\color[rgb]{0,0.65,0.31}\uparrow 22} |
| CodeNova | 54 | 69_{\color[rgb]{0,0.65,0.31}\uparrow 15} | 66 | 99_{\color[rgb]{0,0.65,0.31}\uparrow 33} | 58 | 91_{\color[rgb]{0,0.65,0.31}\uparrow 33} | 68 | 93_{\color[rgb]{0,0.65,0.31}\uparrow 25} | |
| Kimi-K2.7-Code | Direct | 68 | 70_{\color[rgb]{0,0.65,0.31}\uparrow 2} | 77 | 96_{\color[rgb]{0,0.65,0.31}\uparrow 19} | 91 | 91_{\color[rgb]{0.98,0.44,0.26}-} | 86 | 92_{\color[rgb]{0,0.65,0.31}\uparrow 6} |
| CodeNova | 86 | 89_{\color[rgb]{0,0.65,0.31}\uparrow 3} | 79 | 100_{\color[rgb]{0,0.65,0.31}\uparrow 21} | 60 | 93_{\color[rgb]{0,0.65,0.31}\uparrow 33} | 82 | 95_{\color[rgb]{0,0.65,0.31}\uparrow 13} | |
| Qwen3.6-plus | Direct | 50 | 86_{\color[rgb]{0,0.65,0.31}\uparrow 36} | 83 | 93_{\color[rgb]{0,0.65,0.31}\uparrow 10} | 56 | 74_{\color[rgb]{0,0.65,0.31}\uparrow 18} | 65 | 90_{\color[rgb]{0,0.65,0.31}\uparrow 25} |
Appendix figures & tables1 asset
Supplementary material from the paper’s appendix.
Appendix
| Specification source | Validity | Coverage | Joint success |
|---|---|---|---|
| Self | 91 | 0.697 | 57 |
| Oracle | 91 | 1.000 | 91 |