uBPF Validation Plan
Document Version: 1.2.0 Date: 2026-06-12 Status: Draft — Refreshed from current test inventory
1. Overview
1.1 Objectives
This validation plan defines how the uBPF virtual machine library is verified against its requirements specification (docs/specs/requirements.md). It maps existing tests to requirements, identifies coverage gaps, and provides a framework for ongoing validation.
1.2 System Under Test
The uBPF library including:
- Core VM interpreter (
vm/ubpf_vm.c) - JIT compilers (
vm/ubpf_jit_x86_64.c, vm/ubpf_jit_arm64.c) - ELF loader (
vm/ubpf_loader.c) - Instruction validator (
vm/ubpf_instruction_valid.c) - Public API (
vm/inc/ubpf.h) - Python assembler/disassembler (
ubpf/)
1.3 Validation Approach
uBPF uses a multi-layered testing strategy:
- Data-driven tests —
.data files parsed by Python test framework - Custom C++ tests — targeted scenarios for specific features
- Conformance suite — BPF ISA standard compliance (313 tests)
- Differential fuzzing — interpreter vs. JIT comparison with PREVAIL verifier
- Static analysis — CodeQL, scan-build, cpplint, pylint
- Dynamic analysis — ASan, UBSan, Valgrind
2. Scope of Validation
2.1 In Scope
- All public API functions in
ubpf.h - Interpreter execution correctness
- JIT compilation correctness (x86-64, ARM64)
- ELF loading and relocation processing
- Instruction validation and error handling
- Security feature effectiveness
- Platform-specific behavior (Windows, Linux, macOS)
- Python assembler/disassembler correctness
2.2 Out of Scope
- Performance benchmarking (no perf regression tests exist)
- Thread safety / concurrency testing
- Formal verification of JIT output
- External verifier (PREVAIL) correctness
- Stress testing (large programs, deep recursion)
2.3 Constraints
- ARM64 JIT tests require QEMU on x86-64 hosts or native ARM64 hardware
- Fuzzing requires Clang (libFuzzer integration)
- Some tests require environment variables (e.g.,
UBPF_ENABLE_CONSTANT_BLINDING=1) - Valgrind only available on Linux
3. Test Strategy
3.1 Test Levels
| Level | Description | Tools | Coverage |
|---|
| Unit | Individual instruction execution | .data files + test_vm.py | ISA compliance |
| Integration | VM lifecycle + loading + execution | Custom C++ tests | API interactions |
| System | Full pipeline (load ELF → compile → execute) | test_elf.py, ubpf_plugin | End-to-end |
| Regression | Prevent reintroduction of fixed bugs | Full CTest suite | All areas |
| Fuzzing | Find edge cases and differential bugs | libFuzzer + PREVAIL | Interpreter/JIT parity |
3.2 Test Techniques
| Technique | Application |
|---|
| Equivalence partitioning | ALU operations by operand type (reg/imm, 32/64-bit) |
| Boundary value analysis | Register ranges (0, 9, 10), instruction count limits, stack boundaries |
| Error guessing | Division by zero, stack overflow, invalid opcodes |
| Differential testing | Interpreter vs. JIT output comparison (fuzzer) |
| Mutation testing | Register offset variations (20 per test in JIT) |
| Conformance testing | BPF ISA standard (RFC 9669) compliance |
3.3 Test Infrastructure
Python Framework (test_framework/):
testdata.py — Parses .data files into test parameterstest_vm.py — Interpreter execution (1 test per .data file)test_jit.py — JIT compilation (20 register-offset variants per .data file)test_elf.py — ELF format loadingtest_assembler.py — Assembly → binary verificationtest_disassembler.py — Binary → assembly verificationtest_roundtrip.py — Assembler → binary → disassembler consistency
Custom Tests (custom_tests/):
- 17 C++20 test programs with markdown descriptors
- Each returns 0 (pass) or non-zero (fail)
- Some read input from stdin via
.input data files
Conformance Suite (external/bpf_conformance/):
- 313
.data files for standard eBPF instruction semantics - Executed via
ubpf_plugin for both interpreter and JIT - The uBPF CTest wiring also routes the repository's 104 local
.data files through the same plugin contract
Fuzzer (libfuzzer/libfuzz_harness.cc):
- Differential testing: interpreter vs. JIT
- Optional PREVAIL verifier integration
- Configurable via environment variables
4. Requirements Traceability Matrix
4.1 VM Lifecycle
| REQ-ID | Requirement | Test Cases | Coverage |
|---|
| REQ-LIFE-001 | VM creation | TC-LIFE-001 | High — implicitly tested by all tests |
| REQ-LIFE-002 | VM default state | TC-LIFE-004 | Medium — tested indirectly via default behavior |
| REQ-LIFE-003 | VM creation — allocations | TC-LIFE-006 | Low — [GAP: no explicit OOM tests] |
| REQ-LIFE-004 | Platform JIT selection | TC-LIFE-005 | High — CI runs on x86-64, ARM64, macOS |
| REQ-LIFE-005 | VM destruction | TC-LIFE-002 | Medium — Valgrind checks, reload_code_memleak |
| REQ-LIFE-006 | Code unloading | TC-LIFE-003 | High — unload_reload.data, reload.data |
4.2 Program Loading
| REQ-ID | Requirement | Test Cases | Coverage |
|---|
| REQ-LOAD-001 | Code length validation | TC-LOAD-002 | Medium — [GAP: no test for non-multiple-of-8] |
| REQ-LOAD-002 | Maximum instruction count | TC-LOAD-003 | Low — [GAP: no test with 65536+ instructions] |
| REQ-LOAD-003 | Double-load prevention | TC-LOAD-001 | High — all .data tests call ubpf_load |
| REQ-LOAD-004 | Instruction validation | TC-LOAD-004 | High — tests/errors/*, atomic_validate custom test |
| REQ-LOAD-005 | Read-only bytecode storage | TC-LOAD-007, TC-LOAD-008 | Medium — readonly_bytecode custom test (toggles mode only; [GAP: no direct test that bytecode pages are read-only when enabled]) |
| REQ-LOAD-006 | Pointer secret encoding | TC-LOAD-009 | Medium — [GAP: no direct test of pointer secret encoding correctness] |
| REQ-LOAD-007 | Local function marking | TC-LOAD-010 | High — call_local_use_stack.data, factorial.data |
| REQ-LOAD-008 | Stack alignment validation | TC-LOAD-005 | High — custom_local_function_stack_size tests |
| REQ-LOAD-009 | Sub-program containment | TC-LOAD-006 | Medium — tested via local call tests |
| REQ-LOAD-010 | Jump target validation | TC-LOAD-004 | High — tested via instruction validation |
| REQ-LOAD-011 | LDDW pairing validation | TC-LOAD-004 | High — tested via instruction validation |
4.3 Program Execution
| REQ-ID | Requirement | Test Cases | Coverage |
|---|
| REQ-EXEC-001 | Interpreter entry point | TC-EXEC-001 | High — test_vm.py runs all .data files |
| REQ-EXEC-002 | Extended interpreter entry point | TC-EXEC-002 | Medium — [GAP: limited direct exec_ex tests] |
| REQ-EXEC-003 | Register initialization | TC-EXEC-003 | High — mem/result comparison in all tests |
| REQ-EXEC-004 | Code-not-loaded guard | TC-EXEC-004 | Medium — [GAP: no explicit test for exec without load] |
| REQ-EXEC-005 | Instruction limit enforcement | TC-EXEC-009 | Low — [GAP: no direct instruction limit test] |
| REQ-EXEC-006 | Call depth limit | TC-EXEC-007 | High — factorial.data, call_local_use_stack.data, stack tests |
| REQ-EXEC-007 | XOR-decoded instruction fetch | TC-EXEC-004 | High — 360+ .data tests + fuzzer (implicit) |
| REQ-EXEC-008 | Unwind function support | TC-EXEC-008 | Medium — call_unwind.data |
| REQ-EXEC-009 | Debug callback invocation | TC-EXEC-010 | High — debug_function custom test |
4.4 JIT Compilation
| REQ-ID | Requirement | Test Cases | Coverage |
|---|
| REQ-JIT-001 | compile API | TC-JIT-001 | High — test_jit.py runs all .data files through JIT |
| REQ-JIT-002 | compile_ex API (BasicJitMode & ExtendedJitMode) | TC-JIT-002, TC-JIT-003, TC-JIT-004 | High — BasicJitMode is the default in test_jit.py; ExtendedJitMode tested via ubpf_plugin with --jit |
| REQ-JIT-003 | Code caching | TC-JIT-005 | Low — [GAP: no explicit caching test] |
| REQ-JIT-004 | Executable memory (W⊕X) | TC-JIT-006 | Medium — implicitly tested; ASan would catch violations |
| REQ-JIT-005 | JIT buffer sizing | TC-JIT-011 | High — jit_buffer_too_small custom test |
| REQ-JIT-006 | copy_jit API | TC-JIT-008 | Medium — indirectly exercised by ubpf_plugin; [GAP: no dedicated API-focused unit test] |
| REQ-JIT-007 | translate API | TC-JIT-007 | Low — [GAP: no direct translate API test] |
| REQ-JIT-008 | Instruction limit non-applicability | TC-JIT-012 | Low — [GAP: no test verifying JIT ignores instruction limit] |
| REQ-JIT-009 | x86-64 calling conventions | TC-JIT-009 | High — CI tests on Windows + Linux (different ABIs) |
| REQ-JIT-010 | ARM64 backend support | TC-JIT-010 | High — CI tests on ARM64 (native + QEMU) |
| REQ-JIT-011 | Post-compilation helper update | TC-JIT-013 | High — update_helpers, update_dispatcher custom tests |
4.5 ELF Loading
| REQ-ID | Requirement | Test Cases | Coverage |
|---|
| REQ-ELF-001 | ELF header validation | TC-ELF-002 | Medium — [GAP: no tests with malformed ELF headers] |
| REQ-ELF-002 | Section count limit | TC-ELF-008 | Low — [GAP: no test with >32 sections] |
| REQ-ELF-003 | ELF bounds checking | TC-ELF-003 | High — tests/elf/ directory |
| REQ-ELF-004 | R_BPF_64_64 data relocation | TC-ELF-004 | High — bpf/rel_64_32.bpf.c, tests/elf/ |
| REQ-ELF-005 | R_BPF_64_32 helper relocation | TC-ELF-005 | High — conformance suite helper tests |
| REQ-ELF-006 | ELF wrapper functions (load_elf) | TC-ELF-001 | High — test_elf.py |
| REQ-ELF-007 | Multi-function ELF linking | TC-ELF-006, TC-ELF-007 | Medium — tested via multi-function ELF programs; [GAP: no explicit named-main test] |
4.6 Instruction Set
| REQ-ID | Requirement | Test Cases | Coverage |
|---|
| REQ-ISA-001 | Instruction format (8 bytes) | TC-ISA-001 | High — assembler/raw comparison in all .data tests |
| REQ-ISA-002 | Register model (r0-r10) | TC-ISA-002 | High — frame_pointer custom test, JIT register offset variants |
| REQ-ISA-003 | ALU operations (32-bit and 64-bit) | TC-ISA-003, TC-ISA-004 | High — alu.data, alu64.data, 100+ conformance tests |
| REQ-ISA-004 | Signed division and modulo | TC-ISA-013 | High — sdiv32.data, sdiv64.data, smod32.data, smod64.data |
| REQ-ISA-005 | MOV with sign-extension (MOVSX) | TC-ISA-008 | High — conformance movsx tests |
| REQ-ISA-006 | Byte swap operations | TC-ISA-014 | High — conformance be16/32/64, le16/32/64 tests |
| REQ-ISA-007 | Memory load/store and LDDW | TC-ISA-005, TC-ISA-006 | High — ldx.data, st.data, stx.data, 80+ conformance tests (including lddw.data) |
| REQ-ISA-008 | Sign-extending loads | TC-ISA-007 | High — ldxsb-positive.data, ldxsh.data, conformance tests |
| REQ-ISA-009 | Jump instructions (64-bit and 32-bit) | TC-ISA-009, TC-ISA-010 | High — jmp.data, 40+ conformance jmp/jmp32 tests |
| REQ-ISA-010 | Atomic operations | TC-ISA-011 | Medium — atomic_validate custom test (validation only) |
| REQ-ISA-011 | CALL instruction variants | TC-ISA-012 | High — call.data, factorial.data |
| REQ-ISA-012 | EXIT instruction | TC-ISA-015 | High — early-exit.data, all tests terminate via EXIT |
4.7 Security
| REQ-ID | Requirement | Test Cases | Coverage |
|---|
| REQ-SEC-001 | Bounds checking | TC-SEC-001 | High — 10+ error tests (err-stack-oob, err-address-*) |
| REQ-SEC-002 | Bounds check toggle | TC-SEC-010 | Medium — implicitly tested (bounds on by default); [GAP: no explicit toggle test] |
| REQ-SEC-003 | Undefined behavior detection (shadow stack & registers) | TC-SEC-002, TC-SEC-008, TC-SEC-009 | Low — [GAP: no explicit UB detection, shadow stack, or shadow register tests] |
| REQ-SEC-004 | Constant blinding | TC-SEC-003 | High — constant_blinding custom test, CI env var |
| REQ-SEC-005 | Read-only bytecode | TC-SEC-004 | Medium — readonly_bytecode custom test (toggles mode; [GAP: no test verifying pages are actually read-only]) |
| REQ-SEC-006 | Pointer secret / XOR encoding | TC-SEC-005 | Low — [GAP: no test verifying XOR encoding effectiveness] |
| REQ-SEC-007 | Retpolines | TC-SEC-006 | Medium — CI runs with/without retpolines; no functional test |
| REQ-SEC-008 | W⊕X enforcement | TC-SEC-007 | Medium — implicitly tested by JIT execution |
| REQ-SEC-009 | Custom bounds check callback | TC-EXT-005 | Low — [GAP: no explicit custom bounds check test] |
4.8 Extensibility
| REQ-ID | Requirement | Test Cases | Coverage |
|---|
| REQ-EXT-001 | Helper registration | TC-EXT-001 | High — call.data, call-memfrob.data, update_helpers |
| REQ-EXT-002 | Helper function limit | TC-EXT-008 | Low — [GAP: no test filling all 64 helper slots] |
| REQ-EXT-003 | External dispatcher | TC-EXT-002 | High — 3 dispatcher custom tests |
| REQ-EXT-004 | Data relocation callback | TC-EXT-004 | Medium — tested via ELF loading |
| REQ-EXT-005 | Stack usage calculator | TC-EXT-006 | High — 3 custom_local_function_stack_size tests |
| REQ-EXT-006 | Debug function | TC-EXT-007 | High — debug_function custom test |
| REQ-EXT-007 | Unwind function | TC-EXT-003 | High — call_unwind.data |
4.9 Configuration
| REQ-ID | Requirement | Test Cases | Coverage |
|---|
| REQ-CFG-001 | Error print redirection | TC-CFG-001 | Medium — used in custom tests but not directly tested |
| REQ-CFG-002 | JIT buffer sizing | TC-CFG-002 | High — jit_buffer_too_small custom test |
| REQ-CFG-003 | Instruction limit | TC-CFG-003 | Low — [GAP: no instruction limit test] |
| REQ-CFG-004 | Register access (get/set) | TC-CFG-004 | Low — [GAP: no get/set register test] |
4.10 Platform
| REQ-ID | Requirement | Test Cases | Coverage |
|---|
| REQ-PLAT-001 | Windows support | TC-PLAT-001 | High — CI: windows-2022, Debug + Release |
| REQ-PLAT-002 | Linux support | TC-PLAT-002 | High — CI: ubuntu-latest, coverage + sanitizers |
| REQ-PLAT-003 | macOS support | TC-PLAT-003 | High — CI: macos-latest |
| REQ-PLAT-004 | JIT architecture support (x86-64) | TC-PLAT-004 | High — CI on all x86-64 platforms |
| REQ-PLAT-005 | Cryptographic random generation | TC-PLAT-007 | Low — [GAP: no dedicated test verifies RNG output or fallback behavior] |
| REQ-PLAT-006 | Platform atomic operations | TC-PLAT-008 | Medium — atomic_validate custom test; [GAP: no cross-platform atomic correctness test] |
4.11 Error Handling
| REQ-ID | Requirement | Test Cases | Coverage |
|---|
| REQ-ERR-001 | Error message allocation | TC-ERR-001 | High — error tests check stderr output |
| REQ-ERR-002 | Error output function | TC-ERR-002 | Medium — used but not directly validated |
| REQ-ERR-003 | Toggle return values | TC-ERR-003 | Medium — toggles used in custom tests |
4.12 Constants
| REQ-ID | Requirement | Test Cases | Coverage |
|---|
| REQ-CONST-001 | System constants | TC-CONST-001 | Medium — constants used throughout tests but not boundary-tested |
4.13 Safe Interpreter Profile
| REQ-ID | Requirement | Test Cases | Coverage |
|---|
| REQ-SAFE-001 | Additive safe execution profile | TC-SAFE-001 | High — safe-profile opt-in, immutability-after-load, interpreter-only execution, and legacy-vs-safe interpreter parity are covered in both local conformance runs and generated CTest cases |
| REQ-SAFE-002 | Tagged register provenance model | TC-SAFE-002 | Medium — stack-root and no-input-memory behavior are exercised indirectly, but explicit entry-state checks for R0/R3-R9 and R1-without-mem remain open |
| REQ-SAFE-003 | Provenance-checked memory access choke points | TC-SAFE-003 | Medium — pointer-backed loads/stores and opaque-handle rejection are covered; atomic-result scalar classification still needs direct coverage |
| REQ-SAFE-004 | Pointer arithmetic and tag propagation | TC-SAFE-004 | High — pointer add/subtract success and failure matrix, ALU32 tag clearing, and the common stack-frame address-computation idiom are covered |
| REQ-SAFE-005 | Typed helper metadata and return provenance | TC-SAFE-005 | Medium — typed pointer return success and missing-metadata rejection are covered; scalar-return and out-of-bounds return cases remain open |
| REQ-SAFE-006 | Descriptor-based external region metadata | TC-SAFE-006 | Low — single-region descriptor resolution is covered, but multi-region distinction and legacy-bounds-callback insufficiency are still gaps |
| REQ-SAFE-007 | Spill and call-frame provenance preservation | TC-SAFE-007 | Medium — spill restore, spill invalidation, and caller-saved reclassification are covered; direct callee-saved provenance restoration remains open |
| REQ-SAFE-008 | Initial safe-profile JIT unavailability | TC-SAFE-008 | High — explicit compile rejection is covered by a dedicated custom test |
5. Test Cases
TC-LIFE — VM Lifecycle
TC-LIFE-001: VM Creation
- Traces to: REQ-LIFE-001
- Level: Unit
- Confidence: High
- Evidence: Every test implicitly calls
ubpf_create() / ubpf_destroy() - Pass criteria: VM pointer is non-NULL, all subsequent operations succeed
- Existing tests: All test_vm.py, test_jit.py tests
TC-LIFE-002: VM Destruction / Memory Leaks
- Traces to: REQ-LIFE-005
- Level: Integration
- Confidence: Medium
- Evidence:
custom_tests/srcs/ubpf_test_reload_code_memleak.cc, Valgrind CI job - Pass criteria: No memory leaks reported by Valgrind; reload_code_memleak returns 0
- Existing tests: reload_code_memleak-Custom, Valgrind CI workflow
TC-LIFE-003: Code Unloading and Reloading
- Traces to: REQ-LIFE-006, REQ-LOAD-003
- Level: Integration
- Confidence: High
- Evidence:
tests/reload.data, tests/unload_reload.data - Pass criteria: VM accepts new code after unload; second execution produces correct result
- Existing tests: test_vm reload/unload_reload tests
TC-LIFE-004: Default Configuration Values
- Traces to: REQ-LIFE-002
- Level: Unit
- Confidence: Medium
- Evidence: Tested indirectly — defaults produce expected behavior in standard tests
- Pass criteria: Bounds checking enabled, constant blinding disabled, read-only mode enabled
[GAP]: No test explicitly verifies each default value after ubpf_create()
TC-LIFE-005: Platform JIT Selection
- Traces to: REQ-LIFE-004
- Level: System
- Confidence: High
- Evidence: CI matrix runs JIT tests on x86-64 (Windows/Linux/macOS) and ARM64
- Pass criteria: JIT compilation succeeds on supported platforms
TC-LIFE-006: Memory Allocation Failure
- Traces to: REQ-LIFE-003
- Level: Unit
- Confidence: Low
[GAP]: No test injects allocation failures. Would require mock allocator or ulimit.
TC-LOAD — Program Loading
TC-LOAD-001: Double-Load Prevention
- Traces to: REQ-LOAD-003
- Level: Unit
- Confidence: High
- Evidence: All
.data tests call ubpf_load as part of normal flow - Pass criteria: Loading code into a VM that already has code loaded returns an error
- Existing tests: All data-driven tests (implicit)
TC-LOAD-002: Code Length Validation
- Traces to: REQ-LOAD-001
- Level: Unit
- Confidence: Medium
[GAP]: No test for loading code with length that is not a multiple of 8 bytes.
TC-LOAD-003: Maximum Instruction Count
- Traces to: REQ-LOAD-002
- Level: Unit
- Confidence: Low
[GAP]: No test with 65536+ instructions to verify the maximum instruction count limit.
TC-LOAD-004: Instruction Validation
- Traces to: REQ-LOAD-004, REQ-LOAD-010, REQ-LOAD-011
- Level: Unit
- Confidence: High
- Evidence:
tests/errors/* invalid instruction tests, atomic_validate custom test - Pass criteria: Invalid instructions, out-of-range jump targets, and unpaired LDDW are rejected at load time
- Existing tests: tests/errors/*, atomic_validate-Custom
TC-LOAD-005: Stack Alignment Validation
- Traces to: REQ-LOAD-008
- Level: Unit
- Confidence: High
- Evidence:
custom_tests/srcs/ubpf_test_custom_local_function_stack_size.cc and unaligned variant - Pass criteria: Unaligned stack sizes are rejected
- Existing tests: custom_local_function_stack_size-Custom, custom_local_function_stack_size_unaligned-Custom
TC-LOAD-006: Sub-Program Containment
- Traces to: REQ-LOAD-009
- Level: Unit
- Confidence: Medium
- Evidence: Tested via local function call tests that validate sub-programs stay within bounds
- Pass criteria: Sub-programs that exceed the program boundary are rejected
- Existing tests: Local call tests (indirect)
TC-LOAD-007: Read-Only Bytecode Storage (Enabled)
- Traces to: REQ-LOAD-005
- Level: Unit
- Confidence: Medium
- Evidence:
custom_tests/srcs/ubpf_test_readonly_bytecode.cc - Pass criteria: Bytecode pages are marked read-only when feature is enabled
- Existing tests: readonly_bytecode-Custom
[GAP]: No test verifying pages are actually read-only (e.g., via write-and-trap).
TC-LOAD-008: Read-Only Bytecode Storage (Disabled)
- Traces to: REQ-LOAD-005
- Level: Unit
- Confidence: Medium
- Evidence:
custom_tests/srcs/ubpf_test_readonly_bytecode.cc toggles mode - Pass criteria: Bytecode is writable when read-only mode is disabled
- Existing tests: readonly_bytecode-Custom
TC-LOAD-009: Pointer Secret Encoding
- Traces to: REQ-LOAD-006
- Level: Unit
- Confidence: Medium
[GAP]: No direct test of pointer secret encoding correctness. Encoding is exercised implicitly via all interpreter tests.
TC-LOAD-010: Local Function Marking
- Traces to: REQ-LOAD-007
- Level: Unit
- Confidence: High
- Evidence:
tests/extensions/call_local_use_stack.data, tests/factorial.data - Pass criteria: Local functions are correctly identified and callable
- Existing tests: call_local_use_stack, factorial
TC-ELF — ELF Loading
TC-ELF-001: ELF Wrapper Functions
- Traces to: REQ-ELF-006
- Level: System
- Confidence: High
- Evidence:
test_framework/test_elf.py runs ELF-based tests - Pass criteria:
ubpf_load_elf() successfully loads valid ELF files and programs execute correctly - Existing tests: test_elf.py
TC-ELF-002: ELF Header Validation
- Traces to: REQ-ELF-001
- Level: Unit
- Confidence: Medium
[GAP]: No tests with malformed ELF headers (wrong magic, wrong class, wrong machine type).
TC-ELF-003: ELF Bounds Checking
- Traces to: REQ-ELF-003
- Level: Unit
- Confidence: High
- Evidence:
tests/elf/ directory contains ELF-specific test programs - Pass criteria: Out-of-bounds section references in ELF files are rejected
- Existing tests: tests/elf/*
TC-ELF-004: R_BPF_64_64 Data Relocation
- Traces to: REQ-ELF-004
- Level: Integration
- Confidence: High
- Evidence:
bpf/rel_64_32.bpf.c, tests/elf/ relocation tests - Pass criteria: 64-bit data relocations are resolved correctly
- Existing tests: tests/elf/*, bpf/rel_64_32.bpf.c
TC-ELF-005: R_BPF_64_32 Helper Relocation
- Traces to: REQ-ELF-005
- Level: Integration
- Confidence: High
- Evidence: Conformance suite helper tests exercise helper relocations
- Pass criteria: 32-bit helper function relocations are resolved correctly
- Existing tests: Conformance helper tests
TC-ELF-006: Multi-Function ELF Linking
- Traces to: REQ-ELF-007
- Level: Integration
- Confidence: Medium
- Evidence: Multi-function ELF programs tested via ELF loader
- Pass criteria: Multiple functions within an ELF are correctly linked and callable
- Existing tests: Multi-function ELF programs (indirect)
TC-ELF-007: Main Function Selection
- Traces to: REQ-ELF-007
- Level: Integration
- Confidence: Medium
[GAP]: No explicit test for named-main function selection in multi-function ELF files.
TC-ELF-008: Section Count Limit
- Traces to: REQ-ELF-002
- Level: Unit
- Confidence: Low
[GAP]: No test with >32 sections to verify the section count limit is enforced.
TC-EXEC — Execution
TC-EXEC-001: Interpreter Execution (Data-Driven)
- Traces to: REQ-EXEC-001, REQ-EXEC-003, REQ-EXEC-007
- Level: Unit
- Confidence: High
- Evidence:
test_framework/test_vm.py — runs every .data file through interpreter - Pass criteria: Return value matches
-- result section; errors match -- error section - Existing tests: 104 repository
.data files via test_vm.py, plus 417 plugin-driven interpreter runs (104 local + 313 conformance)
TC-EXEC-002: Extended Interpreter Entry Point
- Traces to: REQ-EXEC-002
- Level: Unit
- Confidence: Medium
[GAP]: Limited direct exec_ex tests. No dedicated test exercises ubpf_exec_ex() API independently from standard ubpf_exec().
TC-EXEC-003: Register Initialization
- Traces to: REQ-EXEC-003
- Level: Unit
- Confidence: High
- Evidence: Memory and result comparison in all data-driven tests validates correct r1/r2 initialization
- Pass criteria: r1 points to memory input, r2 contains memory length, r0 returns correct result
- Existing tests: All local
test_vm.py data-driven tests plus plugin-driven interpreter coverage
TC-EXEC-004: Code-Not-Loaded Guard and XOR-Decoded Fetch
- Traces to: REQ-EXEC-004, REQ-EXEC-007
- Level: Unit
- Confidence: Medium
- Evidence: XOR decode is implicit in all 360+ data-driven tests (instructions are encoded on load)
- Pass criteria: Execution without loaded code returns error; XOR-decoded instructions execute correctly
[GAP]: No explicit test for executing without loading code first.
TC-EXEC-005: ALU Operations
- Traces to: REQ-ISA-003, REQ-ISA-004
- Level: Unit
- Confidence: High
- Evidence:
tests/alu.data, tests/alu64.data, tests/sdiv32.data, tests/sdiv64.data, tests/smod32.data, tests/smod64.data, tests/arsh*.data, 100+ conformance ALU tests - Pass criteria: Correct arithmetic results for all operations, all operand types
- Existing tests: Comprehensive coverage of ADD, SUB, MUL, DIV, MOD, OR, AND, XOR, LSH, RSH, ARSH, NEG, MOV, SDIV, SMOD
TC-EXEC-006: Memory Bounds Checking
- Traces to: REQ-SEC-001
- Level: Unit
- Confidence: High
- Evidence:
tests/errors/err-stack-oob.data, tests/errors/err-address-overflow-offset.data, tests/errors/err-address-underflow.data, tests/errors/err-integer-overflow-bounds.data - Pass criteria: Out-of-bounds access produces error (non-zero exit, error message)
- Existing tests: 4+ dedicated error tests
TC-EXEC-007: Local Function Calls
- Traces to: REQ-EXEC-006
- Level: Integration
- Confidence: High
- Evidence:
tests/factorial.data, tests/extensions/call_local_use_stack.data, tests/stack2.data, tests/stack3.data, custom_local_function_stack_size tests - Pass criteria: Correct return values; callee-saved registers (r6-r9) preserved; frame pointer (r10) adjusted correctly
- Existing tests: 5+ tests covering local calls
TC-EXEC-008: External Helper Calls
- Traces to: REQ-EXEC-008, REQ-EXT-001
- Level: Integration
- Confidence: High
- Evidence:
tests/helpers/call.data, tests/helpers/call-memfrob.data, tests/helpers/call-save.data - Pass criteria: Helper receives correct parameters; return value propagated to r0
- Existing tests: 3 dedicated helper tests + conformance call tests
TC-EXEC-009: Instruction Limit Enforcement
- Traces to: REQ-EXEC-005
- Level: Unit
- Confidence: Low
[GAP]: No test currently exercises ubpf_set_instruction_limit(). Should verify interpreter stops after N instructions.
TC-EXEC-010: Debug Callback Invocation
- Traces to: REQ-EXEC-009
- Level: Unit
- Confidence: High
- Evidence:
custom_tests/srcs/ubpf_test_debug_function.cc - Pass criteria: Debug callback invoked before each instruction with correct PC, registers, and stack info
- Existing tests: debug_function-Custom
TC-ISA — Instruction Set Architecture
TC-ISA-001: Instruction Format
- Traces to: REQ-ISA-001
- Level: Unit
- Confidence: High
- Evidence: Assembler/raw comparison in all
.data tests validates instruction encoding - Pass criteria: Instructions are correctly encoded and decoded in the 8-byte format
- Existing tests: 104 local data-driven tests plus plugin-driven coverage over the 313-test conformance suite
TC-ISA-002: Register Model
- Traces to: REQ-ISA-002
- Level: Unit
- Confidence: High
- Evidence:
custom_tests/srcs/ubpf_test_frame_pointer.cc, JIT register offset variants - Pass criteria: All 11 registers (r0-r10) function correctly; r10 is read-only frame pointer
- Existing tests: frame_pointer-Custom, JIT offset tests
TC-ISA-003: ALU64 Operations
- Traces to: REQ-ISA-003
- Level: Unit
- Confidence: High
- Evidence:
tests/alu64.data, 50+ conformance ALU64 tests - Pass criteria: All 64-bit ALU operations produce correct results
- Existing tests: alu64, conformance ALU64 tests
TC-ISA-004: ALU32 Operations
- Traces to: REQ-ISA-003
- Level: Unit
- Confidence: High
- Evidence:
tests/alu.data, 50+ conformance ALU32 tests - Pass criteria: All 32-bit ALU operations produce correct results with zero-extension
- Existing tests: alu, conformance ALU32 tests
TC-ISA-005: Memory Load/Store
- Traces to: REQ-ISA-007
- Level: Unit
- Confidence: High
- Evidence:
tests/ldx.data, tests/st.data, tests/stx.data, 80+ conformance memory tests - Pass criteria: All memory load and store operations at all widths (8/16/32/64) produce correct results
- Existing tests: ldx, st, stx, conformance memory tests
TC-ISA-006: LDDW (64-bit Immediate Load)
- Traces to: REQ-ISA-007
- Level: Unit
- Confidence: High
- Evidence:
external/bpf_conformance/tests/lddw.data, conformance LDDW tests - Pass criteria: 64-bit immediate values are correctly loaded via two-instruction LDDW
- Existing tests: lddw, conformance LDDW tests
TC-ISA-007: Sign-Extending Loads
- Traces to: REQ-ISA-008
- Level: Unit
- Confidence: High
- Evidence:
tests/ldxsb-positive.data, tests/ldxsh.data, conformance sign-extension tests - Pass criteria: Sign-extending loads correctly extend signed values to 64 bits
- Existing tests: ldxsb-positive, ldxsh, conformance tests
TC-ISA-008: MOVSX (Sign-Extending Move)
- Traces to: REQ-ISA-005
- Level: Unit
- Confidence: High
- Evidence: Conformance MOVSX tests
- Pass criteria: MOVSX instructions correctly sign-extend source to destination register
- Existing tests: Conformance MOVSX tests
TC-ISA-009: Jump Instructions (64-bit)
- Traces to: REQ-ISA-009
- Level: Unit
- Confidence: High
- Evidence:
tests/jmp.data, 40+ conformance jump tests - Pass criteria: All conditional and unconditional jumps with 64-bit comparisons branch correctly
- Existing tests: jmp, conformance jump tests
TC-ISA-010: JMP32 (32-bit Jumps)
- Traces to: REQ-ISA-009
- Level: Unit
- Confidence: High
- Evidence: Conformance JMP32 tests
- Pass criteria: All conditional jumps with 32-bit comparisons branch correctly
- Existing tests: Conformance JMP32 tests
TC-ISA-011: Atomic Operations
- Traces to: REQ-ISA-010
- Level: Unit
- Confidence: Medium
- Evidence:
custom_tests/srcs/ubpf_test_atomic_validate.cc (validation only) - Pass criteria: Atomic instructions are validated at load time
- Existing tests: atomic_validate-Custom
[GAP]: No runtime execution test for atomic operations; only validation is tested.
TC-ISA-012: CALL Instruction
- Traces to: REQ-ISA-011
- Level: Unit
- Confidence: High
- Evidence:
tests/helpers/call.data, tests/factorial.data - Pass criteria: CALL instruction correctly invokes helper functions and local functions
- Existing tests: call, factorial
TC-ISA-013: Signed Division and Modulo
- Traces to: REQ-ISA-004
- Level: Unit
- Confidence: High
- Evidence:
tests/sdiv32.data, tests/sdiv64.data, tests/smod32.data, tests/smod64.data - Pass criteria: Signed division and modulo produce correct results including negative operands
- Existing tests: sdiv32, sdiv64, smod32, smod64
TC-ISA-014: Byte Swap Operations
- Traces to: REQ-ISA-006
- Level: Unit
- Confidence: High
- Evidence: Conformance BE16/32/64, LE16/32/64 tests
- Pass criteria: Byte swap operations correctly convert endianness at all widths
- Existing tests: Conformance BE/LE tests
TC-ISA-015: EXIT Instruction
- Traces to: REQ-ISA-012
- Level: Unit
- Confidence: High
- Evidence:
tests/early-exit.data, all tests terminate via EXIT instruction - Pass criteria: EXIT instruction terminates execution and returns r0
- Existing tests: early-exit, all data-driven tests
TC-JIT — JIT Compilation
TC-JIT-001: JIT Execution Correctness
- Traces to: REQ-JIT-001, REQ-JIT-002
- Level: System
- Confidence: High
- Evidence:
test_framework/test_jit.py — runs every .data file through JIT with 20 register-offset variants - Pass criteria: JIT output matches interpreter output for all tests
- Existing tests: 104 local
.data files with up to 20 register-offset variants, plus 417 plugin-driven JIT runs (104 local + 313 conformance)
TC-JIT-002: compile_ex API
- Traces to: REQ-JIT-002
- Level: Integration
- Confidence: Medium
- Evidence:
ubpf_plugin in ExtendedJitMode exercises ubpf_compile_ex() - Pass criteria: Extended JIT compilation API succeeds and produces executable code
- Existing tests: ubpf_plugin ExtendedJitMode tests
TC-JIT-003: BasicJitMode
- Traces to: REQ-JIT-002
- Level: System
- Confidence: High
- Evidence: Default mode in
test_framework/test_jit.py - Pass criteria: JIT compilation in basic mode produces correct results for all tests
- Existing tests: test_jit.py (default mode)
TC-JIT-004: ExtendedJitMode
- Traces to: REQ-JIT-002
- Level: System
- Confidence: Medium
- Evidence:
ubpf_plugin with --jit flag exercises extended JIT mode - Pass criteria: JIT compilation in extended mode produces correct results
- Existing tests: ubpf_plugin with --jit
TC-JIT-005: Code Caching
- Traces to: REQ-JIT-003
- Level: Unit
- Confidence: Low
[GAP]: No explicit caching test. No test verifies that compiled JIT code is reused across invocations.
TC-JIT-006: W⊕X Memory
- Traces to: REQ-JIT-004
- Level: Integration
- Confidence: Medium
- Evidence: Implicit; ASan would catch memory protection violations
- Pass criteria: JIT-compiled code memory is not simultaneously writable and executable
- Existing tests: All JIT tests with ASan (implicit)
TC-JIT-007: translate API
- Traces to: REQ-JIT-007
- Level: Unit
- Confidence: Low
[GAP]: No direct test of the ubpf_translate() API for outputting JIT code to an external buffer.
TC-JIT-008: copy_jit API
- Traces to: REQ-JIT-006
- Level: Unit
- Confidence: Medium
- Evidence:
ubpf_plugin/ubpf_plugin.cc copies JIT output into an executable mapping and executes the copy, comparing it with the original JIT result. - Pass criteria: Copied JIT code executes independently and matches the original JIT result.
[GAP]: No dedicated unit test isolates ubpf_copy_jit() failure modes beyond the plugin path.
TC-JIT-009: x86-64 Dual ABI
- Traces to: REQ-JIT-009
- Level: System
- Confidence: High
- Evidence: CI runs JIT tests on both Windows (Win64 ABI) and Linux (System V ABI)
- Pass criteria: Same tests pass on both platforms
- Existing tests: CI matrix covers both ABIs
TC-JIT-010: ARM64 Backend Support
- Traces to: REQ-JIT-010
- Level: System
- Confidence: High
- Evidence: CI on ARM64 (native + QEMU emulation)
- Pass criteria: JIT compilation and execution succeeds on ARM64 architecture
- Existing tests: CI matrix (ARM64 native and QEMU)
TC-JIT-011: JIT Buffer Too Small
- Traces to: REQ-JIT-005, REQ-CFG-002
- Level: Unit
- Confidence: High
- Evidence:
custom_tests/srcs/ubpf_test_jit_buffer_too_small.cc - Pass criteria: JIT compilation fails gracefully with error message
- Existing tests: jit_buffer_too_small-Custom
TC-JIT-012: Instruction Limit Non-Applicability
- Traces to: REQ-JIT-008
- Level: Unit
- Confidence: Low
[GAP]: No test verifying that ubpf_set_instruction_limit() does not affect JIT execution.
TC-JIT-013: Post-Compilation Helper Update
- Traces to: REQ-JIT-011
- Level: Integration
- Confidence: High
- Evidence:
custom_tests/srcs/ubpf_test_update_helpers.cc, ubpf_test_update_dispatcher.cc - Pass criteria: Helpers/dispatcher can be updated after JIT compilation; updated functions are called
- Existing tests: update_helpers-Custom, update_dispatcher-Custom
TC-SEC — Security
TC-SEC-001: Bounds Check Enforcement
- Traces to: REQ-SEC-001
- Level: Unit
- Confidence: High
- Evidence:
tests/errors/err-stack-oob.data and related error tests - Pass criteria: OOB access rejected with error
- Existing tests: 10+ error condition tests
TC-SEC-003: Constant Blinding
- Traces to: REQ-SEC-004
- Level: Integration
- Confidence: High
- Evidence:
custom_tests/srcs/ubpf_test_constant_blinding.cc, CI runs with UBPF_ENABLE_CONSTANT_BLINDING=1 - Pass criteria: JIT produces correct results with blinding enabled; all CTest passes with blinding
- Existing tests: constant_blinding-Custom, CI environment flag
TC-SEC-004: Read-Only Bytecode
- Traces to: REQ-SEC-005
- Level: Unit
- Confidence: High
- Evidence:
custom_tests/srcs/ubpf_test_readonly_bytecode.cc - Pass criteria: Bytecode stored in read-only pages; toggling mode works correctly
- Existing tests: readonly_bytecode-Custom
TC-SEC-005: Pointer Secret / XOR Encoding
- Traces to: REQ-SEC-006
- Level: Unit
- Confidence: Low
[GAP]: No test verifying XOR encoding effectiveness or that pointer secret changes instruction storage.
TC-SEC-006: Retpolines
- Traces to: REQ-SEC-007
- Level: System
- Confidence: Medium
- Evidence: CI runs both with and without
UBPF_DISABLE_RETPOLINES - Pass criteria: Tests pass in both configurations
- Existing tests: CI matrix (no dedicated functional test)
TC-SEC-007: W⊕X Enforcement
- Traces to: REQ-SEC-008
- Level: Integration
- Confidence: Medium
- Evidence: JIT code executes successfully; ASan/Valgrind would detect violations
- Pass criteria: JIT memory is executable but not writable during execution
- Existing tests: Implicitly tested by all JIT tests
TC-SEC-010: Bounds Check Toggle
- Traces to: REQ-SEC-002
- Level: Unit
- Confidence: Medium
[GAP]: No explicit test toggling bounds checking off and verifying behavior change.
TC-SEC-002: Undefined Behavior Detection
- Traces to: REQ-SEC-003
- Level: Unit
- Confidence: Low
[GAP]: No test enabling UB detection and verifying uninitialized register/stack reads are flagged.
TC-SEC-008: Shadow Stack
- Traces to: REQ-SEC-003
- Level: Unit
- Confidence: Low
[GAP]: No test verifying shadow stack bit tracking (marks on write, checks on read).
TC-SEC-009: Shadow Registers
- Traces to: REQ-SEC-003
- Level: Unit
- Confidence: Low
[GAP]: No test verifying shadow register bitmask tracking for uninitialized register detection.
TC-EXT — Extensibility
TC-EXT-001: Helper Registration
- Traces to: REQ-EXT-001
- Level: Unit
- Confidence: High
- Evidence:
tests/helpers/call.data, tests/helpers/call-memfrob.data, custom_tests/srcs/ubpf_test_update_helpers.cc - Pass criteria: Helper functions are registered and callable by BPF programs via CALL instruction
- Existing tests: call, call-memfrob, update_helpers-Custom
TC-EXT-002: External Dispatcher
- Traces to: REQ-EXT-003
- Level: Integration
- Confidence: High
- Evidence:
custom_tests/srcs/ubpf_test_external_dispatcher_simple_context.cc, ubpf_test_external_dispatcher_context_overwrite.cc, ubpf_test_default_dispatcher_helper_context.cc, ubpf_test_update_dispatcher.cc - Pass criteria: Dispatcher receives correct parameters; context handling correct; updates work
- Existing tests: 4 custom tests
TC-EXT-003: Unwind Function
- Traces to: REQ-EXT-007
- Level: Unit
- Confidence: High
- Evidence:
tests/extensions/call_unwind.data - Pass criteria: Unwind function is called on error; execution terminates with correct error code
- Existing tests: call_unwind
TC-EXT-004: Data Relocation Callback
- Traces to: REQ-EXT-004
- Level: Integration
- Confidence: Medium
- Evidence: Tested via ELF loading pipeline
- Pass criteria: Data relocation callback is invoked for map references during ELF loading
- Existing tests: ELF loading tests (indirect)
TC-EXT-005: Custom Bounds Check Callback
- Traces to: REQ-SEC-009
- Level: Unit
- Confidence: Low
[GAP]: No test registering a custom bounds check callback via ubpf_register_data_bounds_check() and verifying it is invoked during memory access.
TC-EXT-006: Stack Usage Calculator
- Traces to: REQ-EXT-005
- Level: Unit
- Confidence: High
- Evidence:
custom_tests/srcs/ubpf_test_custom_local_function_stack_size.cc, *_unaligned.cc, *_zero.cc, ubpf_test_default_local_function_stack_size.cc - Pass criteria: Custom stack sizes applied; unaligned rejected; zero accepted; default works
- Existing tests: 4 custom tests
TC-EXT-007: Debug Function
- Traces to: REQ-EXT-006
- Level: Unit
- Confidence: High
- Evidence:
custom_tests/srcs/ubpf_test_debug_function.cc - Pass criteria: Debug function callback is invoked before each instruction with correct state
- Existing tests: debug_function-Custom
TC-EXT-008: Helper Function Limit
- Traces to: REQ-EXT-002
- Level: Unit
- Confidence: Low
[GAP]: No test filling all 64 helper slots to verify the helper function registration limit.
TC-CFG — Configuration
TC-CFG-001: Error Print Redirection
- Traces to: REQ-CFG-001
- Level: Unit
- Confidence: Medium
- Evidence: Used in custom tests but not directly tested for correctness
- Pass criteria: Error output is redirected to the configured print function
- Existing tests: Custom tests (indirect)
TC-CFG-002: JIT Buffer Sizing
- Traces to: REQ-CFG-002
- Level: Unit
- Confidence: High
- Evidence:
custom_tests/srcs/ubpf_test_jit_buffer_too_small.cc - Pass criteria: JIT buffer size can be configured; undersized buffer causes compilation failure
- Existing tests: jit_buffer_too_small-Custom
TC-CFG-003: Instruction Limit
- Traces to: REQ-CFG-003
- Level: Unit
- Confidence: Low
[GAP]: No test exercises ubpf_set_instruction_limit() to verify instruction count limiting.
TC-CFG-004: Register Access
- Traces to: REQ-CFG-004
- Level: Unit
- Confidence: Low
[GAP]: No test exercises get/set register APIs to verify register access functionality.
TC-PLAT — Platform Support
TC-PLAT-001: Windows Support
- Traces to: REQ-PLAT-001
- Level: System
- Confidence: High
- Evidence: CI: windows-2022, Debug + Release configurations
- Pass criteria: All tests pass on Windows with MSVC
- Existing tests: CI matrix (windows-2022)
TC-PLAT-002: Linux Support
- Traces to: REQ-PLAT-002
- Level: System
- Confidence: High
- Evidence: CI: ubuntu-latest, coverage + sanitizers (ASan, UBSan)
- Pass criteria: All tests pass on Linux with GCC/Clang; no sanitizer violations
- Existing tests: CI matrix (ubuntu-latest)
TC-PLAT-003: macOS Support
- Traces to: REQ-PLAT-003
- Level: System
- Confidence: High
- Evidence: CI: macos-latest
- Pass criteria: All tests pass on macOS
- Existing tests: CI matrix (macos-latest)
TC-PLAT-004: x86-64 JIT
- Traces to: REQ-PLAT-004
- Level: System
- Confidence: High
- Evidence: CI runs JIT tests on all x86-64 platforms (Windows, Linux, macOS)
- Pass criteria: JIT compilation and execution succeeds on x86-64
- Existing tests: CI matrix (all x86-64 platforms)
TC-PLAT-007: Crypto RNG
- Traces to: REQ-PLAT-005
- Level: System
- Confidence: Low
- Evidence: Source inspection shows platform branches in
vm/ubpf_jit_support.c, but no dedicated runtime assertion validates RNG output or fallback selection. [GAP]: No test verifies BCryptGenRandom, getrandom, arc4random_buf, or the rand() fallback behavior.
TC-PLAT-008: Platform Atomics
- Traces to: REQ-PLAT-006
- Level: System
- Confidence: Medium
[GAP]: No cross-platform atomic correctness test. Atomics are compiled but not tested for cross-platform behavior.
TC-ERR — Error Handling
TC-ERR-001: Error Message Allocation
- Traces to: REQ-ERR-001
- Level: Unit
- Confidence: High
- Evidence: Error tests check stderr output for correct error messages
- Pass criteria: Error messages are allocated and returned correctly via the error string parameter
- Existing tests: tests/errors/* (error message verification)
TC-ERR-002: Error Output Function
- Traces to: REQ-ERR-002
- Level: Unit
- Confidence: Medium
- Evidence: Error output function is used but not directly validated for correct invocation
- Pass criteria: Custom error output function receives formatted error messages
- Existing tests: Custom tests (indirect)
TC-ERR-003: Toggle Return Values
- Traces to: REQ-ERR-003
- Level: Unit
- Confidence: Medium
- Evidence: Toggle functions return values are used in custom tests
- Pass criteria: Toggle functions return previous state value
- Existing tests: Custom tests (indirect)
TC-CONST — Constants
TC-CONST-001: System Constants
- Traces to: REQ-CONST-001
- Level: Unit
- Confidence: Medium
- Evidence: Constants (MAX_INSTS, STACK_SIZE, etc.) are used throughout tests but not boundary-tested
- Pass criteria: System constants are correctly defined and enforced at boundaries
- Existing tests: All tests (indirect usage)
TC-SAFE — Safe Interpreter Profile
TC-SAFE-001: Safe-Profile Compatibility Gate
- Traces to: REQ-SAFE-001
- Level: Integration
- Confidence: Medium
- Evidence:
custom_tests/srcs/ubpf_test_safe_profile_compile_rejection.cc; ubpf_plugin/CMakeLists.txt; ubpf_plugin/ubpf_plugin.cc exercised against external/bpf_conformance/tests with --profile legacy --interpret and --profile safe --interpret - Pass criteria:
ubpf_set_execution_profile() opts a VM into safe mode before load, rejects profile changes after load, and leaves interpreter execution available while JIT remains rejected. - Existing tests:
ubpf_test_safe_profile_compile_rejection-Custom; per-file *-Interpreter and *-Safe-Interpreter CTest cases generated from external/bpf_conformance/tests/*.data and tests/*.data - Remaining gap: Extend parity coverage beyond the default v3 interpreter matrix to typed-pointer helper scenarios that require region descriptors.
TC-SAFE-002: Root Provenance Initialization
- Traces to: REQ-SAFE-002
- Level: Unit
- Confidence: Medium
- Evidence:
custom_tests/srcs/ubpf_test_safe_profile_spills_and_local_calls.cc, custom_tests/srcs/ubpf_test_safe_profile_pointer_arithmetic.cc - Pass criteria: Safe-profile entry initializes stack-root provenance correctly, rejects use of reclassified scalars as pointers, and preserves only explicit provenance-bearing values.
- Existing tests:
ubpf_test_safe_profile_spills_and_local_calls-Custom, ubpf_test_safe_profile_pointer_arithmetic-Custom - Remaining gap: Add explicit checks for R0/R3-R9 scalar entry state and for R1 being scalar when
mem == NULL.
TC-SAFE-003: Safe Dereference Choke Points
- Traces to: REQ-SAFE-003
- Level: Unit
- Confidence: Medium
- Evidence:
custom_tests/srcs/ubpf_test_safe_profile_helpers.cc, custom_tests/srcs/ubpf_test_safe_profile_spills_and_local_calls.cc - Pass criteria: Safe-mode dereferences succeed only through pointer-tagged registers within region bounds; dereference through handles or reclassified scalars fails before host access.
- Existing tests:
ubpf_test_safe_profile_helpers-Custom, ubpf_test_safe_profile_spills_and_local_calls-Custom - Remaining gap: Add direct atomic coverage showing fetch-result registers are classified as scalars.
TC-SAFE-004: Pointer Arithmetic Matrix
- Traces to: REQ-SAFE-004
- Level: Unit
- Confidence: Medium
- Evidence:
custom_tests/srcs/ubpf_test_safe_profile_pointer_arithmetic.cc, custom_tests/srcs/ubpf_test_safe_profile_spills_and_local_calls.cc, external/bpf_conformance/tests/stack.data - Pass criteria: Pointer-plus-pointer and scalar-minus-pointer fail, same-region pointer subtraction produces a scalar, different-region pointer subtraction fails, and pointer-plus-scalar / pointer-minus-scalar remain usable for valid stack access.
- Existing tests:
ubpf_test_safe_profile_pointer_arithmetic-Custom, ubpf_test_safe_profile_spills_and_local_calls-Custom; local bpf_conformance_runner execution of stack.data with --profile safe --interpret
TC-SAFE-005: Typed Helper Return Validation
- Traces to: REQ-SAFE-005
- Level: Integration
- Confidence: Medium
- Evidence:
custom_tests/srcs/ubpf_test_safe_profile_helpers.cc - Pass criteria: Helpers with safe descriptors can return typed pointers or handles, and helper calls without safe metadata fail before dispatch.
- Existing tests:
ubpf_test_safe_profile_helpers-Custom - Remaining gap: Add scalar-return and out-of-bounds-pointer negative cases.
TC-SAFE-006: External Region Descriptor Resolution
- Traces to: REQ-SAFE-006
- Level: Integration
- Confidence: Low
- Evidence:
custom_tests/srcs/ubpf_test_safe_profile_helpers.cc - Pass criteria: Safe helper metadata resolves to registered region descriptors, and returned pointers remain constrained to their registered region.
- Existing tests:
ubpf_test_safe_profile_helpers-Custom - Remaining gap: Add two-disjoint-region coverage and a regression proving the legacy bool bounds callback alone does not establish provenance.
TC-SAFE-007: Spill and Local-Call Provenance
- Traces to: REQ-SAFE-007
- Level: Integration
- Confidence: Medium
- Evidence:
custom_tests/srcs/ubpf_test_safe_profile_spills_and_local_calls.cc - Pass criteria: Full-width stack spills restore provenance, partial writes invalidate it, and caller-saved registers lose provenance on local-call return.
- Existing tests:
ubpf_test_safe_profile_spills_and_local_calls-Custom - Remaining gap: Add a direct callee-saved provenance-preservation case using R6-R9 across a local call.
TC-SAFE-008: Safe-Profile Compile Rejection
- Traces to: REQ-SAFE-008
- Level: Unit
- Confidence: High
- Evidence:
custom_tests/srcs/ubpf_test_safe_profile_compile_rejection.cc - Pass criteria:
ubpf_compile*() and ubpf_translate*() reject safe-profile VMs with an explicit interpreter-only error. - Existing tests:
ubpf_test_safe_profile_compile_rejection-Custom
TC-FUZZ — Fuzzing
TC-FUZZ-001: Differential Interpreter/JIT Testing
- Traces to: REQ-EXEC-007, REQ-JIT-001
- Level: System
- Confidence: High
- Evidence:
libfuzzer/libfuzz_harness.cc - Pass criteria: Interpreter and JIT produce identical results for all generated inputs
- Existing tests: Daily 1-hour fuzzing runs, corpus regression in CI
TC-FUZZ-002: PREVAIL Verifier Integration
- Traces to: REQ-EXEC-007
- Level: System
- Confidence: Medium
- Evidence:
libfuzzer/libfuzz_harness.cc with UBPF_FUZZER_VERIFY_BYTE_CODE=1 - Pass criteria: Verifier-approved programs execute without crashes
- Existing tests: Fuzzer with verifier enabled
6. Risk-Based Test Prioritization
6.1 Risk Categories
| Risk ID | Category | Impact | Likelihood | Priority |
|---|
| R1 | JIT produces incorrect results | Critical — silent data corruption | Medium | P1 |
| R2 | Bounds check bypass | Critical — arbitrary memory access | Low | P1 |
| R3 | Memory corruption in VM | Critical — host process crash | Medium | P1 |
| R4 | ELF loader accepts malformed input | High — potential code execution | Medium | P2 |
| R5 | Constant blinding bypass | High — JIT spraying attack | Low | P2 |
| R6 | Platform-specific failures | Medium — limited to one platform | Medium | P2 |
| R7 | Helper function parameter corruption | Medium — incorrect helper behavior | Low | P3 |
| R8 | Stack overflow in local calls | Medium — program crash | Low | P3 |
| R9 | Configuration API misuse | Low — unexpected behavior | Medium | P3 |
| R10 | Safe-profile provenance bypass | Critical — verifier-like memory safety defeated | Medium | P1 |
6.2 Prioritization Rationale
P1 (Must test): JIT correctness, bounds checking, memory safety, and safe-profile provenance enforcement — these are the core security and correctness guarantees.
- Covered by: Differential fuzzing (TC-FUZZ-001), error tests (TC-SEC-001), sanitizers (ASan/UBSan), Valgrind
- Gap: Safe-profile provenance coverage exists, but direct regressions for null-input root state, multi-region descriptors, and legacy-vs-safe side-by-side behavior remain open
P2 (Should test): ELF robustness, constant blinding effectiveness, platform parity — important but lower likelihood.
- Covered by: CI matrix (TC-PLAT-*), constant blinding tests (TC-SEC-003), some ELF tests
- Gap: No adversarial ELF fuzzing
P3 (Nice to test): Helper correctness, stack depth, configuration edge cases — lower impact.
- Covered by: Helper tests (TC-EXT-001), stack tests (TC-EXEC-007)
- Gaps: Instruction limit, register get/set, deep call chains
7. Pass/Fail Criteria
7.1 Entry Criteria
Before test execution:
- Code compiles successfully on all target platforms
- All submodules initialized (
git submodule update --init --recursive) - Test dependencies installed (Python: parcon, nose, pyelftools)
- Environment configured (platform-specific build prerequisites)
7.2 Exit Criteria
Test suite passes when:
- All CTest tests pass on every CI platform (Windows, Linux, macOS, ARM64)
- Zero ASan/UBSan violations in sanitizer builds
- Zero Valgrind errors (Linux)
- Fuzzer runs for 1 hour without finding new crashes
- Code coverage does not decrease vs. previous baseline (Coveralls)
7.3 Acceptance Thresholds
| Metric | Threshold | Current Status |
|---|
| CTest pass rate | 100% | Enforced by CI |
| ASan violations | 0 | Enforced by CI |
| Valgrind errors | 0 | Enforced by CI (Linux) |
| Fuzzer crashes | 0 new | Enforced by CI |
| Code coverage | Non-decreasing | Tracked by Coveralls |
8. Coverage Gap Summary
8.1 High-Priority Gaps
| Gap | REQ-IDs Affected | Risk | Recommendation |
|---|
| No UB detection tests | REQ-SEC-003 | Medium | Add tests enabling UB checks, verify shadow stack/register detection |
| No instruction limit test | REQ-CFG-003 | Low | Add test setting limit and verifying execution stops |
| No malformed ELF tests | REQ-ELF-001 | Medium | Fuzz the ELF loader with invalid headers/sections |
| No register get/set tests | REQ-CFG-004 | Low | Add test calling ubpf_set_registers/ubpf_get_registers |
| No custom bounds check test | REQ-SEC-009 | Medium | Add test registering custom bounds check callback |
8.2 Medium-Priority Gaps
| Gap | REQ-IDs Affected | Risk | Recommendation |
|---|
| No OOM handling tests | REQ-LIFE-003 | Low | Test with constrained memory or mock allocator |
| No explicit exec_ex test | REQ-EXEC-002 | Low | Add test calling ubpf_exec_ex with custom stack |
| No translate/copy_jit tests | REQ-JIT-007, REQ-JIT-006 | Low | Add tests for these less-used APIs |
| No JIT caching verification | REQ-JIT-003 | Low | Verify compile returns same pointer on second call |
| No XOR encoding verification | REQ-LOAD-006, REQ-SEC-006 | Medium | Verify instructions are XOR-encoded in memory |
| No direct safe-profile entry-state regression for null input memory | REQ-SAFE-002 | Medium | Add a test that dereferences R1 with mem == NULL and proves safe mode treats it as a scalar |
| No multi-region safe descriptor regression | REQ-SAFE-006 | Medium | Add two disjoint safe regions plus helper returns that prove provenance remains region-specific |
8.3 Structural Gaps
| Gap | Impact | Recommendation |
|---|
| No concurrency tests | Unknown thread safety | Define thread-safety model, add tests |
| No stress tests | Unknown scalability limits | Test with MAX_INSTS programs, deep call chains |
| No performance regression | Silent performance degradation | Add benchmark suite |
| No adversarial ELF fuzzing | Potential loader vulnerabilities | Add ELF-specific fuzzer |
| Atomic operations: validation only | Correctness unverified at runtime | Add atomic execution correctness tests |
9. Revision History
| Version | Date | Author | Description |
|---|
| 1.2.0 | 2026-06-12 | Evolve refresh | Added validation scope for the additive safe-interpreter profile, including planned coverage for provenance enforcement and safe-mode JIT rejection. |
| 1.1.0 | 2026-06-12 | Bootstrap refresh | Reconciled current test inventory counts, credited indirect ubpf_copy_jit() coverage via ubpf_plugin, and downgraded overstated RNG coverage claims. |
| 1.0.0 | 2026-03-31 | Extracted by AI | Initial draft — mapped existing tests to requirements, identified gaps |