Skip to content

[SVCOMP] Add support for sv-witness generation in 2.2. format - #1102

Open
hernanponcedeleon wants to merge 1 commit into
developmentfrom
sv-witness
Open

hernanponcedeleon wants to merge 1 commit into
developmentfrom
sv-witness

Conversation

@hernanponcedeleon

Copy link
Copy Markdown
Owner

Summary

This PR adds support for generating violation witnesses in the SV-Witness 2.2 YAML format. It supports reachability, data-race, overflow, and memory-safety violations.

The generated witnesses describe a coarse concurrent execution containing the relevant thread ordering, assumptions, and violation targets.

Validation

The 30 fastest successful SV-COMP 2026 false(unreach-call) benchmarks were tested (using the only two available validators for the new format) with a 30-second limit per tool.

Outcome Dartagnan Theta CPAchecker
Benchmarks considered 30 30 30
Witnesses generated / validator invoked 29 29 29
Validated 10 9
Rejected 3 3
Timeout 1 2 13
Error or unsupported feature 0 14 4
Skipped 1 1

Most unsuccessful validations resulted from timeouts or unsupported features in the validators.

@hernanponcedeleon hernanponcedeleon changed the title Add support for sv-witness generation in 2.2. format [SVCOMP] Add support for sv-witness generation in 2.2. format Sep 13, 2026
@github-actions

Copy link
Copy Markdown

Performance comparison

Linux x64

Benchmark details

Memory model: vmm

Benchmark Base branch PR branch Improvement (99% CI) Result
benchmarks/locks/cna.c 10.237 ± 0.614 s 10.073 ± 0.193 s ➖ +1.4% [-20.9%, +23.8%] UNKNOWN
benchmarks/locks/mutex_musl.c 21.641 ± 0.086 s 22.018 ± 0.531 s ➖ -1.7% [-16.3%, +12.8%] UNKNOWN
benchmarks/lfds/dglm.c 18.333 ± 0.657 s 18.296 ± 0.685 s ➖ +0.0% [-42.6%, +42.6%] UNKNOWN
benchmarks/lfds/ms.c 31.795 ± 0.114 s 31.850 ± 0.349 s ➖ -0.2% [-6.8%, +6.5%] UNKNOWN
benchmarks/lfds/treiber.c 9.546 ± 0.058 s 9.400 ± 0.152 s ➖ +1.5% [-7.2%, +10.2%] UNKNOWN
benchmarks/lfds/safe_stack.c 5.040 ± 0.209 s 5.035 ± 0.176 s ➖ +0.1% [-12.8%, +12.9%] UNKNOWN
benchmarks/challenging/cna.c 31.562 ± 1.418 s 32.329 ± 0.700 s ➖ -2.6% [-41.0%, +35.7%] UNKNOWN

Memory model: aarch64

Benchmark Base branch PR branch Improvement (99% CI) Result
benchmarks/locks/linuxrwlock.c 5.335 ± 0.039 s 5.644 ± 0.324 s ➖ -5.8% [-40.4%, +28.8%] UNKNOWN
benchmarks/challenging/cna.c 12.341 ± 0.543 s 12.834 ± 0.589 s ➖ -4.2% [-50.6%, +42.2%] UNKNOWN
benchmarks/challenging/wsq.c 5.292 ± 0.093 s 5.266 ± 0.017 s ➖ +0.5% [-7.8%, +8.7%] UNKNOWN

Memory model: power

Benchmark Base branch PR branch Improvement (99% CI) Result
benchmarks/locks/linuxrwlock.c 13.673 ± 0.139 s 13.773 ± 0.144 s ➖ -0.7% [-4.8%, +3.4%] UNKNOWN
benchmarks/locks/mutex_musl.c 11.719 ± 1.089 s 12.658 ± 1.151 s ➖ -8.3% [-66.1%, +49.5%] UNKNOWN
benchmarks/lfds/ms.c 18.123 ± 2.262 s 17.596 ± 0.485 s ➖ +2.1% [-55.4%, +59.5%] UNKNOWN
benchmarks/lfds/treiber.c 11.582 ± 0.375 s 11.890 ± 0.745 s ➖ -2.8% [-50.5%, +45.0%] UNKNOWN

Total

Benchmarks Base branch PR branch Improvement (99% CI)
All reported benchmarks 206.221 ± 2.359 s 208.662 ± 1.802 s ➖ -1.2% [-12.9%, +10.5%]

4 benchmark(s) omitted because both averages were below 5 seconds.

macOS ARM64

Benchmark details

Memory model: vmm

Benchmark Base branch PR branch Improvement (99% CI) Result
benchmarks/locks/cna.c 17.125 ± 0.514 s 17.462 ± 1.119 s ➖ -2.1% [-55.8%, +51.5%] UNKNOWN
benchmarks/locks/mutex_musl.c 25.021 ± 0.257 s 25.377 ± 0.185 s ➖ -1.4% [-10.2%, +7.3%] UNKNOWN
benchmarks/lfds/dglm.c 44.330 ± 2.086 s 42.116 ± 0.878 s ➖ +4.9% [-20.3%, +30.1%] UNKNOWN
benchmarks/lfds/ms.c 77.000 ± 1.000 s 82.000 ± 6.928 s ➖ -6.4% [-51.0%, +38.1%] UNKNOWN
benchmarks/lfds/treiber.c 18.346 ± 0.452 s 19.347 ± 1.041 s ➖ -5.6% [-51.2%, +40.1%] UNKNOWN
benchmarks/lfds/safe_stack.c 20.867 ± 3.165 s 14.673 ± 0.833 s ➖ +28.9% [-17.0%, +74.8%] UNKNOWN
benchmarks/challenging/cna.c 51.343 ± 0.481 s 52.331 ± 0.841 s ➖ -1.9% [-12.4%, +8.6%] UNKNOWN

Memory model: aarch64

Benchmark Base branch PR branch Improvement (99% CI) Result
benchmarks/locks/linuxrwlock.c 17.838 ± 2.175 s 18.909 ± 0.838 s ➖ -6.8% [-63.1%, +49.6%] UNKNOWN
benchmarks/locks/mutex_musl.c 12.500 ± 0.472 s 12.369 ± 0.300 s ➖ +1.0% [-6.7%, +8.8%] UNKNOWN
benchmarks/lfds/dglm.c 14.521 ± 1.929 s 12.653 ± 0.322 s ➖ +11.6% [-68.7%, +91.9%] PASS
benchmarks/lfds/ms.c 15.570 ± 0.361 s 16.215 ± 1.619 s ➖ -4.3% [-71.8%, +63.3%] UNKNOWN
benchmarks/challenging/cna.c 47.549 ± 1.987 s 41.822 ± 1.217 s ➖ +11.9% [-14.3%, +38.2%] UNKNOWN
benchmarks/challenging/wsq.c 22.484 ± 2.436 s 21.008 ± 0.965 s ➖ +5.7% [-67.2%, +78.6%] UNKNOWN

Memory model: power

Benchmark Base branch PR branch Improvement (99% CI) Result
benchmarks/locks/linuxrwlock.c 52.495 ± 2.812 s 54.199 ± 4.892 s ➖ -3.3% [-49.2%, +42.6%] UNKNOWN
benchmarks/locks/mutex_musl.c 25.994 ± 4.566 s 25.234 ± 3.057 s ➖ +1.7% [-71.3%, +74.7%] UNKNOWN
benchmarks/lfds/dglm.c 10.484 ± 1.569 s 11.449 ± 2.980 s ➖ -7.9% [-80.7%, +64.9%] UNKNOWN
benchmarks/lfds/ms.c 58.511 ± 0.660 s 53.920 ± 3.877 s ➖ +7.8% [-32.5%, +48.1%] UNKNOWN
benchmarks/lfds/treiber.c 30.138 ± 0.296 s 28.834 ± 2.036 s ➖ +4.3% [-32.4%, +41.1%] UNKNOWN

Total

Benchmarks Base branch PR branch Improvement (99% CI)
All reported benchmarks 562.117 ± 9.145 s 549.920 ± 5.518 s ➖ +2.2% [-6.3%, +10.7%]

Comment on lines +25 to +45
// Add program-order (po) edges between consecutive events of each thread.
for (var thread : model.getThreadModels()) {
final List<EventModel> threadEvents = thread.getEventModels();
for (int i = 1; i < threadEvents.size(); i++) {
addEdge(successors, threadEvents.get(i - 1), threadEvents.get(i));
}
}

final Set<RelationModel.EdgeModel> coherence = relationEdges(model, CO);
for (RelationModel.EdgeModel edge : coherence) {
addEdge(successors, edge.from(), edge.to());
}
for (RelationModel.EdgeModel readFrom : relationEdges(model, RF)) {
addEdge(successors, readFrom.from(), readFrom.to());
for (RelationModel.EdgeModel co : coherence) {
if (co.from().equals(readFrom.from())) {
// fr = rf^-1 ; co
addEdge(successors, readFrom.to(), co.to());
}
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't the ExecutionModelNext already contain usable hb relation? Is the recomputation here necessary?

Comment on lines +47 to +49
// TODO: Extract this deterministic, cycle-rejecting topological sort into a general utility.
// Use Kahn's algorithm to construct a topological ordering. The in-degree records how many
// predecessors of each event still need to be added to the result.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, DependencyGraph.from(events, successors) already computes this. No TODO needed :).
This subsumes essentially all of the following code.

Comment on lines +34 to +43
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.HexFormat;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import java.util.*?

Comment on lines +62 to +64
public static Optional<SvcompWitness> forViolation(
ExecutionModelNext model, VerificationTask task, IREvaluator evaluator)
throws IOException {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here you can see how our current model sucks. Despite having the model, you still need an IREvaluator because the model has not enough information :(.

Comment on lines +125 to 128
public Output getOutputFromSolver(TaskSolver solver, Path programPath) {
if (solver instanceof VerificationTaskSolver verificationTaskSolver) {
return getOutputFromSolver(verificationTaskSolver, programPath);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With program.getInputPath() as metadata, I think the second parameter can be fully removed from all methods with the exception of getOutputFromException.
I always disliked that parameter and it was only there due to lack of source metadata in Program.

I think you can (and should) cleanly split the PR into two:
(1) Add source metadata to Program, update ProgramParser to add the metadata when parsing, update OutputLogger to use that data and get rid of the programPath parameter.
You can also put all other minor changes in this PR (e.g. EnvironmentInfo.getVersion().
(2) Add SVCOMP witnesses.

@hernanponcedeleon hernanponcedeleon added the SVCOMP Issues related to SVCOMP label Sep 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

SVCOMP Issues related to SVCOMP

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants