Testing the Verifier: Automated Testing for Isabelle (Artifact, Working paper)
Description
Isabelle Testing Project -- Findings Summary
This document summarises the findings reported in "Testing the Verifier: Automated Testing for Isabelle" together with the project ownership mapping used in this repository.Abstract.
This initial report summarises the investigation and gives each student space to describe their individual experience of the process. A more concise and synthesised report, intended for publication as a research paper, is planned as future work.
We present a fuzzing-based approach for testing Isabelle by targeting components that interact with its trusted core. Over six months, four students investigated different subsystems and uncovered 25 distinct anomalies. We reported 20 findings to the developers, 13 of which were confirmed, and 12 were subsequently fixed in response to our reports. We also submitted seven patches, resulting in six accepted pull requests and improving the quality of the broader Isabelle ecosystem beyond its core.
Acknowledgements.
We thank Larry Paulson and Fabian Huch for discussions and feedback that helped shape this project.
We thank King's College London, Department of Informatics, for supporting this project under Knowledge Transfer Projects (KEP) 2025/2026 UG.
Evaluation
Findings Ownership
| Findings | Subsystem | Student | PRs By Student |
|---|---|---|---|
| #1--5 | Poly/ML Lexer (x86) | Enzo Bestetti |
Commits: fc8748, 2a1c2ab |
| #6--8 | Poly/ML ARM64 | Aravinth Kaneshalingam |
PR #294 (waiting to merge). |
| #9--19 | Isabelle/jEdit | Bartosz Gowacki |
- |
| #20--24 | Sledgehammer | Jiangjing Xu | PR #103, PR #106, PR #106, ebb7430 (direct suggest ack in the commit) |
Issues #10, #24, and #25 were detected by our approach but had already been reported by others.
All other confirmed issues were never reported before we did.
Additional repositories:
- https://zenodo.org/records/19593541
- https://zenodo.org/records/19593553
- https://zenodo.org/records/19593519
- https://zenodo.org/records/19696191
- https://zenodo.org/records/19899187
- https://github.com/BGlowacki-kcl/Isabelle_dissertation_Bartosz/tree/main/differential/bug_reports (also attached as a zip here)
- https://github.com/aravinth-kanesh/polyml-fuzz (also attached as a zip here)
- https://github.com/Xujiangjing/fyp-isabelle-fuzz (also attached as a zip here)
- https://github.com/enzozbest/polyfuzz (also attached as a zip here)
Findings Summary
The component-level breakdown reveals the following. Poly/ML lexer has the broadest spread across all categories, with one new issue, one confirmed issue, three fixed issues, and four marked as WONT FIX, which includes duplicate bugs, false positives and minor bugs that the maintainers found irrelevant to the reliability of the platform (e.g not a clear enough error message). While the sledgehammer shows the strongest resolution trend. All six recorded issues are fixed, with no remaining new, confirmed, or WONT FIX items. This points to focused maintenance and effective closure of known problems.
Isabelle/jEdit stands out because most of its issues are classified as WONT FIX. With 8 in that category and only 3 fixed, the pattern may indicate design limitations, low-priority requests, obsolete reports, or issues considered too costly relative to their impact. The absence of new or confirmed items could also mean that its backlog is relatively stable.
| Component | New | Confirmed | Fixed | WON'T FIX |
|---|---|---|---|---|
| Poly/ML lexer | 1 | 1 | 3 | 4 |
| Isabelle/jEdit | 0 | 0 | 3 | 8 |
| Sledgehammer | 0 | 0 | 6 | 0 |
The main follow-up area is understanding the connection between the testing technique used and the component bug discovery performance.
Public Bug Reports, Pull Requests and References [THIS IS A FIRST DRAFT! - PLEASE CHECK NEWER VERSIONS]
| Finding | Component | Report venue | Status | Evidence | TODO |
|---|---|---|---|---|---|
| #1 | Poly/ML lexer X86 | public mailing list | Confirmed | Confirmed bug with a proposed fix; no fix approved. | - |
| #2 | Poly/ML lexer X86 | GitHub Issue #256 | Fixed | Commit fc87489 + email [link] | - |
| #3 | Poly/ML lexer X86 | GitHub Issue #258 | Fixed | Commit 2a1c2ab + email [link] | - |
| #4 | Poly/ML lexer X86 | N/A | WON’T FIX | Private communication regarding poly/ml lexer behaviour (2026), email correspon- dence between David Matthews and Enzo Bestetti |
- |
| #5 | Poly/ML lexer X86 | N/A | Not reported | Informational observation; likely intentional parser deviation | Remove from the final list of bugs |
| #6 | Poly/ML ARM64 | GitHub Issue #271 | Reported | A fix was suggested as PR #294. | - |
| #7 | Poly/ML ARM64 | GitHub Issue #273 | WON’T FIX | Remove from the final list of bugs | |
| #8 | Poly/ML ARM64 | GitHub Issue #272 | Fixed | Commit cf7b84a (Input 1) | - |
| #8 (dup) | Poly/ML ARM64 | GitHub Issue #274 | Duplicate | The maintainer confirmed the shared root cause. Closed as a duplicate of #272 | Remove from the final list of bugs |
| #9 | Isabelle/jEdit | Mailing list [link] [additional data link] | Fixed | Maintainers committed a patch in response to our report that prevents the observed behaviour from happening. | - |
| #10 | Isabelle/jEdit | NA | Fixed | Old bug. Fixed (before we reported it) on the trunk [link]. | - |
| #11 | Isabelle/jEdit | Mailing list | Not Reported | Patch submitted to developers | Remove from the final list of bugs |
| #12 | Isabelle/jEdit | Mailing list [link] [additional data link] | Fixed | Maintainers committed a different patch in response to our report that prevents the observed behaviour from happening | - |
| #13 | Isabelle/jEdit | Mailing list | False Positive | Email evidence: differences in output confirmed, not significant. False Positive |
Remove from the final list of bugs |
| #14 | Isabelle/jEdit | Mailing list | False Positive | Email evidence: differences in output confirmed, not significant. False Positive | Remove from the final list of bugs |
| #15 | Isabelle/jEdit | Mailing list | False Positive | Email evidence: differences in output confirmed, not significant. False Positive | Remove from the final list of bugs |
| #16 | Isabelle/jEdit | Mailing list | False Positive | Email evidence: differences in output confirmed, not significant. False Positive | Remove from the final list of bugs |
| #17 | Isabelle/jEdit | Mailing list | False Positive | Email evidence: differences in output confirmed, not significant. False Positive | Remove from the final list of bugs |
| #18 | Isabelle/jEdit | Mailing list | False Positive | Email evidence: differences in output confirmed, not significant. False Positive | Remove from the final list of bugs |
| #19 | Isabelle/jEdit | Mailing list | False Positive | Email evidence: differences in output confirmed, not significant. False Positive | Remove from the final list of bugs |
| #20 | Zipperposition | GitHub Issue #102, [Mailing list], and [Mailing list 2] | Fixed | PR #103 | - |
| #21 | Zipperposition | GitHub Issue #104 | Fixed | PR #106 | - |
| #22 | E prover | Direct email on Thursday, 2 April 2026 | Fixed | Commit ebb7430: “Fixed parser source bug … Thanks to Jiangjing Xu”. | I have the email. Can we add it here? |
| #23 | Zipperposition | GitHub Issue #108 | Fixed | PR #109 | - |
| #24 | Z3 | NA | Fixed | Old bug in Isabelle-bundled Z3 4.4.0 | - |
| #25 | Z3 | NA | Fixed | Old bug in Isabelle-bundled Z3 4.4.0 | - |
Finding #9
The fix was done just after the report. We used an LLM (OpenAI, 15/07/2026, GPT 5.5 High configuration) to map each fix to the reported issue:
This changeset is **most closely related to Finding #9**, because it modifies `src/Pure/Concurrent/delay.scala` and the way delayed events are scheduled throughout Isabelle. However, **it does not appear to be the direct fix for Finding #9**. Finding #9 concerns an exception escaping from `Delay.run()`, killing the shared event-timer thread. Its proposed fix was to log the exception **without rethrowing it**. In this changeset, the relevant modification is instead: ```scala -if (do_run) event +if (do_run) app(event) ``` It also replaces the global `Delay` factory with `Delay_Ops`, introduces separate `GUI.Delay` and `Resources.Delay` objects, and supplies context-specific loggers and execution mechanisms. The GUI version, for example, sends the event through `GUI_Thread.later`. There is no shown removal of the problematic exception rethrow, and the changeset contains no new `catch` or exception-handling logic. Therefore: > **Classification: related follow-up/refactoring for Finding #9, but not sufficient evidence of the direct Finding #9 fix.** It is clearly not: * **Finding #10**, which concerns `Progress.stopped` consuming and caching a thread-interruption flag. * **Finding #11**, which concerns recursive XML traversal and stack overflow. * **Finding #12**, which concerns null handling in `XML.Output.string`. **Best label:** **Finding #9-related architectural change**, with medium confidence that it was motivated by or followed the Finding #9 discussion, but low confidence that this changeset itself fixes the reported exception-rethrow defect.
Finding #12
The fix was done just after the report. We used an LLM (OpenAI, 15/07/2026, GPT 5.5 High configuration) to map each fix to the reported issue:
This changeset is fixing **Finding #12 — XML serialisation null-handling corruption**. Finding #12 identifies this exact code in `XML.Output.string`: ```scala if (str == null) { builder ++= str } ``` Because Scala/Java’s `StringBuilder.append(null)` writes the four characters `"null"`, a null value could silently corrupt the serialised XML rather than causing an explicit failure. The changeset removes that special null branch: ```scala str foreach { ... } ``` Consequently, a null string is no longer silently converted into the text `"null"`. Instead, it fails, which reflects the maintainer’s stated position that valid XML trees must never contain null. The additional `Tree.toString` protection returns `"<malformed>"` for applicable XML errors, making top-level diagnostic output more robust. ### Classification > **Changeset `98810e4d19d9` → Finding #12** **Confidence:** Very high — it changes the exact `XML.Output.string` code described in Finding #12. There is a minor difference between the student’s proposed solution and the accepted implementation: * **Student patch:** make the null branch a no-op. * **Accepted approach:** remove permissive null handling and let malformed XML fail, while making `toString` output more defensive. It is **not Finding #11**, because Finding #11 concerns recursive `filter_elements` traversal causing a possible `StackOverflowError`, not null handling.
Findings #13 to #18:
The maintainer acknowledged that the reported differences are real, but argued that differences between batch build and PIDE should not automatically be treated as software bugs. We therefore classify such reports as false positives only when the observed divergence does not identify a concrete defect or actionable improvement. See msg00019 for further details.
Finding #24 was a crash:
================ mut_02539_230fd4c313 ================
(lldb) target create "/Users/xujiangjing/Isabelle2025/Isabelle2025.app/contrib/z3-4.4.0pre-4/x86_64-darwin/z3"
Current executable set to '/Users/xujiangjing/Isabelle2025/Isabelle2025.app/contrib/z3-4.4.0pre-4/x86_64-darwin/z3' (x86_64).
(lldb) settings set -- target.run-args "-smt2" "/Users/xujiangjing/smt_fuzz_v2/mutants/mut_02539_230fd4c313.smt2"
(lldb) run
warning: libobjc.A.dylib is being read from process memory. This indicates that LLDB could not read from the host's in-memory shared cache. This will likely reduce debugging performance.
Process 8749 launched: '/Users/xujiangjing/Isabelle2025/Isabelle2025.app/contrib/z3-4.4.0pre-4/x86_64-darwin/z3' (x86_64)
Process 8749 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x60010108954f)
frame #0: 0x00000001003487b7 z3`___lldb_unnamed_symbol_100348702 + 181
z3`___lldb_unnamed_symbol_100348702:
-> 0x1003487b7 <+181>: movsbl (%rax,%r14), %eax
0x1003487bc <+186>: cmpl $-0x1, %eax
0x1003487bf <+189>: je 0x1003487d4 ; <+210>
0x1003487c1 <+191>: testl %eax, %eax
Target 0: (z3) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x60010108954f)
* frame #0: 0x00000001003487b7 z3`___lldb_unnamed_symbol_100348702 + 181
frame #1: 0x0000000100349064 z3`___lldb_unnamed_symbol_100348fec + 120
frame #2: 0x0000000100349a63 z3`___lldb_unnamed_symbol_100349974 + 239
frame #3: 0x000000010034dfd0 z3`___lldb_unnamed_symbol_10034da76 + 1370
frame #4: 0x0000000100332867 z3`___lldb_unnamed_symbol_1003327b6 + 177
frame #5: 0x0000000100339b95 z3`___lldb_unnamed_symbol_100339b08 + 141
frame #6: 0x00000001002de2a2 z3`___lldb_unnamed_symbol_1002dd64e + 3156
frame #7: 0x00000001006ba18d z3`___lldb_unnamed_symbol_1006b9f90 + 509
frame #8: 0x00000001006ba2f8 z3`___lldb_unnamed_symbol_1006b9f90 + 872
frame #9: 0x00000001006bfca1 z3`___lldb_unnamed_symbol_1006bfae4 + 445
frame #10: 0x00000001006ba2f8 z3`___lldb_unnamed_symbol_1006b9f90 + 872
frame #11: 0x00000001006b68a6 z3`___lldb_unnamed_symbol_1006b6860 + 70
frame #12: 0x00000001006b6af1 z3`___lldb_unnamed_symbol_1006b69d0 + 289
frame #13: 0x00000001005d3bb9 z3`___lldb_unnamed_symbol_1005d39ee + 459
frame #14: 0x00000001005d3035 z3`___lldb_unnamed_symbol_1005d2fa4 + 145
frame #15: 0x00000001005d2af1 z3`___lldb_unnamed_symbol_1005d2806 + 747
frame #16: 0x000000010053477b z3`___lldb_unnamed_symbol_100534638 + 323
frame #17: 0x000000010051d453 z3`___lldb_unnamed_symbol_10051cd84 + 1743
frame #18: 0x00000001005234ec z3`___lldb_unnamed_symbol_1005233d0 + 284
frame #19: 0x0000000100510968 z3`___lldb_unnamed_symbol_100510940 + 40
frame #20: 0x000000010000b241 z3`___lldb_unnamed_symbol_10000b110 + 305
frame #21: 0x000000010000ac4e z3`___lldb_unnamed_symbol_10000aa10 + 574
frame #22: 0x0000000100000f74 z3`___lldb_unnamed_symbol_100000f40 + 52
(lldb) quit
================ mut_02606_702c48cda4 ================
(lldb) target create "/Users/xujiangjing/Isabelle2025/Isabelle2025.app/contrib/z3-4.4.0pre-4/x86_64-darwin/z3"
Current executable set to '/Users/xujiangjing/Isabelle2025/Isabelle2025.app/contrib/z3-4.4.0pre-4/x86_64-darwin/z3' (x86_64).
(lldb) settings set -- target.run-args "-smt2" "/Users/xujiangjing/smt_fuzz_v2/mutants/mut_02606_702c48cda4.smt2"
(lldb) run
warning: libobjc.A.dylib is being read from process memory. This indicates that LLDB could not read from the host's in-memory shared cache. This will likely reduce debugging performance.
WARNING: unknown logic, ignoring set-logic command
Process 8821 launched: '/Users/xujiangjing/Isabelle2025/Isabelle2025.app/contrib/z3-4.4.0pre-4/x86_64-darwin/z3' (x86_64)
Process 8821 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x60010347c7cf)
frame #0: 0x00000001003487b7 z3`___lldb_unnamed_symbol_100348702 + 181
z3`___lldb_unnamed_symbol_100348702:
-> 0x1003487b7 <+181>: movsbl (%rax,%r14), %eax
0x1003487bc <+186>: cmpl $-0x1, %eax
0x1003487bf <+189>: je 0x1003487d4 ; <+210>
0x1003487c1 <+191>: testl %eax, %eax
Target 0: (z3) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x60010347c7cf)
* frame #0: 0x00000001003487b7 z3`___lldb_unnamed_symbol_100348702 + 181
frame #1: 0x0000000100349064 z3`___lldb_unnamed_symbol_100348fec + 120
frame #2: 0x0000000100349a63 z3`___lldb_unnamed_symbol_100349974 + 239
frame #3: 0x000000010034dfd0 z3`___lldb_unnamed_symbol_10034da76 + 1370
frame #4: 0x0000000100332867 z3`___lldb_unnamed_symbol_1003327b6 + 177
frame #5: 0x0000000100339b95 z3`___lldb_unnamed_symbol_100339b08 + 141
frame #6: 0x00000001002de2a2 z3`___lldb_unnamed_symbol_1002dd64e + 3156
frame #7: 0x00000001006bfcf5 z3`___lldb_unnamed_symbol_1006bfae4 + 529
frame #8: 0x00000001006ba2f8 z3`___lldb_unnamed_symbol_1006b9f90 + 872
frame #9: 0x00000001006ba2f8 z3`___lldb_unnamed_symbol_1006b9f90 + 872
frame #10: 0x00000001006b68a6 z3`___lldb_unnamed_symbol_1006b6860 + 70
frame #11: 0x00000001006b6af1 z3`___lldb_unnamed_symbol_1006b69d0 + 289
frame #12: 0x00000001005d3bb9 z3`___lldb_unnamed_symbol_1005d39ee + 459
frame #13: 0x00000001005d3035 z3`___lldb_unnamed_symbol_1005d2fa4 + 145
frame #14: 0x00000001005d2af1 z3`___lldb_unnamed_symbol_1005d2806 + 747
frame #15: 0x000000010053477b z3`___lldb_unnamed_symbol_100534638 + 323
frame #16: 0x000000010051d453 z3`___lldb_unnamed_symbol_10051cd84 + 1743
frame #17: 0x00000001005234ec z3`___lldb_unnamed_symbol_1005233d0 + 284
frame #18: 0x0000000100510968 z3`___lldb_unnamed_symbol_100510940 + 40
frame #19: 0x000000010000b241 z3`___lldb_unnamed_symbol_10000b110 + 305
frame #20: 0x000000010000ac4e z3`___lldb_unnamed_symbol_10000aa10 + 574
frame #21: 0x0000000100000f74 z3`___lldb_unnamed_symbol_100000f40 + 52
(lldb) quit
Finding #25 was a crash:
================ mut_04980_25978f85bf ================
(lldb) target create "/Users/xujiangjing/Isabelle2025/Isabelle2025.app/contrib/z3-4.4.0pre-4/x86_64-darwin/z3"
Current executable set to '/Users/xujiangjing/Isabelle2025/Isabelle2025.app/contrib/z3-4.4.0pre-4/x86_64-darwin/z3' (x86_64).
(lldb) settings set -- target.run-args "-smt2" "/Users/xujiangjing/smt_fuzz_v2/mutants/mut_04980_25978f85bf.smt2"
(lldb) run
warning: libobjc.A.dylib is being read from process memory. This indicates that LLDB could not read from the host's in-memory shared cache. This will likely reduce debugging performance.
Process 8839 launched: '/Users/xujiangjing/Isabelle2025/Isabelle2025.app/contrib/z3-4.4.0pre-4/x86_64-darwin/z3' (x86_64)
Process 8839 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x6001021b559f)
frame #0: 0x000000010034cc2d z3`___lldb_unnamed_symbol_10034cad6 + 343
z3`___lldb_unnamed_symbol_10034cad6:
-> 0x10034cc2d <+343>: movsbl (%rcx,%rdx), %ecx
0x10034cc31 <+347>: testl %ecx, %ecx
0x10034cc33 <+349>: je 0x10034cc52 ; <+380>
0x10034cc35 <+351>: cmpl $-0x1, %ecx
Target 0: (z3) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x6001021b559f)
* frame #0: 0x000000010034cc2d z3`___lldb_unnamed_symbol_10034cad6 + 343
frame #1: 0x000000010034e345 z3`___lldb_unnamed_symbol_10034da76 + 2255
frame #2: 0x0000000100332867 z3`___lldb_unnamed_symbol_1003327b6 + 177
frame #3: 0x0000000100339b95 z3`___lldb_unnamed_symbol_100339b08 + 141
frame #4: 0x00000001002de2a2 z3`___lldb_unnamed_symbol_1002dd64e + 3156
frame #5: 0x00000001006bd840 z3`___lldb_unnamed_symbol_1006bd7de + 98
frame #6: 0x00000001006bfca1 z3`___lldb_unnamed_symbol_1006bfae4 + 445
frame #7: 0x00000001006ba18d z3`___lldb_unnamed_symbol_1006b9f90 + 509
frame #8: 0x00000001006ba2f8 z3`___lldb_unnamed_symbol_1006b9f90 + 872
frame #9: 0x00000001006bfca1 z3`___lldb_unnamed_symbol_1006bfae4 + 445
frame #10: 0x00000001006ba2f8 z3`___lldb_unnamed_symbol_1006b9f90 + 872
frame #11: 0x00000001006b68a6 z3`___lldb_unnamed_symbol_1006b6860 + 70
frame #12: 0x00000001006b6af1 z3`___lldb_unnamed_symbol_1006b69d0 + 289
frame #13: 0x00000001005d3bb9 z3`___lldb_unnamed_symbol_1005d39ee + 459
frame #14: 0x00000001005d3035 z3`___lldb_unnamed_symbol_1005d2fa4 + 145
frame #15: 0x00000001005d2af1 z3`___lldb_unnamed_symbol_1005d2806 + 747
frame #16: 0x000000010053477b z3`___lldb_unnamed_symbol_100534638 + 323
frame #17: 0x000000010051d453 z3`___lldb_unnamed_symbol_10051cd84 + 1743
frame #18: 0x00000001005234ec z3`___lldb_unnamed_symbol_1005233d0 + 284
frame #19: 0x0000000100510968 z3`___lldb_unnamed_symbol_100510940 + 40
frame #20: 0x000000010000b241 z3`___lldb_unnamed_symbol_10000b110 + 305
frame #21: 0x000000010000ac4e z3`___lldb_unnamed_symbol_10000aa10 + 574
frame #22: 0x0000000100000f74 z3`___lldb_unnamed_symbol_100000f40 + 52
(lldb) quit
=====
Files
fyp-isabelle-fuzz-main.zip
Files
(16.9 MB)
| Name | Size | Download all |
|---|---|---|
|
md5:9d8378fb98f5b1cdd02600aaa4ebbd59
|
13.9 MB | Preview Download |
|
md5:ba168ffe9fcbaf007f1664492eaedb8a
|
1.9 MB | Preview Download |
|
md5:a691dca84f5d25e258123e7454970c1e
|
55.2 kB | Preview Download |
|
md5:8cf62ec939e5ad9455a17cf262d6d523
|
565.0 kB | Preview Download |
|
md5:7149355efd7e51717e4857ca2ef38be7
|
419.9 kB | Preview Download |
|
md5:c5a947b5e30b8051dc721226eecc2da8
|
9.1 kB | Preview Download |