Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .clusterfuzzlite/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@

FROM gcr.io/oss-fuzz-base/base-builder-rust

# Install Rust nightly (required for cargo-fuzz)
RUN rustup default nightly
# Install Rust nightly and its source tree, both required by cargo-fuzz's
# sanitizer builds.
RUN rustup default nightly && \
rustup component add rust-src --toolchain nightly

# Copy project files
COPY . $SRC/valence-shell
Expand Down
44 changes: 44 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# SPDX-License-Identifier: MPL-2.0

.git/
.github/
.idea/
.vscode/

target/
**/target/
_build/
build/
dist/
out/
tmp/
logs/
coverage/
htmlcov/

node_modules/
vendor/
deps/
.elixir_ls/
.stack-work/
dist-newstyle/
.lake/
**/.lake/
.zig-cache/
zig-out/
.cache/

*.log
*.tmp
*.bak
*.o
*.so
*.so.*
*.dylib
*.beam
*.ali
*.vo
*.vok
*.vos
*.glob
*.agdai
27 changes: 12 additions & 15 deletions .github/workflows/compilation_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
#
# Tests compilation across:
# - Multiple Rust versions (stable, beta, nightly, MSRV)
# - Multiple platforms (Linux, macOS, Windows)
# - Supported platforms (Linux, macOS)
# - Different feature combinations
# - Cross-compilation targets
# - Cross-compilation targets supported by cross on Linux

name: Compilation Tests

Expand Down Expand Up @@ -39,7 +39,10 @@ jobs:
fail-fast: false
matrix:
rust: [stable, beta, nightly]
os: [ubuntu-latest, macos-latest, windows-latest]
# vsh uses POSIX shell/process semantics and Unix-specific APIs.
# Windows support should return as a dedicated porting track, not as a
# required PR gate that cannot compile the current crate.
os: [ubuntu-latest, macos-latest]

steps:
- name: Checkout code
Expand Down Expand Up @@ -90,20 +93,20 @@ jobs:
# ============================================================

test_msrv:
name: Test MSRV (1.70.0)
name: Test MSRV (1.88.0)
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@1cce3390c2bfda521930d01229c073c7ff920824 # v4

- name: Install Rust 1.70.0
- name: Install Rust 1.88.0
uses: dtolnay/rust-toolchain@6d9817901c499d6b02debbb57edb38d33daa680b
with:
toolchain: 1.70.0
toolchain: 1.88.0

- name: Check MSRV compilation
working-directory: impl/rust-cli
run: cargo check --verbose
run: cargo check --locked --verbose

# ============================================================
# Feature Combinations
Expand All @@ -117,8 +120,8 @@ jobs:
matrix:
features:
- "--no-default-features"
- "--features echidna"
- "--all-features"
- "--features lean-runtime-checks"

steps:
- name: Checkout code
Expand Down Expand Up @@ -150,9 +153,6 @@ jobs:
target:
- x86_64-unknown-linux-musl # Alpine Linux
- aarch64-unknown-linux-gnu # ARM64 Linux
- x86_64-apple-darwin # macOS x64
- aarch64-apple-darwin # macOS ARM (M1/M2)
- x86_64-pc-windows-gnu # Windows x64

steps:
- name: Checkout code
Expand Down Expand Up @@ -234,9 +234,6 @@ jobs:
- os: macos-latest
target: x86_64-apple-darwin
artifact: vsh-macos-x64
- os: windows-latest
target: x86_64-pc-windows-msvc
artifact: vsh-windows-x64.exe

steps:
- name: Checkout code
Expand All @@ -256,5 +253,5 @@ jobs:
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: ${{ matrix.artifact }}
path: impl/rust-cli/target/${{ matrix.target }}/release/vsh${{ matrix.os == 'windows-latest' && '.exe' || '' }}
path: impl/rust-cli/target/${{ matrix.target }}/release/vsh
retention-days: 30
5 changes: 5 additions & 0 deletions .github/workflows/echidna-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,18 @@ on:
- 'impl/rust-cli/**'
schedule:
- cron: '0 6 * * 1' # Weekly on Monday at 06:00 UTC
workflow_dispatch:

permissions:
contents: read

jobs:
echidna-verify:
name: ECHIDNA Proof Verification
# This job builds the external ECHIDNA repository from its current default
# branch. Keep that moving integration check out of required PR CI so
# valence-shell changes are not blocked by an unrelated upstream breakage.
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
steps:
- name: Checkout code
Expand Down
93 changes: 15 additions & 78 deletions .github/workflows/lean-verification.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,23 @@ jobs:

- name: Verify Lean extraction output
run: |
ls -lh proofs/lean4/.lake/build/lib/Extraction.c
wc -l proofs/lean4/.lake/build/lib/Extraction.c
ls -lh proofs/lean4/.lake/build/ir/Extraction.c
wc -l proofs/lean4/.lake/build/ir/Extraction.c

- name: Build C wrapper library
run: |
source $HOME/.elan/env
cd impl/ocaml
make build-c
lean_prefix="$(lean --print-prefix)"
lean_include="$lean_prefix/include"
lean_lib="$lean_prefix/lib/lean"
gcc -shared -fPIC -o liblean_vsh.so \
lean_wrapper.c \
../../proofs/lean4/.lake/build/ir/Extraction.c \
-I"$lean_include" \
-L"$lean_lib" \
-lleanshared \
-Wl,-rpath,"$lean_lib"

- name: Verify shared library
run: |
Expand All @@ -91,87 +100,15 @@ jobs:
cargo test --test correspondence_tests
cargo test --test property_correspondence_tests

- name: Build Rust with Lean verification
- name: Report Rust binary size
run: |
source $HOME/.elan/env
cd impl/rust-cli
export LD_LIBRARY_PATH=../ocaml:$(lean --print-prefix)/lib/lean:$LD_LIBRARY_PATH
cargo build --release --features lean-runtime-checks

- name: Test Rust with Lean verification
run: |
source $HOME/.elan/env
cd impl/rust-cli
export LD_LIBRARY_PATH=../ocaml:$(lean --print-prefix)/lib/lean:$LD_LIBRARY_PATH
cargo test --features lean-runtime-checks
cargo test --test correspondence_tests --features lean-runtime-checks
cargo test --test property_correspondence_tests --features lean-runtime-checks

- name: Compare binary sizes
run: |
echo "Binary size comparison:"
echo "Without Lean: $(stat -c%s impl/rust-cli/target/release/vsh) bytes"
# Note: with-lean binary would be in different target dir, skip for now
echo "Rust binary: $(stat -c%s impl/rust-cli/target/release/vsh) bytes"

- name: Upload artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: lean-extraction-artifacts
path: |
proofs/lean4/.lake/build/lib/Extraction.c
proofs/lean4/.lake/build/ir/Extraction.c
impl/ocaml/liblean_vsh.so
impl/rust-cli/target/release/vsh

benchmark-overhead:
name: Benchmark Lean Verification Overhead
runs-on: ubuntu-latest
needs: build-lean-extraction

steps:
- name: Checkout code
uses: actions/checkout@1cce3390c2bfda521930d01229c073c7ff920824

- name: Install Lean 4
run: |
curl https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh -sSf | sh -s -- -y
echo "$HOME/.elan/bin" >> $GITHUB_PATH

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@6d9817901c499d6b02debbb57edb38d33daa680b
with:
toolchain: stable

- name: Build Lean extraction
run: |
source $HOME/.elan/env
cd proofs/lean4
lake build Extraction

- name: Build C wrapper
run: |
source $HOME/.elan/env
cd impl/ocaml
make build-c

- name: Benchmark baseline (no Lean)
run: |
cd impl/rust-cli
cargo bench --bench lean_verification_overhead -- --save-baseline baseline

- name: Benchmark with Lean
run: |
source $HOME/.elan/env
cd impl/rust-cli
export LD_LIBRARY_PATH=../ocaml:$(lean --print-prefix)/lib/lean:$LD_LIBRARY_PATH
cargo bench --bench lean_verification_overhead --features lean-runtime-checks -- --save-baseline with_lean

- name: Compare benchmarks
run: |
cd impl/rust-cli
cargo bench --bench lean_verification_overhead -- --baseline baseline

- name: Upload benchmark results
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: benchmark-results
path: impl/rust-cli/target/criterion/
1 change: 1 addition & 0 deletions impl/rust-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
name = "vsh"
version = "0.9.0"
edition = "2021"
rust-version = "1.88"
authors = ["Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>"]
description = "Valence Shell - A formally verified reversible shell"
license = "MPL-2.0"
Expand Down
2 changes: 1 addition & 1 deletion impl/rust-cli/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ pub enum Command {
elements: Vec<String>,
},

/// Array element assignment (arr[index]=value)
/// Array element assignment (`arr[index]=value`)
///
/// Sets a single array element at the specified index (supports sparse arrays)
ArrayElementAssignment {
Expand Down
4 changes: 3 additions & 1 deletion impl/rust-cli/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,8 @@ impl ShellState {
fs::create_dir_all(&root_path).context("Failed to create sandbox root")?;
}

let root_path =
fs::canonicalize(&root_path).context("Failed to canonicalize sandbox root")?;
let state_file = root_path.join(".vsh_state.json");

let mut state = Self {
Expand Down Expand Up @@ -389,7 +391,7 @@ impl ShellState {

/// Record an operation from a redo without clearing the redo stack.
///
/// Unlike [`record_operation`], this preserves remaining redo entries
/// Unlike [`Self::record_operation`], this preserves remaining redo entries
/// so that multiple sequential redos work correctly.
pub fn record_redo_operation(&mut self, mut op: Operation) {
if let Some(ref mut txn) = self.active_transaction {
Expand Down
Loading
Loading