diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index b544f1bce..c6db9b723 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -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 diff --git a/crates/pecos-qis-ffi/src/ffi.rs b/crates/pecos-qis-ffi/src/ffi.rs index b78cfb42c..9a2f3bfd4 100644 --- a/crates/pecos-qis-ffi/src/ffi.rs +++ b/crates/pecos-qis-ffi/src/ffi.rs @@ -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] diff --git a/crates/pecos-qis-ffi/src/lib.rs b/crates/pecos-qis-ffi/src/lib.rs index 2f7c986c5..b772a8749 100644 --- a/crates/pecos-qis-ffi/src/lib.rs +++ b/crates/pecos-qis-ffi/src/lib.rs @@ -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` (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 @@ -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) }; @@ -1409,10 +1407,8 @@ 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(); @@ -1420,10 +1416,8 @@ mod tests { 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();