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
23 changes: 5 additions & 18 deletions .github/workflows/dependency-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,12 @@ on:
- '.github/dependabot.yml'
- '.github/workflows/dependency-review.yml'
pull_request:
# No `paths:` filter here on purpose. `dependency-review` is a required
# status check on protected branches; gating it by `paths:` blocks merges
# of PRs that don't touch dep files (GitHub waits forever for a check
# that doesn't fire). `actions/dependency-review-action` is cheap and
# idempotent on no-diff PRs.
branches: [ "main", "master", "development", "dev" ]
paths:
- 'Cargo.toml'
- 'Cargo.lock'
- 'scripts/native_bench/bench_pecos/Cargo.toml'
- 'scripts/native_bench/bench_pecos/Cargo.lock'
- 'pyproject.toml'
- 'python/**/pyproject.toml'
- 'uv.lock'
- 'requirements*.txt'
- '**/requirements*.txt'
- 'package.json'
- 'package-lock.json'
- 'pnpm-lock.yaml'
- 'yarn.lock'
- 'bun.lock'
- 'bun.lockb'
- '.github/dependabot.yml'
- '.github/workflows/dependency-review.yml'

permissions:
contents: read
Expand Down
16 changes: 7 additions & 9 deletions crates/pecos-qis-ffi/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1567,18 +1567,16 @@ mod tests {

#[test]
fn test_heap_alloc_and_free() {
let ptr = unsafe { heap_alloc(100) };
assert!(!ptr.is_null());
let ptr = std::ptr::NonNull::new(unsafe { heap_alloc(100) })
.expect("heap_alloc(100) should return non-null");

// SAFETY: `ptr` was just allocated by `heap_alloc(100)` and asserted non-null
// above; the test scope owns it exclusively until `heap_free` below.
// SAFETY: `ptr` owns this allocation exclusively for the test scope;
// `heap_alloc` returns a properly-aligned `u8` allocation.
unsafe {
std::ptr::write(ptr, 42u8);
assert_eq!(std::ptr::read(ptr), 42u8);
std::ptr::write(ptr.as_ptr(), 42u8);
assert_eq!(std::ptr::read(ptr.as_ptr()), 42u8);
heap_free(ptr.as_ptr());
}

// Free should not crash
unsafe { heap_free(ptr) };
}

#[test]
Expand Down
28 changes: 11 additions & 17 deletions crates/pecos-qis-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1046,11 +1046,11 @@ mod tests {

// Get pending operations
let ptr = pecos_get_pending_operations();
assert!(!ptr.is_null());

// SAFETY: `pecos_get_pending_operations` returns a fresh leaked Box;
// non-null asserted above; the test scope owns it until `pecos_free_operations`.
let collector = unsafe { &*ptr };
// SAFETY: `pecos_get_pending_operations` returns null or a leaked
// `Box<OperationCollector>` (properly initialised + aligned);
// ownership stays here until `pecos_free_operations` below.
let collector =
unsafe { ptr.as_ref() }.expect("pecos_get_pending_operations returned null");
assert_eq!(collector.operations.len(), 2);

// Free the collector
Expand Down Expand Up @@ -1341,10 +1341,8 @@ mod tests {

// Verify operations were exported
let ops_ptr = pecos_get_pending_operations();
assert!(!ops_ptr.is_null());
// SAFETY: `pecos_get_pending_operations` returns a fresh leaked Box;
// non-null asserted above; freed below via `pecos_free_operations`.
let ops = unsafe { &*ops_ptr };
// SAFETY: see `pecos_get_pending_operations` -- null-or-leaked-Box invariant.
let ops = unsafe { ops_ptr.as_ref() }.expect("pecos_get_pending_operations returned null");
assert_eq!(ops.operations.len(), 2);
unsafe { pecos_free_operations(ops_ptr) };

Expand Down Expand Up @@ -1409,21 +1407,17 @@ mod tests {
let needed_id = pecos_wait_for_need_result(500);
assert_eq!(needed_id, 0);
let ops_ptr = pecos_get_pending_operations();
assert!(!ops_ptr.is_null());
// SAFETY: `pecos_get_pending_operations` returns a fresh leaked Box;
// non-null asserted above; freed below via `pecos_free_operations`.
let ops = unsafe { &*ops_ptr };
// SAFETY: see `pecos_get_pending_operations` -- null-or-leaked-Box invariant.
let ops = unsafe { ops_ptr.as_ref() }.expect("pecos_get_pending_operations returned null");
assert_eq!(ops.operations, vec![Operation::AllocateQubit { id: 0 }]);
unsafe { pecos_free_operations(ops_ptr) };
pecos_signal_result_ready();

let needed_id = pecos_wait_for_need_result(500);
assert_eq!(needed_id, 1);
let ops_ptr = pecos_get_pending_operations();
assert!(!ops_ptr.is_null());
// SAFETY: `pecos_get_pending_operations` returns a fresh leaked Box;
// non-null asserted above; freed below via `pecos_free_operations`.
let ops = unsafe { &*ops_ptr };
// SAFETY: see `pecos_get_pending_operations` -- null-or-leaked-Box invariant.
let ops = unsafe { ops_ptr.as_ref() }.expect("pecos_get_pending_operations returned null");
assert_eq!(ops.operations, vec![Operation::Quantum(QuantumOp::H(0))]);
unsafe { pecos_free_operations(ops_ptr) };
pecos_signal_result_ready();
Expand Down
Loading