Property-Based Slicing

Property-based slicing allows you to slice programs with respect to specific verification properties, reducing the program to only the parts relevant to checking that property.

Overview

Property-based slicing extends Lotus’s PDG slicing capabilities by allowing you to specify properties using Symbiotic-compatible .prp files. The slicer automatically identifies relevant program points based on the property and computes backward or forward slices.

Property Specification Format

Lotus supports Symbiotic-style property files with LTL/FQL syntax:

Safety Properties (CHECK):

CHECK( init(main()), LTL(G ! call(reach_error())) )
CHECK( init(main()), LTL(G valid-deref) )
CHECK( init(main()), LTL(G valid-free) )
CHECK( init(main()), LTL(G valid-memtrack) )
CHECK( init(main()), LTL(G ! overflow) )
CHECK( init(main()), LTL(G ! null-deref) )
CHECK( init(main()), LTL(G def-behavior) )
CHECK( init(main()), LTL(G valid-memcleanup) )
CHECK( init(main()), LTL(F end) )

Coverage Properties (COVER):

COVER( init(main()), FQL(COVER EDGES(@DECISIONEDGE)) )
COVER( init(main()), FQL(COVER EDGES(@BASICBLOCKENTRY)) )
COVER( init(main()), FQL(COVER EDGES(@CONDITIONEDGE)) )
COVER( init(main()), FQL(COVER EDGES(@CALL(reach_error))) )

Supported Property Types

  • UnreachCall: Target function should not be reachable

  • MemSafety: Memory safety (valid-deref, valid-free, valid-memtrack)

  • NoOverflow: No signed integer overflow

  • Termination: Program terminates

  • NullDeref: No null pointer dereference

  • DefBehavior: No undefined behavior

  • MemCleanup: Memory cleanup safety

  • CoverageBranches: Branch coverage

  • CoverageStatements: Statement coverage

  • CoverageConditions: Condition coverage

  • CoverageErrorCall: Error call coverage

Usage

Basic usage with pdg-query:

# Backward slice (default)
pdg-query input.bc --property-file property.prp

# Forward slice
pdg-query input.bc --property-file property.prp --direction forward

# Dump slice nodes
pdg-query input.bc --property-file property.prp --dump-slice

Example

Given a property file unreach-call.prp:

CHECK( init(main()), LTL(G ! call(reach_error())) )

And a program test.c:

extern void reach_error();

int main() {
  int x = 0;
  if (x > 0) {
    reach_error();
  }
  return 0;
}

Slice the program:

clang -emit-llvm -c test.c -o test.bc
pdg-query test.bc --property-file unreach-call.prp

The slicer will identify the reach_error() call and compute a backward slice containing all instructions that can affect whether that call is executed.

Integration with Verification

Property-based slicing is designed to work with Lotus’s verification backends:

pdg-query input.bc --property-file property.prp --dump-slice

This workflow identifies the PDG region relevant to the property so it can be fed into verification or reduction passes without requiring a separate frontend binary.