From dfebb9dfbb5dbf18cd768a9401e4db689675ebb5 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Tue, 11 Aug 2026 23:26:28 +0200 Subject: [PATCH] chore(safety): hoist the unsafe lints into the workspace tables (WP2c hoist) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit undocumented_unsafe_blocks joins unsafe_op_in_unsafe_fn in [workspace.lints], and the ~100 scattered per-file #![deny(...)] attributes (85 files) are deleted — a new crate, or a new module in an old one, is now covered on creation rather than on remembering. The per-file form is how pf-vkhdr-layer, wdk-probe and half of pf-clipboard stayed uncovered. There are THREE workspaces, so the claim is made three times: the main Cargo.toml, packaging/windows/drivers (workspace table + [lints] workspace = true in all seven members), and packaging/windows/pf-vkhdr-layer (its [lints] table, previous commit). pf-update now opts into workspace lints; the two vendored member snapshots (cros-codecs, usbip-sim) stay out deliberately and now both say so. Newly-covered fallout was two link-sanity tests (pyrowave-sys, libvpl-sys) — proofs written. Stale prose that claimed the workspace held unsafe_op_in_unsafe_fn at "warn" (it has been deny) or pointed at the deleted attributes is corrected. nvenc_core.rs is carved OUT of the unsafe_op_in_unsafe_fn fence: its exemption rationale ("raw entry-table calls almost line for line") was false — the file makes zero FFI calls. Its unsafe surface is C-union writes whose soundness hangs on which codec arm is active, and its own 4:4:4 note records the shipped bug (hevcConfig bytes stamped onto an AV1 config) that per-operation blocks make visible. It now runs the strictest discipline in the crate: clippy::multiple_unsafe_ops_per_block at deny, one union access per block, each naming its codec guard. Verified here: cargo fmt clean in all three workspaces; native clippy -D warnings clean for everything that compiles on macOS (the three pre-existing mac-native failures — pf-client-core wol.rs, pf-encode dead-code/closure-call, probe mic_burst — reproduce on the clean tree). Linux/Windows legs ride the .25/.133 gate. --- Cargo.toml | 11 +++ clients/windows/src/main.rs | 1 - crates/libvpl-sys/src/lib.rs | 2 + crates/pf-capture/src/lib.rs | 7 -- crates/pf-capture/src/linux/mod.rs | 1 - crates/pf-capture/src/windows/dxgi.rs | 3 - crates/pf-capture/src/windows/idd_push.rs | 3 - .../src/windows/idd_push/channel.rs | 3 - .../pf-capture/src/windows/idd_push/cursor.rs | 3 - .../src/windows/idd_push/cursor_blend.rs | 3 - .../src/windows/idd_push/cursor_poll.rs | 3 - .../src/windows/idd_push/descriptor.rs | 3 - .../src/windows/idd_push/dxgkrnl_etw.rs | 3 - .../pf-capture/src/windows/idd_push/probes.rs | 3 - .../pf-capture/src/windows/idd_push/stall.rs | 3 - crates/pf-client-core/src/lib.rs | 1 - crates/pf-clipboard/src/lib.rs | 6 +- crates/pf-console-ui/src/lib.rs | 1 - crates/pf-dxvadec/src/lib.rs | 1 - crates/pf-encode/src/enc/linux/mod.rs | 2 - crates/pf-encode/src/enc/linux/nvenc_cuda.rs | 2 - crates/pf-encode/src/enc/linux/vaapi.rs | 2 - crates/pf-encode/src/enc/linux/worker.rs | 3 - crates/pf-encode/src/enc/nvenc_core.rs | 87 ++++++++++++------- crates/pf-encode/src/enc/sw.rs | 2 - crates/pf-encode/src/enc/windows/amf.rs | 2 - .../pf-encode/src/enc/windows/ffmpeg_win.rs | 2 - crates/pf-encode/src/enc/windows/nvenc.rs | 2 - crates/pf-encode/src/enc/windows/qsv.rs | 3 - crates/pf-encode/src/lib.rs | 1 - crates/pf-frame/src/dxgi.rs | 3 - crates/pf-frame/src/lib.rs | 1 - crates/pf-frame/src/session_tuning.rs | 3 - crates/pf-frame/src/thread_qos.rs | 3 - crates/pf-gpu/src/lib.rs | 1 - crates/pf-inject/src/inject/linux/gamepad.rs | 3 - .../src/inject/linux/kwin_fake_input.rs | 2 - crates/pf-inject/src/inject/linux/wlr.rs | 3 - .../src/inject/windows/pointer_windows.rs | 3 - .../pf-inject/src/inject/windows/sendinput.rs | 3 - crates/pf-inject/src/lib.rs | 7 -- crates/pf-presenter/src/lib.rs | 1 - crates/pf-update/Cargo.toml | 3 + crates/pf-vdisplay/src/lib.rs | 7 -- crates/pf-vdisplay/src/vdisplay/linux/kwin.rs | 3 - .../src/vdisplay/linux/kwin_output_mgmt.rs | 2 - .../src/vdisplay/windows/manager.rs | 3 - .../src/vdisplay/windows/pf_vdisplay.rs | 3 - crates/pf-vkdecode/src/lib.rs | 7 +- crates/pf-vkdecode/tests/gpu_parity.rs | 2 - crates/pf-vkdecode/tests/gpu_smoke.rs | 2 - crates/pf-win-display/src/display_events.rs | 3 - crates/pf-win-display/src/lib.rs | 2 - crates/pf-win-display/src/win_display.rs | 7 -- crates/pf-zerocopy/src/dmabuf_fence.rs | 3 - crates/pf-zerocopy/src/imp/client.rs | 3 - crates/pf-zerocopy/src/imp/cuda.rs | 2 - crates/pf-zerocopy/src/imp/cuda/ffi.rs | 2 - crates/pf-zerocopy/src/imp/egl.rs | 2 - crates/pf-zerocopy/src/imp/egl/gl.rs | 2 - crates/pf-zerocopy/src/imp/ipc.rs | 3 - crates/pf-zerocopy/src/imp/vkslot.rs | 3 - crates/pf-zerocopy/src/imp/vulkan.rs | 3 - crates/pf-zerocopy/src/imp/worker.rs | 3 - crates/pf-zerocopy/src/lib.rs | 10 +-- crates/punktfunk-core/src/lib.rs | 1 - .../src/audio/windows/audio_control.rs | 3 - .../src/audio/windows/audio_probe.rs | 3 - .../src/audio/windows/devnode_cleanup.rs | 3 - .../src/audio/windows/pad_endpoint.rs | 3 - .../src/audio/windows/wasapi_mic.rs | 3 - crates/punktfunk-host/src/gamestream/audio.rs | 3 - .../punktfunk-host/src/gamestream/stream.rs | 3 - crates/punktfunk-host/src/linux/drm_sync.rs | 2 - crates/punktfunk-host/src/linux/gpuclocks.rs | 2 - crates/punktfunk-host/src/main.rs | 12 +-- crates/punktfunk-host/src/native.rs | 3 - crates/punktfunk-host/src/windows/crash.rs | 1 - .../punktfunk-host/src/windows/interactive.rs | 9 +- crates/punktfunk-host/src/windows/service.rs | 3 - .../vendor/usbip-sim/Cargo.toml | 4 + crates/punktfunk-tray/src/main.rs | 1 - crates/pyrowave-sys/src/lib.rs | 2 + packaging/windows/drivers/Cargo.toml | 11 +++ .../windows/drivers/pf-gamepad/Cargo.toml | 3 + .../windows/drivers/pf-gamepad/src/lib.rs | 2 - packaging/windows/drivers/pf-mouse/Cargo.toml | 3 + packaging/windows/drivers/pf-mouse/src/lib.rs | 2 - .../windows/drivers/pf-umdf-util/Cargo.toml | 3 + .../windows/drivers/pf-umdf-util/src/lib.rs | 9 +- .../windows/drivers/pf-vdisplay/Cargo.toml | 3 + .../windows/drivers/pf-vdisplay/src/lib.rs | 2 - packaging/windows/drivers/pf-xusb/Cargo.toml | 3 + packaging/windows/drivers/pf-xusb/src/lib.rs | 2 - .../windows/drivers/wdk-iddcx/Cargo.toml | 3 + .../windows/drivers/wdk-iddcx/src/lib.rs | 2 - .../windows/drivers/wdk-probe/Cargo.toml | 3 + .../windows/drivers/wdk-probe/src/lib.rs | 2 - tools/display-disturb/src/main.rs | 1 - 99 files changed, 127 insertions(+), 270 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c4cc9afc..97e4ef20 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,6 +101,17 @@ repository = "https://git.unom.io/unom/punktfunk" [workspace.lints.rust] unsafe_op_in_unsafe_fn = "deny" +# The companion lint: every `unsafe {}` / `unsafe impl` carries a `// SAFETY:` proof. Hoisted here +# from ~85 per-file `#![deny(...)]` attributes so a NEW crate (or a new module in an old one) is +# covered on creation rather than on remembering — the per-file form left pf-vkhdr-layer, +# wdk-probe, and half of pf-clipboard uncovered for months. NOTE: this table reaches only crates +# with `[lints] workspace = true`; `packaging/windows/drivers` and `packaging/windows/pf-vkhdr-layer` +# are SEPARATE workspaces and restate it (any "workspace-wide" claim must be made three times or it +# is false). Of the members, only the two vendored snapshots (pf-bitstream/vendor/cros-codecs, +# punktfunk-host/vendor/usbip-sim) stay out, deliberately — upstream code stays pristine. +[workspace.lints.clippy] +undocumented_unsafe_blocks = "deny" + [profile.release] opt-level = 3 lto = "thin" diff --git a/clients/windows/src/main.rs b/clients/windows/src/main.rs index 110719b0..278c3a94 100644 --- a/clients/windows/src/main.rs +++ b/clients/windows/src/main.rs @@ -15,7 +15,6 @@ //! (measure the path: probe burst → goodput / loss / recommended bitrate) // Unsafe-proof program: every `unsafe {}` in this client carries a `// SAFETY:` proof. -#![deny(clippy::undocumented_unsafe_blocks)] // Link as a GUI (windows) subsystem binary so the default windowed launch (MSIX / double-click) // does NOT pop a console window. The CLI paths (--headless/--discover) reattach to the launching // terminal's console at startup (see main), so their output is still visible when run from a shell. diff --git a/crates/libvpl-sys/src/lib.rs b/crates/libvpl-sys/src/lib.rs index 56972208..3b460301 100644 --- a/crates/libvpl-sys/src/lib.rs +++ b/crates/libvpl-sys/src/lib.rs @@ -27,6 +27,8 @@ mod tests { /// implementations — that's fine, MFXLoad itself must still succeed). #[test] fn dispatcher_links_and_loads() { + // SAFETY: MFXLoad allocates the dispatcher's loader context (documented to work with no + // driver present) and MFXUnload frees that same non-null handle; nothing else is touched. unsafe { let loader = MFXLoad(); assert!(!loader.is_null(), "MFXLoad returned NULL"); diff --git a/crates/pf-capture/src/lib.rs b/crates/pf-capture/src/lib.rs index becd589e..153026fb 100644 --- a/crates/pf-capture/src/lib.rs +++ b/crates/pf-capture/src/lib.rs @@ -7,13 +7,6 @@ //! [`FrameChannelSender`] closure, so this crate reaches neither the encoder nor the host //! orchestrator). -// Every unsafe block in this crate carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] -// …and that program only covers a whole `unsafe fn` body once the body needs its own block: in -// edition 2021 `unsafe_op_in_unsafe_fn` is allow-by-default, which exempted the crate's hardest FFI -// (the ring/slot construction, the channel broker, every D3D converter ctor) from the deny above. -#![deny(unsafe_op_in_unsafe_fn)] - use anyhow::Result; use pf_frame::{CapturedFrame, FramePayload, PixelFormat}; // The Linux capturer reaches `DmabufFrame` through `super::`; `CursorOverlay` it names directly as diff --git a/crates/pf-capture/src/linux/mod.rs b/crates/pf-capture/src/linux/mod.rs index 6a28ff21..6099aa29 100644 --- a/crates/pf-capture/src/linux/mod.rs +++ b/crates/pf-capture/src/linux/mod.rs @@ -25,7 +25,6 @@ // Every `unsafe` block in this module TREE carries a `// SAFETY:` proof; enforce it (unsafe-proof // program). This file itself has none — the FFI lives in the child modules declared at the bottom // (`pipewire`, `pw_cursor`, `pw_pods`, `portal`, `xfixes_cursor`), which this inner attribute covers. -#![deny(clippy::undocumented_unsafe_blocks)] use super::{CapturedFrame, Capturer, DmabufFrame, FramePayload, PixelFormat, ZeroCopyPolicy}; use anyhow::{anyhow, Context, Result}; diff --git a/crates/pf-capture/src/windows/dxgi.rs b/crates/pf-capture/src/windows/dxgi.rs index 190664a4..962b22b9 100644 --- a/crates/pf-capture/src/windows/dxgi.rs +++ b/crates/pf-capture/src/windows/dxgi.rs @@ -9,9 +9,6 @@ //! `crate::dxgi::*` path keeps resolving. DXGI Desktop Duplication has been removed; this //! module contains no capturer. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - pub use pf_frame::dxgi::{make_device, pack_luid, D3d11Frame, PyroFrameShare, WinCaptureTarget}; // The P010 colour self-test (sweep Phase 5.5) — the `hdr-p010-selftest` subcommand, its f64 diff --git a/crates/pf-capture/src/windows/idd_push.rs b/crates/pf-capture/src/windows/idd_push.rs index abeeae0e..1d1c3a3b 100644 --- a/crates/pf-capture/src/windows/idd_push.rs +++ b/crates/pf-capture/src/windows/idd_push.rs @@ -16,9 +16,6 @@ //! [`pf_driver_proto`] (which OWNS the contract, with `const` size asserts) — both sides `use` it, so //! drift is a compile error rather than a "must match" comment. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use super::dxgi::{ make_device, BgraToYuvPlanes, D3d11Frame, HdrP010Converter, HdrRgb10Converter, PyroFrameShare, VideoConverter, WinCaptureTarget, diff --git a/crates/pf-capture/src/windows/idd_push/channel.rs b/crates/pf-capture/src/windows/idd_push/channel.rs index f72e3476..3c99f3ce 100644 --- a/crates/pf-capture/src/windows/idd_push/channel.rs +++ b/crates/pf-capture/src/windows/idd_push/channel.rs @@ -2,9 +2,6 @@ //! capturer): duplicates the unnamed shared header / ring / event handles into the driver's WUDFHost //! and delivers them as bare handle values over the SYSTEM-only control device. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use super::*; /// The sealed channel's handle-duplication broker (`design/idd-push-security.md`): the frame objects diff --git a/crates/pf-capture/src/windows/idd_push/cursor.rs b/crates/pf-capture/src/windows/idd_push/cursor.rs index 80e79ae7..f630ae6a 100644 --- a/crates/pf-capture/src/windows/idd_push/cursor.rs +++ b/crates/pf-capture/src/windows/idd_push/cursor.rs @@ -5,9 +5,6 @@ //! [`pf_frame::CursorOverlay`] the Linux portal path produces — everything downstream (the //! cursor forwarder, the wire, the client renderer) is shared. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it. -#![deny(clippy::undocumented_unsafe_blocks)] - use super::*; use pf_driver_proto::cursor::{ CursorShm, CURSOR_MAGIC, CURSOR_SHAPE_BYTES, CURSOR_SHAPE_MAX, CURSOR_SHAPE_OFFSET, diff --git a/crates/pf-capture/src/windows/idd_push/cursor_blend.rs b/crates/pf-capture/src/windows/idd_push/cursor_blend.rs index cf389496..da55bd2c 100644 --- a/crates/pf-capture/src/windows/idd_push/cursor_blend.rs +++ b/crates/pf-capture/src/windows/idd_push/cursor_blend.rs @@ -10,9 +10,6 @@ //! alpha-blended quad (the GDI poller's full-fidelity shape at its polled position), entirely //! GPU-side on the capture device, before the normal conversion runs from the scratch. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use super::*; use windows::core::s; use windows::Win32::Graphics::Direct3D::D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; diff --git a/crates/pf-capture/src/windows/idd_push/cursor_poll.rs b/crates/pf-capture/src/windows/idd_push/cursor_poll.rs index d3dc7f49..3dd7cc23 100644 --- a/crates/pf-capture/src/windows/idd_push/cursor_poll.rs +++ b/crates/pf-capture/src/windows/idd_push/cursor_poll.rs @@ -20,9 +20,6 @@ //! `winsta0\default` (the service supervisor retargets the token — `windows/service.rs` //! `spawn_host`), so the poller thread sees the session's cursor directly; no helper process. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use super::*; use windows::Win32::Graphics::Gdi::{ DeleteObject, GetDC, GetDIBits, GetObjectW, ReleaseDC, BITMAP, BITMAPINFO, BITMAPINFOHEADER, diff --git a/crates/pf-capture/src/windows/idd_push/descriptor.rs b/crates/pf-capture/src/windows/idd_push/descriptor.rs index 3866ba0c..c5d64e11 100644 --- a/crates/pf-capture/src/windows/idd_push/descriptor.rs +++ b/crates/pf-capture/src/windows/idd_push/descriptor.rs @@ -1,9 +1,6 @@ //! Off-thread display-descriptor polling (plan §W4, carved out of the IDD-push capturer): the //! live HDR state + active resolution of the virtual target, sampled off the capture loop via CCD. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use super::*; /// The display descriptor the capture loop follows: live HDR state + active resolution of the diff --git a/crates/pf-capture/src/windows/idd_push/dxgkrnl_etw.rs b/crates/pf-capture/src/windows/idd_push/dxgkrnl_etw.rs index 2b4f03e9..e9c59917 100644 --- a/crates/pf-capture/src/windows/idd_push/dxgkrnl_etw.rs +++ b/crates/pf-capture/src/windows/idd_push/dxgkrnl_etw.rs @@ -33,9 +33,6 @@ //! The session's `FlushTimer` is 1 s, so a bracket from the trailing second of a gap can land //! AFTER that stall's report line — the next report (and the metronomic tally) still carries it. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use std::collections::VecDeque; use std::sync::{Arc, Mutex, OnceLock, Weak}; use std::time::{Duration, Instant}; diff --git a/crates/pf-capture/src/windows/idd_push/probes.rs b/crates/pf-capture/src/windows/idd_push/probes.rs index d87a03e9..39941e3a 100644 --- a/crates/pf-capture/src/windows/idd_push/probes.rs +++ b/crates/pf-capture/src/windows/idd_push/probes.rs @@ -25,9 +25,6 @@ //! ([`acquire`]), refcounted across parallel capturers; probes sample at 20 Hz or slower and cost //! microseconds each, so the engine is invisible next to a streaming session. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use std::collections::VecDeque; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex, Weak}; diff --git a/crates/pf-capture/src/windows/idd_push/stall.rs b/crates/pf-capture/src/windows/idd_push/stall.rs index 9ed9c735..27d729fc 100644 --- a/crates/pf-capture/src/windows/idd_push/stall.rs +++ b/crates/pf-capture/src/windows/idd_push/stall.rs @@ -1,9 +1,6 @@ //! Capture-stall detection (plan §W4, carved out of the IDD-push capturer): flags multi-hundred-ms //! holes in DWM frame delivery that open while the desktop was actively composing. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use super::*; /// A detected capture stall: a multi-hundred-ms hole in DWM's frame delivery that opened while the diff --git a/crates/pf-client-core/src/lib.rs b/crates/pf-client-core/src/lib.rs index 2c985143..b84c6ba7 100644 --- a/crates/pf-client-core/src/lib.rs +++ b/crates/pf-client-core/src/lib.rs @@ -18,7 +18,6 @@ // proof of why it is sound. This crate held ~91 unsafe items with NO enforcement while every // other subsystem crate denied it — the decoders' `unsafe impl Send`s had a one-line aside // instead of an argument precisely because nothing required one. -#![deny(clippy::undocumented_unsafe_blocks)] #[cfg(any(target_os = "linux", windows))] mod au_dump; diff --git a/crates/pf-clipboard/src/lib.rs b/crates/pf-clipboard/src/lib.rs index ac3c0343..cb1e271c 100644 --- a/crates/pf-clipboard/src/lib.rs +++ b/crates/pf-clipboard/src/lib.rs @@ -10,9 +10,9 @@ //! [`spawn_decline_loop`] — so its control loop compiles unchanged on every host platform; the //! platform split lives entirely behind [`start`]. -// Crate-wide: every `unsafe` block in any backend carries a `// SAFETY:` proof (unsafe-proof -// program). At the root — not per-module — so a new backend under `host/` is covered on creation. -#![deny(clippy::undocumented_unsafe_blocks)] +// Unsafe-proof program: every `unsafe` block in any backend carries a `// SAFETY:` proof, +// enforced workspace-wide by `[workspace.lints]` — a new backend under `host/` is covered on +// creation. use std::sync::atomic::AtomicBool; use std::sync::Arc; diff --git a/crates/pf-console-ui/src/lib.rs b/crates/pf-console-ui/src/lib.rs index 7e5a15f2..560a6557 100644 --- a/crates/pf-console-ui/src/lib.rs +++ b/crates/pf-console-ui/src/lib.rs @@ -11,7 +11,6 @@ //! capture hint, start banner. // Unsafe-proof program: every `unsafe {}` in the Skia/Vulkan overlay carries a `// SAFETY:` proof. -#![deny(clippy::undocumented_unsafe_blocks)] #[cfg(any(target_os = "linux", windows))] mod anim; diff --git a/crates/pf-dxvadec/src/lib.rs b/crates/pf-dxvadec/src/lib.rs index 88549a0e..841a3718 100644 --- a/crates/pf-dxvadec/src/lib.rs +++ b/crates/pf-dxvadec/src/lib.rs @@ -52,7 +52,6 @@ //! ([`dxva::as_bytes`] / [`dxva::slice_bytes`]), fenced behind a sealed trait //! that only this crate's `#[repr(C)]` PODs implement, and carrying a written //! proof — enforced: -#![deny(clippy::undocumented_unsafe_blocks)] pub mod config; pub mod descriptors; diff --git a/crates/pf-encode/src/enc/linux/mod.rs b/crates/pf-encode/src/enc/linux/mod.rs index 9149df81..21638b26 100644 --- a/crates/pf-encode/src/enc/linux/mod.rs +++ b/crates/pf-encode/src/enc/linux/mod.rs @@ -12,8 +12,6 @@ //! does *not* accept — we expand it to `rgb0` (one padding byte/pixel, no colour math). //! The encoder is opened *without* a global header so VPS/SPS/PPS are emitted in-band on //! every IDR — the output is both a playable raw Annex-B stream and self-contained AUs. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] use super::{ChromaFormat, Codec, EncodedFrame, Encoder}; use anyhow::{anyhow, bail, Context, Result}; diff --git a/crates/pf-encode/src/enc/linux/nvenc_cuda.rs b/crates/pf-encode/src/enc/linux/nvenc_cuda.rs index 25bb1cc1..a8999802 100644 --- a/crates/pf-encode/src/enc/linux/nvenc_cuda.rs +++ b/crates/pf-encode/src/enc/linux/nvenc_cuda.rs @@ -63,8 +63,6 @@ // the signature. Clearing this file means DELETING the markers that carry no caller contract, not // wrapping the calls — until then the lint is off HERE and enforced everywhere else. #![allow(unsafe_op_in_unsafe_fn)] -// Every `unsafe` block / impl in this file carries a `// SAFETY:` proof; enforce it. -#![deny(clippy::undocumented_unsafe_blocks)] use super::nvenc_core::{ apply_low_latency_config, build_init_params, cached_ceiling, cached_split_verdict, codec_guid, diff --git a/crates/pf-encode/src/enc/linux/vaapi.rs b/crates/pf-encode/src/enc/linux/vaapi.rs index d11086a6..ea5bd6c7 100644 --- a/crates/pf-encode/src/enc/linux/vaapi.rs +++ b/crates/pf-encode/src/enc/linux/vaapi.rs @@ -19,8 +19,6 @@ //! hwdevice/hwframes/buffersrc/buffersink calls go through `ffmpeg::ffi` (= `ffmpeg_sys_next`), //! as the CUDA encode path and the clients' decode paths already do. The encoder is opened //! *without* a global header, so VPS/SPS/PPS are in-band on every IDR. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] use super::{Codec, EncodedFrame, Encoder}; use anyhow::{anyhow, bail, Context, Result}; diff --git a/crates/pf-encode/src/enc/linux/worker.rs b/crates/pf-encode/src/enc/linux/worker.rs index 14ce0f31..f76f3fc4 100644 --- a/crates/pf-encode/src/enc/linux/worker.rs +++ b/crates/pf-encode/src/enc/linux/worker.rs @@ -41,9 +41,6 @@ //! worker caches it, so the steady state passes **zero** descriptors (the PipeWire pool recycles a //! small buffer set). -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use anyhow::{Context, Result}; use pf_frame::{CapturedFrame, CursorOverlay, DmabufFrame, FramePayload, PixelFormat}; use pf_zerocopy::ipc; diff --git a/crates/pf-encode/src/enc/nvenc_core.rs b/crates/pf-encode/src/enc/nvenc_core.rs index 242230f9..9fb89318 100644 --- a/crates/pf-encode/src/enc/nvenc_core.rs +++ b/crates/pf-encode/src/enc/nvenc_core.rs @@ -5,12 +5,13 @@ //! `libloading`), the device binding (D3D11 vs CUDA), input-surface registration, and the //! Windows-only async retrieve — stay in their backends. Sibling of [`super::nvenc_status`]. -// UNSAFE-LINT EXEMPTION (rationale + exit criteria: `unsafe_op_in_unsafe_fn` in the workspace -// Cargo.toml). This body is raw `nvEncodeAPI` entry-table calls almost line for line; narrowing it -// would add one `unsafe {}` plus one SAFETY comment per call that could only restate the signature. -// Clearing this file means DELETING the markers that carry no caller contract, not wrapping the -// calls — until then the lint is off HERE and enforced everywhere else. -#![allow(unsafe_op_in_unsafe_fn)] +// UNSAFE-LINT EXEMPTION REMOVED — the old fence rationale ("raw nvEncodeAPI entry-table calls +// almost line for line") was false for this file: it makes ZERO FFI calls. Its unsafe surface is +// C-union writes whose soundness hangs entirely on which codec arm is active, and the 4:4:4 note +// below records the shipped bug (hevcConfig bytes stamped onto an AV1 config) that per-operation +// blocks make visible. So this file runs the strictest discipline in the crate: every union +// access sits in its own `unsafe {}` block naming the codec guard it relies on. +#![deny(clippy::multiple_unsafe_ops_per_block)] use super::Codec; use nvidia_video_codec_sdk::sys::nvEncodeAPI as nv; @@ -694,10 +695,9 @@ mod tests { }; assert_eq!(cfg.profileGUID, nv::NV_ENC_HEVC_PROFILE_FREXT_GUID); // SAFETY: an HEVC session's union arm is `hevcConfig` — the one this path wrote. - unsafe { - assert_eq!(cfg.encodeCodecConfig.hevcConfig.chromaFormatIDC(), 3); - assert_eq!(cfg.encodeCodecConfig.hevcConfig.pixelBitDepthMinus8(), 2); - } + unsafe { assert_eq!(cfg.encodeCodecConfig.hevcConfig.chromaFormatIDC(), 3) }; + // SAFETY: same HEVC arm as above. + unsafe { assert_eq!(cfg.encodeCodecConfig.hevcConfig.pixelBitDepthMinus8(), 2) }; } #[test] @@ -1210,8 +1210,10 @@ pub(super) unsafe fn apply_low_latency_config(cfg: &mut nv::NV_ENC_CONFIG, c: Lo // are the only accepted config). H.264 has no tier. Level 0 = autoselect for HEVC. match c.codec { Codec::H265 => { - cfg.encodeCodecConfig.hevcConfig.tier = 1; - cfg.encodeCodecConfig.hevcConfig.level = 0; + // SAFETY: HEVC session (matched on `c.codec`), so `hevcConfig` is the active arm. + unsafe { cfg.encodeCodecConfig.hevcConfig.tier = 1 }; + // SAFETY: same HEVC arm, same match guard. + unsafe { cfg.encodeCodecConfig.hevcConfig.level = 0 }; } Codec::Av1 => {} Codec::H264 => {} @@ -1227,12 +1229,16 @@ pub(super) unsafe fn apply_low_latency_config(cfg: &mut nv::NV_ENC_CONFIG, c: Lo if let Some(n) = Some(c.slices).filter(|n| *n >= 2) { match c.codec { Codec::H264 => { - cfg.encodeCodecConfig.h264Config.sliceMode = 3; - cfg.encodeCodecConfig.h264Config.sliceModeData = n; + // SAFETY: H.264 session (matched on `c.codec`), so `h264Config` is the active arm. + unsafe { cfg.encodeCodecConfig.h264Config.sliceMode = 3 }; + // SAFETY: same H.264 arm, same match guard. + unsafe { cfg.encodeCodecConfig.h264Config.sliceModeData = n }; } Codec::H265 => { - cfg.encodeCodecConfig.hevcConfig.sliceMode = 3; - cfg.encodeCodecConfig.hevcConfig.sliceModeData = n; + // SAFETY: HEVC session (matched on `c.codec`), so `hevcConfig` is the active arm. + unsafe { cfg.encodeCodecConfig.hevcConfig.sliceMode = 3 }; + // SAFETY: same HEVC arm, same match guard. + unsafe { cfg.encodeCodecConfig.hevcConfig.sliceModeData = n }; } Codec::Av1 | Codec::PyroWave => {} } @@ -1264,21 +1270,29 @@ pub(super) unsafe fn apply_low_latency_config(cfg: &mut nv::NV_ENC_CONFIG, c: Lo } if want_444 && c.codec == Codec::H265 { cfg.profileGUID = nv::NV_ENC_HEVC_PROFILE_FREXT_GUID; - cfg.encodeCodecConfig.hevcConfig.set_chromaFormatIDC(3); + // SAFETY: HEVC session (guarded by `c.codec == Codec::H265` on this branch), so + // `hevcConfig` is the active arm. + unsafe { cfg.encodeCodecConfig.hevcConfig.set_chromaFormatIDC(3) }; if c.bit_depth == 10 { - cfg.encodeCodecConfig.hevcConfig.set_pixelBitDepthMinus8(2); // Main 4:4:4 10 + // SAFETY: same HEVC arm, same branch guard. (Main 4:4:4 10) + unsafe { cfg.encodeCodecConfig.hevcConfig.set_pixelBitDepthMinus8(2) }; } } else if c.bit_depth == 10 { match c.codec { Codec::H265 => { cfg.profileGUID = nv::NV_ENC_HEVC_PROFILE_MAIN10_GUID; - cfg.encodeCodecConfig.hevcConfig.set_pixelBitDepthMinus8(2); + // SAFETY: HEVC session (matched on `c.codec`), so `hevcConfig` is the active arm. + unsafe { cfg.encodeCodecConfig.hevcConfig.set_pixelBitDepthMinus8(2) }; } Codec::Av1 => { - cfg.encodeCodecConfig.av1Config.set_pixelBitDepthMinus8(2); - cfg.encodeCodecConfig - .av1Config - .set_inputPixelBitDepthMinus8(c.av1_input_depth_minus8); + // SAFETY: AV1 session (matched on `c.codec`), so `av1Config` is the active arm. + unsafe { cfg.encodeCodecConfig.av1Config.set_pixelBitDepthMinus8(2) }; + // SAFETY: same AV1 arm, same match guard. + unsafe { + cfg.encodeCodecConfig + .av1Config + .set_inputPixelBitDepthMinus8(c.av1_input_depth_minus8) + }; } Codec::H264 => {} // no 10-bit H.264 encode on NVENC — negotiation never asks Codec::PyroWave => unreachable!("PyroWave never opens the direct-NVENC backend"), @@ -1306,7 +1320,9 @@ pub(super) unsafe fn apply_low_latency_config(cfg: &mut nv::NV_ENC_CONFIG, c: Lo }; match c.codec { Codec::H265 => { - let vui = &mut cfg.encodeCodecConfig.hevcConfig.hevcVUIParameters; + // SAFETY: HEVC session (matched on `c.codec`), so `hevcConfig` is the active + // arm; the borrow is dropped before any other union access. + let vui = unsafe { &mut cfg.encodeCodecConfig.hevcConfig.hevcVUIParameters }; vui.videoSignalTypePresentFlag = 1; vui.videoFullRangeFlag = 0; vui.colourDescriptionPresentFlag = 1; @@ -1315,7 +1331,9 @@ pub(super) unsafe fn apply_low_latency_config(cfg: &mut nv::NV_ENC_CONFIG, c: Lo vui.colourMatrix = mat; } Codec::H264 => { - let vui = &mut cfg.encodeCodecConfig.h264Config.h264VUIParameters; + // SAFETY: H.264 session (matched on `c.codec`), so `h264Config` is the active + // arm; the borrow is dropped before any other union access. + let vui = unsafe { &mut cfg.encodeCodecConfig.h264Config.h264VUIParameters }; vui.videoSignalTypePresentFlag = 1; vui.videoFullRangeFlag = 0; vui.colourDescriptionPresentFlag = 1; @@ -1324,7 +1342,9 @@ pub(super) unsafe fn apply_low_latency_config(cfg: &mut nv::NV_ENC_CONFIG, c: Lo vui.colourMatrix = mat; } Codec::Av1 => { - let av1 = &mut cfg.encodeCodecConfig.av1Config; + // SAFETY: AV1 session (matched on `c.codec`), so `av1Config` is the active arm; + // the borrow is dropped before any other union access. + let av1 = unsafe { &mut cfg.encodeCodecConfig.av1Config }; av1.colorPrimaries = prim; av1.transferCharacteristics = trc; av1.matrixCoefficients = mat; @@ -1341,15 +1361,20 @@ pub(super) unsafe fn apply_low_latency_config(cfg: &mut nv::NV_ENC_CONFIG, c: Lo let one = nv::NV_ENC_NUM_REF_FRAMES::NV_ENC_NUM_REF_FRAMES_1; match c.codec { Codec::H264 => { - cfg.encodeCodecConfig.h264Config.maxNumRefFrames = RFI_DPB; - cfg.encodeCodecConfig.h264Config.numRefL0 = one; + // SAFETY: H.264 session (matched on `c.codec`), so `h264Config` is the active arm. + unsafe { cfg.encodeCodecConfig.h264Config.maxNumRefFrames = RFI_DPB }; + // SAFETY: same H.264 arm, same match guard. + unsafe { cfg.encodeCodecConfig.h264Config.numRefL0 = one }; } Codec::H265 => { - cfg.encodeCodecConfig.hevcConfig.maxNumRefFramesInDPB = RFI_DPB; - cfg.encodeCodecConfig.hevcConfig.numRefL0 = one; + // SAFETY: HEVC session (matched on `c.codec`), so `hevcConfig` is the active arm. + unsafe { cfg.encodeCodecConfig.hevcConfig.maxNumRefFramesInDPB = RFI_DPB }; + // SAFETY: same HEVC arm, same match guard. + unsafe { cfg.encodeCodecConfig.hevcConfig.numRefL0 = one }; } Codec::Av1 => { - cfg.encodeCodecConfig.av1Config.maxNumRefFramesInDPB = RFI_DPB; + // SAFETY: AV1 session (matched on `c.codec`), so `av1Config` is the active arm. + unsafe { cfg.encodeCodecConfig.av1Config.maxNumRefFramesInDPB = RFI_DPB }; } Codec::PyroWave => unreachable!("PyroWave never opens the direct-NVENC backend"), } diff --git a/crates/pf-encode/src/enc/sw.rs b/crates/pf-encode/src/enc/sw.rs index 732aa637..053790a5 100644 --- a/crates/pf-encode/src/enc/sw.rs +++ b/crates/pf-encode/src/enc/sw.rs @@ -12,8 +12,6 @@ //! defaulting to BT.709 limited — true of every punktfunk client (`csc_rows` falls back to 709 on //! "unspecified"), but NOT of vendor TV decoders, which guess colorimetry from RESOLUTION: an LG //! webOS panel reads a 4K SDR stream as BT.2020 and renders it visibly washed out. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] use super::{EncodedFrame, Encoder}; use anyhow::{bail, ensure, Context, Result}; diff --git a/crates/pf-encode/src/enc/windows/amf.rs b/crates/pf-encode/src/enc/windows/amf.rs index abc2a5e6..a11e2c56 100644 --- a/crates/pf-encode/src/enc/windows/amf.rs +++ b/crates/pf-encode/src/enc/windows/amf.rs @@ -49,8 +49,6 @@ // restate the signature. Clearing this file means DELETING the markers that carry no caller // contract, not wrapping the calls — until then the lint is off HERE and enforced everywhere else. #![allow(unsafe_op_in_unsafe_fn)] -// Every `unsafe` block / impl in this file carries a `// SAFETY:` proof; enforce it. -#![deny(clippy::undocumented_unsafe_blocks)] use super::{ChromaFormat, Codec, EncodedFrame, Encoder, EncoderCaps}; use anyhow::{anyhow, bail, Context, Result}; diff --git a/crates/pf-encode/src/enc/windows/ffmpeg_win.rs b/crates/pf-encode/src/enc/windows/ffmpeg_win.rs index ed428523..c536b316 100644 --- a/crates/pf-encode/src/enc/windows/ffmpeg_win.rs +++ b/crates/pf-encode/src/enc/windows/ffmpeg_win.rs @@ -37,8 +37,6 @@ //! through `ffmpeg::ffi` (= `ffmpeg_sys_next`), exactly as the Linux CUDA/VAAPI paths do. The //! `AVD3D11VADeviceContext`/`AVD3D11VAFramesContext` layouts are mirrored (the bindings don't //! allowlist `hwcontext_d3d11va.h`), as [`super::linux`] mirrors `AVCUDADeviceContext`. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] use super::{ChromaFormat, Codec, EncodedFrame, Encoder}; use anyhow::{anyhow, bail, Context, Result}; diff --git a/crates/pf-encode/src/enc/windows/nvenc.rs b/crates/pf-encode/src/enc/windows/nvenc.rs index 67c0f7ce..f2269e25 100644 --- a/crates/pf-encode/src/enc/windows/nvenc.rs +++ b/crates/pf-encode/src/enc/windows/nvenc.rs @@ -39,8 +39,6 @@ // the signature. Clearing this file means DELETING the markers that carry no caller contract, not // wrapping the calls — until then the lint is off HERE and enforced everywhere else. #![allow(unsafe_op_in_unsafe_fn)] -// Every `unsafe` block / impl in this file carries a `// SAFETY:` proof; enforce it. -#![deny(clippy::undocumented_unsafe_blocks)] use super::nvenc_core::{ apply_low_latency_config, build_init_params, cached_ceiling, codec_guid, plan_range_recovery, diff --git a/crates/pf-encode/src/enc/windows/qsv.rs b/crates/pf-encode/src/enc/windows/qsv.rs index 1912fd11..d2448dfe 100644 --- a/crates/pf-encode/src/enc/windows/qsv.rs +++ b/crates/pf-encode/src/enc/windows/qsv.rs @@ -37,9 +37,6 @@ //! it stays behind the same gate and falls back to IDR wherever the driver declines. 4:4:4 stays //! `false` until probed on real hardware (design §8.6). -// Every `unsafe` block / impl in this file carries a `// SAFETY:` proof; enforce it. -#![deny(clippy::undocumented_unsafe_blocks)] - use super::{ChromaFormat, Codec, EncodedFrame, Encoder, EncoderCaps}; use anyhow::{anyhow, bail, Context, Result}; use libvpl_sys as vpl; diff --git a/crates/pf-encode/src/lib.rs b/crates/pf-encode/src/lib.rs index 8c093b5c..918aefb8 100644 --- a/crates/pf-encode/src/lib.rs +++ b/crates/pf-encode/src/lib.rs @@ -12,7 +12,6 @@ // `#[cfg(test)]` instead. // Every unsafe block in this module tree carries a `// SAFETY:` proof; enforce it (unsafe-proof // program). As a parent module this also covers the child modules (windows/linux backends). -#![deny(clippy::undocumented_unsafe_blocks)] use anyhow::Result; use pf_frame::{CapturedFrame, PixelFormat}; diff --git a/crates/pf-frame/src/dxgi.rs b/crates/pf-frame/src/dxgi.rs index 609e1312..e846e3c0 100644 --- a/crates/pf-frame/src/dxgi.rs +++ b/crates/pf-frame/src/dxgi.rs @@ -7,9 +7,6 @@ //! The win32u GPU-preference hook, the HDR/video-engine converters, and the self-tests stay in the //! capture crate — they are capture mechanics, not shared identity. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use anyhow::{Context, Result}; use windows::core::Interface; use windows::Win32::Foundation::{HMODULE, LUID}; diff --git a/crates/pf-frame/src/lib.rs b/crates/pf-frame/src/lib.rs index ab946b8d..38cc96f7 100644 --- a/crates/pf-frame/src/lib.rs +++ b/crates/pf-frame/src/lib.rs @@ -10,7 +10,6 @@ //! tuning), and — on Windows — [`dxgi`] (the capture identity + D3D11 device creation). // Unsafe-proof program: every `unsafe {}` / `unsafe impl` must carry a `// SAFETY:` proof. -#![deny(clippy::undocumented_unsafe_blocks)] pub mod hdr; pub mod metronome; diff --git a/crates/pf-frame/src/session_tuning.rs b/crates/pf-frame/src/session_tuning.rs index 0e6700a6..0695fcbc 100644 --- a/crates/pf-frame/src/session_tuning.rs +++ b/crates/pf-frame/src/session_tuning.rs @@ -11,9 +11,6 @@ //! state) auto-revert at thread exit (= session end); the process-wide bits revert at process exit. //! See `design/host-latency-plan.md` Tier 3A. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - #[cfg(target_os = "windows")] mod imp { #![allow(non_snake_case)] diff --git a/crates/pf-frame/src/thread_qos.rs b/crates/pf-frame/src/thread_qos.rs index bc7ba85c..80a748bb 100644 --- a/crates/pf-frame/src/thread_qos.rs +++ b/crates/pf-frame/src/thread_qos.rs @@ -3,9 +3,6 @@ //! can't deschedule them; the native, GameStream, and direct-NVENC send threads all reach this the //! same way (`pf_frame::thread_qos::boost_thread_priority`). -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - /// Raise the current thread's OS scheduling priority so a CPU-heavy game can't deschedule our /// capture/encode/send threads. This matters even though our GPU work is already HIGH priority: the /// GPU scheduler can only favour commands we've actually SUBMITTED, so if a normal-priority thread is diff --git a/crates/pf-gpu/src/lib.rs b/crates/pf-gpu/src/lib.rs index 5364795b..241b38d2 100644 --- a/crates/pf-gpu/src/lib.rs +++ b/crates/pf-gpu/src/lib.rs @@ -23,7 +23,6 @@ //! live session actually encodes on, for the console's "in use" display. // Unsafe-proof program: every `unsafe {}` in this leaf carries a `// SAFETY:` proof. -#![deny(clippy::undocumented_unsafe_blocks)] use anyhow::Result; use serde::{Deserialize, Serialize}; diff --git a/crates/pf-inject/src/inject/linux/gamepad.rs b/crates/pf-inject/src/inject/linux/gamepad.rs index 0f557a4c..4250c15e 100644 --- a/crates/pf-inject/src/inject/linux/gamepad.rs +++ b/crates/pf-inject/src/inject/linux/gamepad.rs @@ -15,9 +15,6 @@ //! `` on x86_64. `/dev/uinput` needs a udev rule + `input` group membership //! (see `scripts/60-punktfunk.rules`); creation fails with a clear error otherwise. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use crate::pad_slots::PadSlots; use anyhow::{bail, Result}; use punktfunk_core::input::{gamepad, GamepadFrame, MAX_PADS}; diff --git a/crates/pf-inject/src/inject/linux/kwin_fake_input.rs b/crates/pf-inject/src/inject/linux/kwin_fake_input.rs index 2d577692..5c8e9efc 100644 --- a/crates/pf-inject/src/inject/linux/kwin_fake_input.rs +++ b/crates/pf-inject/src/inject/linux/kwin_fake_input.rs @@ -17,8 +17,6 @@ //! output's logical rectangle — the same shape the libei backend uses with its EI region. #![allow(clippy::all, dead_code, non_camel_case_types, non_snake_case, unused)] -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] use super::{gs_button_to_evdev, vk_to_evdev, InputEvent, InputInjector}; use anyhow::{Context, Result}; diff --git a/crates/pf-inject/src/inject/linux/wlr.rs b/crates/pf-inject/src/inject/linux/wlr.rs index c506e5a8..34bf2c76 100644 --- a/crates/pf-inject/src/inject/linux/wlr.rs +++ b/crates/pf-inject/src/inject/linux/wlr.rs @@ -6,9 +6,6 @@ //! to evdev/US), and translate events into virtual pointer/keyboard requests, tracking modifier //! state so the compositor resolves shifted keysyms correctly. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use super::{gs_button_to_evdev, vk_to_evdev, InputEvent, InputInjector}; use anyhow::{bail, Context, Result}; use punktfunk_core::input::InputKind; diff --git a/crates/pf-inject/src/inject/windows/pointer_windows.rs b/crates/pf-inject/src/inject/windows/pointer_windows.rs index f6664e24..109c70b4 100644 --- a/crates/pf-inject/src/inject/windows/pointer_windows.rs +++ b/crates/pf-inject/src/inject/windows/pointer_windows.rs @@ -15,9 +15,6 @@ //! with its position (never at a stale point), tip edges get their own DOWN/UP frames, and a //! range-leave is a final frame without `INRANGE`. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it. -#![deny(clippy::undocumented_unsafe_blocks)] - use anyhow::{Context, Result}; use punktfunk_core::input::{InputEvent, InputKind}; use punktfunk_core::quic::{ diff --git a/crates/pf-inject/src/inject/windows/sendinput.rs b/crates/pf-inject/src/inject/windows/sendinput.rs index 4f1baab9..93247118 100644 --- a/crates/pf-inject/src/inject/windows/sendinput.rs +++ b/crates/pf-inject/src/inject/windows/sendinput.rs @@ -14,9 +14,6 @@ //! user's, and any layout re-reads a *position* as a *character* — on a German host that is //! exactly the y↔z swap / ü-on-ö scramble. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it. -#![deny(clippy::undocumented_unsafe_blocks)] - use anyhow::Result; use punktfunk_core::input::{InputEvent, InputKind}; use std::mem::size_of; diff --git a/crates/pf-inject/src/lib.rs b/crates/pf-inject/src/lib.rs index dd1b3eb0..71bf4957 100644 --- a/crates/pf-inject/src/lib.rs +++ b/crates/pf-inject/src/lib.rs @@ -14,13 +14,6 @@ // Scaffold: trait methods + per-OS backends are defined ahead of the target that uses them. #![allow(dead_code)] -// Every unsafe block in this crate carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] -// …and its companion: without this, an `unsafe fn` body needs no blocks, so an unproven FFI call -// could hide inside one and still satisfy the deny above. The workspace keeps -// `unsafe_op_in_unsafe_fn` at `warn` while the encoder backends are cleared; this crate is at zero. -#![deny(unsafe_op_in_unsafe_fn)] - use anyhow::Result; use punktfunk_core::input::{InputEvent, InputKind}; diff --git a/crates/pf-presenter/src/lib.rs b/crates/pf-presenter/src/lib.rs index c868e158..431d3b5f 100644 --- a/crates/pf-presenter/src/lib.rs +++ b/crates/pf-presenter/src/lib.rs @@ -17,7 +17,6 @@ //! the decode chain there is Vulkan → D3D11VA → software. // Unsafe-proof program: every `unsafe {}` in this crate carries a `// SAFETY:` proof. -#![deny(clippy::undocumented_unsafe_blocks)] // THE VULKAN CONTRACT, stated once - most `// SAFETY:` proofs in this crate are an instance of it. // diff --git a/crates/pf-update/Cargo.toml b/crates/pf-update/Cargo.toml index 26ba05cc..051fa8b8 100644 --- a/crates/pf-update/Cargo.toml +++ b/crates/pf-update/Cargo.toml @@ -18,3 +18,6 @@ path = "src/main.rs" [target.'cfg(target_os = "linux")'.dependencies] serde = { version = "1", features = ["derive"] } serde_json = "1" + +[lints] +workspace = true diff --git a/crates/pf-vdisplay/src/lib.rs b/crates/pf-vdisplay/src/lib.rs index 319aa59c..f27baa20 100644 --- a/crates/pf-vdisplay/src/lib.rs +++ b/crates/pf-vdisplay/src/lib.rs @@ -39,13 +39,6 @@ // honest. (Was a bare crate-wide allow whose "scaffold, defined ahead of the target that uses them" // rationale had stopped being true.) #![cfg_attr(not(target_os = "linux"), allow(dead_code))] -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] -// …and that program only covers a whole `unsafe fn` body once the body needs its own block: in -// edition 2021 `unsafe_op_in_unsafe_fn` is allow-by-default, which exempted this crate's hardest -// FFI from the deny above — every IOCTL wrapper, and `restore_displays_ccd`, the call the whole -// Windows teardown path depends on to give the operator their physical panels back. -#![deny(unsafe_op_in_unsafe_fn)] use anyhow::Result; pub use punktfunk_core::Mode; diff --git a/crates/pf-vdisplay/src/vdisplay/linux/kwin.rs b/crates/pf-vdisplay/src/vdisplay/linux/kwin.rs index b75e98bf..0eab03a4 100644 --- a/crates/pf-vdisplay/src/vdisplay/linux/kwin.rs +++ b/crates/pf-vdisplay/src/vdisplay/linux/kwin.rs @@ -23,9 +23,6 @@ //! "Could not find output". We talk raw Wayland on `$WAYLAND_DISPLAY`, so the host must run inside //! the KWin session's environment. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use super::{Mode, VirtualDisplay, VirtualOutput}; use anyhow::{anyhow, bail, Context, Result}; use std::os::fd::{AsFd, AsRawFd}; diff --git a/crates/pf-vdisplay/src/vdisplay/linux/kwin_output_mgmt.rs b/crates/pf-vdisplay/src/vdisplay/linux/kwin_output_mgmt.rs index 2a219a17..92b84b5f 100644 --- a/crates/pf-vdisplay/src/vdisplay/linux/kwin_output_mgmt.rs +++ b/crates/pf-vdisplay/src/vdisplay/linux/kwin_output_mgmt.rs @@ -20,8 +20,6 @@ //! each output's name / enabled / priority / current-mode size, then build a //! `kde_output_configuration_v2` and `apply()` it, waiting for `applied` / `failed`. -#![deny(clippy::undocumented_unsafe_blocks)] - use std::collections::HashMap; use std::os::fd::{AsFd, AsRawFd}; use std::time::{Duration, Instant}; diff --git a/crates/pf-vdisplay/src/vdisplay/windows/manager.rs b/crates/pf-vdisplay/src/vdisplay/windows/manager.rs index d49a4f50..049da9da 100644 --- a/crates/pf-vdisplay/src/vdisplay/windows/manager.rs +++ b/crates/pf-vdisplay/src/vdisplay/windows/manager.rs @@ -14,9 +14,6 @@ //! its `Drop` releases the refcount (a *stale* lease — its monitor was preempted + recreated under it — //! is a no-op, so it can never tear down the live monitor). -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use std::collections::BTreeMap; use std::os::windows::io::{AsRawHandle, FromRawHandle, OwnedHandle}; use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU64, Ordering}; diff --git a/crates/pf-vdisplay/src/vdisplay/windows/pf_vdisplay.rs b/crates/pf-vdisplay/src/vdisplay/windows/pf_vdisplay.rs index 355d3ee6..e91e8ae7 100644 --- a/crates/pf-vdisplay/src/vdisplay/windows/pf_vdisplay.rs +++ b/crates/pf-vdisplay/src/vdisplay/windows/pf_vdisplay.rs @@ -16,9 +16,6 @@ //! Only the driver-specific bits (GUID, IOCTL codes, request/reply structs, the version handshake) are //! here, per `pf_driver_proto`. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use std::ffi::c_void; use std::mem::size_of; use std::os::windows::io::{AsRawHandle, FromRawHandle, OwnedHandle}; diff --git a/crates/pf-vkdecode/src/lib.rs b/crates/pf-vkdecode/src/lib.rs index d46407ae..896f8f5a 100644 --- a/crates/pf-vkdecode/src/lib.rs +++ b/crates/pf-vkdecode/src/lib.rs @@ -112,10 +112,9 @@ //! Unsafe posture: unlike pf-bitstream (which forbids unsafe outright), this crate //! cannot — the `ash::vk::native` bindgen structs are zero-initialized the way the //! encode side does it (`pf-encode/src/enc/linux/vk_build.rs`), and the GPU half is -//! Vulkan FFI. Every unsafe block therefore carries a written `// SAFETY:` proof, -//! enforced (and unlike the encoder there is NO file-level -//! `unsafe_op_in_unsafe_fn` exemption — every operation is individually fenced): -#![deny(clippy::undocumented_unsafe_blocks)] +//! Vulkan FFI. Every unsafe block therefore carries a written `// SAFETY:` proof — enforced by +//! the workspace `[workspace.lints]` tables, and (unlike the encoder) with NO file-level +//! `unsafe_op_in_unsafe_fn` exemption: every operation is individually fenced. pub mod caps; pub mod caps_av1; diff --git a/crates/pf-vkdecode/tests/gpu_parity.rs b/crates/pf-vkdecode/tests/gpu_parity.rs index b1a03d3f..d4675f19 100644 --- a/crates/pf-vkdecode/tests/gpu_parity.rs +++ b/crates/pf-vkdecode/tests/gpu_parity.rs @@ -88,8 +88,6 @@ //! the readback geometry (row pitch / crop) or intra decode; mismatches that //! only appear on later frames point at inter prediction / DPB management. -#![deny(clippy::undocumented_unsafe_blocks)] - mod common; use ash::vk; diff --git a/crates/pf-vkdecode/tests/gpu_smoke.rs b/crates/pf-vkdecode/tests/gpu_smoke.rs index b7c4bba3..53efb01d 100644 --- a/crates/pf-vkdecode/tests/gpu_smoke.rs +++ b/crates/pf-vkdecode/tests/gpu_smoke.rs @@ -39,8 +39,6 @@ //! so releases pass `false`), soak, and both vendors' DPB arrangements at once //! (each box exercises only its own). -#![deny(clippy::undocumented_unsafe_blocks)] - mod common; use ash::vk; diff --git a/crates/pf-win-display/src/display_events.rs b/crates/pf-win-display/src/display_events.rs index 6dbe2d75..d0988703 100644 --- a/crates/pf-win-display/src/display_events.rs +++ b/crates/pf-win-display/src/display_events.rs @@ -28,9 +28,6 @@ //! suspects — without ever touching the CCD lock itself (the display-config lock is exactly what //! stalls during churn; the capture thread must never block on it). -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use std::collections::VecDeque; use std::sync::{Mutex, Once, OnceLock}; use std::time::Instant; diff --git a/crates/pf-win-display/src/lib.rs b/crates/pf-win-display/src/lib.rs index ab4a83a5..46a9b928 100644 --- a/crates/pf-win-display/src/lib.rs +++ b/crates/pf-win-display/src/lib.rs @@ -12,8 +12,6 @@ // `win_display` has denied both unsafe-proof lints since its CCD helpers stopped being `unsafe fn`; // hoist that to the crate root so the smaller modules (`input_desktop`, `monitor_devnode`, // `display_events`) and any future one are covered by default rather than by remembering to opt in. -#![deny(clippy::undocumented_unsafe_blocks)] -#![deny(unsafe_op_in_unsafe_fn)] #[cfg(target_os = "windows")] pub mod display_events; diff --git a/crates/pf-win-display/src/win_display.rs b/crates/pf-win-display/src/win_display.rs index e0b5b66d..80cbd8d7 100644 --- a/crates/pf-win-display/src/win_display.rs +++ b/crates/pf-win-display/src/win_display.rs @@ -8,13 +8,6 @@ //! them, which let the SudoVDA backend be dropped without losing them (audit §9 / Goal 2 — done). The //! plan's `windows/display_ccd.rs`. Extracted verbatim from the former SudoVDA backend before its removal. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] -// …and that program only covers a whole `unsafe fn` body once the body needs its own block: in -// edition 2021 `unsafe_op_in_unsafe_fn` is allow-by-default, which exempted every CCD/GDI helper -// below — including `restore_displays_ccd`, the call pf-vdisplay's teardown path depends on to give -// the operator their physical panels back. -#![deny(unsafe_op_in_unsafe_fn)] // The CCD/GDI helpers below are SAFE fns. They were `unsafe fn` for a decade of habit rather than a // memory-safety obligation: every one takes `Copy` scalars or borrowed Rust data, returns owned // values, and discharges its own FFI preconditions internally (`retry_set_display_config` even binds diff --git a/crates/pf-zerocopy/src/dmabuf_fence.rs b/crates/pf-zerocopy/src/dmabuf_fence.rs index 40d68ad0..48a7cff1 100644 --- a/crates/pf-zerocopy/src/dmabuf_fence.rs +++ b/crates/pf-zerocopy/src/dmabuf_fence.rs @@ -14,9 +14,6 @@ //! wait, no harm, and `WaitOutcome::NoFence` tells us the driver doesn't fence (so zero-copy //! would still race). -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use std::os::fd::RawFd; use std::time::{Duration, Instant}; diff --git a/crates/pf-zerocopy/src/imp/client.rs b/crates/pf-zerocopy/src/imp/client.rs index 563cb84d..8e63e9db 100644 --- a/crates/pf-zerocopy/src/imp/client.rs +++ b/crates/pf-zerocopy/src/imp/client.rs @@ -6,9 +6,6 @@ //! A worker death — the whole point of the isolation — surfaces as an `Err` with //! [`RemoteImporter::dead`] set, never as a host fault. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use super::cuda::{self, CUdeviceptr, DeviceBuffer, CU_IPC_HANDLE_SIZE}; use super::egl::DmabufPlane; use super::ipc; diff --git a/crates/pf-zerocopy/src/imp/cuda.rs b/crates/pf-zerocopy/src/imp/cuda.rs index bfb09f48..ddcea5a2 100644 --- a/crates/pf-zerocopy/src/imp/cuda.rs +++ b/crates/pf-zerocopy/src/imp/cuda.rs @@ -18,8 +18,6 @@ //! driver — see [`super::egl`].) #![allow(non_camel_case_types, non_snake_case)] -// Every `unsafe` block/impl below carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] use anyhow::{bail, Result}; use std::os::raw::{c_uint, c_void}; diff --git a/crates/pf-zerocopy/src/imp/cuda/ffi.rs b/crates/pf-zerocopy/src/imp/cuda/ffi.rs index f77d4932..7e8a18b9 100644 --- a/crates/pf-zerocopy/src/imp/cuda/ffi.rs +++ b/crates/pf-zerocopy/src/imp/cuda/ffi.rs @@ -5,8 +5,6 @@ //! and drive this layer. #![allow(non_camel_case_types, non_snake_case)] -// Every `unsafe` block/impl below carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] use anyhow::{bail, Result}; use std::os::raw::{c_int, c_uint, c_void}; diff --git a/crates/pf-zerocopy/src/imp/egl.rs b/crates/pf-zerocopy/src/imp/egl.rs index 9d6b1a81..a7036597 100644 --- a/crates/pf-zerocopy/src/imp/egl.rs +++ b/crates/pf-zerocopy/src/imp/egl.rs @@ -12,8 +12,6 @@ //! owned [`DeviceBuffer`] so the dmabuf can be returned to the compositor immediately. #![allow(non_upper_case_globals)] -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] use super::cuda::{self, DeviceBuffer}; use anyhow::{ensure, Context as _, Result}; diff --git a/crates/pf-zerocopy/src/imp/egl/gl.rs b/crates/pf-zerocopy/src/imp/egl/gl.rs index 32116f7c..b2062fdf 100644 --- a/crates/pf-zerocopy/src/imp/egl/gl.rs +++ b/crates/pf-zerocopy/src/imp/egl/gl.rs @@ -5,8 +5,6 @@ //! [`super`]. #![allow(non_upper_case_globals)] -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] use anyhow::{bail, ensure, Result}; use std::os::raw::{c_int, c_void}; diff --git a/crates/pf-zerocopy/src/imp/ipc.rs b/crates/pf-zerocopy/src/imp/ipc.rs index 89fc8de4..f94e0484 100644 --- a/crates/pf-zerocopy/src/imp/ipc.rs +++ b/crates/pf-zerocopy/src/imp/ipc.rs @@ -18,9 +18,6 @@ //! inode with `punktfunk-host`, because a shared inode shares the file capability — so it passes //! its own resolved path to [`spawn_worker`] instead. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use serde::de::DeserializeOwned; use serde::Serialize; use std::fs::File; diff --git a/crates/pf-zerocopy/src/imp/vkslot.rs b/crates/pf-zerocopy/src/imp/vkslot.rs index 9bf703da..674b87c5 100644 --- a/crates/pf-zerocopy/src/imp/vkslot.rs +++ b/crates/pf-zerocopy/src/imp/vkslot.rs @@ -34,9 +34,6 @@ //! Falls back cleanly: if bring-up fails the encoder allocates plain CUDA surfaces and composite //! mode degrades to no cursor (warned once) — never a failed session. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use super::cuda::{self, CUdeviceptr}; use anyhow::{anyhow, Context as _, Result}; use ash::vk; diff --git a/crates/pf-zerocopy/src/imp/vulkan.rs b/crates/pf-zerocopy/src/imp/vulkan.rs index 08157bc4..a7990424 100644 --- a/crates/pf-zerocopy/src/imp/vulkan.rs +++ b/crates/pf-zerocopy/src/imp/vulkan.rs @@ -16,9 +16,6 @@ //! a stream's life). Falls back cleanly: any init/import error disables the importer and the //! CPU mmap path takes over. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use super::cuda::{self, DeviceBuffer}; use anyhow::{anyhow, bail, Context as _, Result}; use ash::vk; diff --git a/crates/pf-zerocopy/src/imp/worker.rs b/crates/pf-zerocopy/src/imp/worker.rs index a439384c..45782c68 100644 --- a/crates/pf-zerocopy/src/imp/worker.rs +++ b/crates/pf-zerocopy/src/imp/worker.rs @@ -9,9 +9,6 @@ //! only happens after the capturer AND every in-flight frame on the host side are gone, so pooled //! device memory is never freed under a frame the host still reads. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use super::cuda::{self, CUdeviceptr, DeviceBuffer}; use super::egl::{DmabufPlane, EglImporter}; use super::ipc; diff --git a/crates/pf-zerocopy/src/lib.rs b/crates/pf-zerocopy/src/lib.rs index 8f6d1eee..f3f0c44a 100644 --- a/crates/pf-zerocopy/src/lib.rs +++ b/crates/pf-zerocopy/src/lib.rs @@ -8,13 +8,9 @@ //! consumes the shared frame vocabulary, which sits ABOVE this crate (this crate provides the //! `DeviceBuffer` that vocabulary's `FramePayload::Cuda` owns). -// Unsafe-proof program: every `unsafe {}` / `unsafe impl` must carry a `// SAFETY:` proof. Each -// file keeps its own `#![deny(...)]` too; this crate-root deny is the catch-all gate. -// `unsafe_op_in_unsafe_fn` closes the gap the clippy lint leaves: operations inside an -// `unsafe fn` body are not "unsafe blocks", so without it ~45 functions' worth of raw driver -// calls sat OUTSIDE the invariant this crate advertises. -#![deny(clippy::undocumented_unsafe_blocks)] -#![deny(unsafe_op_in_unsafe_fn)] +// Unsafe-proof program: every `unsafe {}` / `unsafe impl` carries a `// SAFETY:` proof, and +// `unsafe fn` bodies need explicit blocks (~45 functions' worth of raw driver calls used to sit +// outside that invariant). Both lints are enforced by the workspace `[workspace.lints]` tables. /// Wait for a dmabuf's implicit read-ready fence (`DMA_BUF_IOCTL_EXPORT_SYNC_FILE` + poll). #[cfg(target_os = "linux")] diff --git a/crates/punktfunk-core/src/lib.rs b/crates/punktfunk-core/src/lib.rs index 42780f77..cfd6b7e5 100644 --- a/crates/punktfunk-core/src/lib.rs +++ b/crates/punktfunk-core/src/lib.rs @@ -46,7 +46,6 @@ // `qos_windows`) — sendmmsg/recvmsg_x/USO/qWAVE move caller-owned buffers, nothing more. // A new module parsing wire data may NOT add a carve-out. #![deny(unsafe_code)] -#![deny(clippy::undocumented_unsafe_blocks)] #![forbid(unsafe_op_in_unsafe_fn)] pub mod abi; diff --git a/crates/punktfunk-host/src/audio/windows/audio_control.rs b/crates/punktfunk-host/src/audio/windows/audio_control.rs index c0f24f5e..1f4f2be2 100644 --- a/crates/punktfunk-host/src/audio/windows/audio_control.rs +++ b/crates/punktfunk-host/src/audio/windows/audio_control.rs @@ -46,9 +46,6 @@ //! `PUNKTFUNK_KEEP_DEFAULT`) leaves the user's chosen defaults untouched — the plan is still //! computed, since the mic must still pick a target. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it. -#![deny(clippy::undocumented_unsafe_blocks)] - use super::wiring_plan::{self, plan, plan_with_formats, Endpoint, MixFormat, Wiring}; use anyhow::{anyhow, bail, Result}; use std::ffi::c_void; diff --git a/crates/punktfunk-host/src/audio/windows/audio_probe.rs b/crates/punktfunk-host/src/audio/windows/audio_probe.rs index b756c3b5..59356cd3 100644 --- a/crates/punktfunk-host/src/audio/windows/audio_probe.rs +++ b/crates/punktfunk-host/src/audio/windows/audio_probe.rs @@ -21,9 +21,6 @@ //! endpoint of that name, and the probe restores the default playback/recording devices it //! disturbed before exiting. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it. -#![deny(clippy::undocumented_unsafe_blocks)] - use super::pad_endpoint as pe; use super::{audio_control, SAMPLE_RATE}; use anyhow::{anyhow, bail, Context, Result}; diff --git a/crates/punktfunk-host/src/audio/windows/devnode_cleanup.rs b/crates/punktfunk-host/src/audio/windows/devnode_cleanup.rs index de36e8d4..97b5f070 100644 --- a/crates/punktfunk-host/src/audio/windows/devnode_cleanup.rs +++ b/crates/punktfunk-host/src/audio/windows/devnode_cleanup.rs @@ -24,9 +24,6 @@ //! bundled one all carry no marker and are therefore untouchable here — uninstalling punktfunk //! removes what punktfunk created, and nothing else. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it. -#![deny(clippy::undocumented_unsafe_blocks)] - use super::{audio_control, audio_probe, minted, pad_endpoint as pe}; use anyhow::Result; use windows::Win32::Devices::DeviceAndDriverInstallation::SetupDiEnumDeviceInfo; diff --git a/crates/punktfunk-host/src/audio/windows/pad_endpoint.rs b/crates/punktfunk-host/src/audio/windows/pad_endpoint.rs index 624ad95d..4bc65054 100644 --- a/crates/punktfunk-host/src/audio/windows/pad_endpoint.rs +++ b/crates/punktfunk-host/src/audio/windows/pad_endpoint.rs @@ -35,9 +35,6 @@ //! COM discipline matches the sibling modules: WASAPI/COM objects live on the thread that made //! them (the provisioning worker, the capture thread); only channels and plain data cross. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it. -#![deny(clippy::undocumented_unsafe_blocks)] - use super::{audio_control, AudioCapturer, SAMPLE_RATE}; use anyhow::{anyhow, bail, Context, Result}; use std::collections::{HashSet, VecDeque}; diff --git a/crates/punktfunk-host/src/audio/windows/wasapi_mic.rs b/crates/punktfunk-host/src/audio/windows/wasapi_mic.rs index 3339c27b..e3a091dd 100644 --- a/crates/punktfunk-host/src/audio/windows/wasapi_mic.rs +++ b/crates/punktfunk-host/src/audio/windows/wasapi_mic.rs @@ -28,9 +28,6 @@ //! ([`VirtualMic::set_target_depth`]), filling silence when the client isn't talking. WASAPI //! objects are `!Send`, so they live entirely on that thread (mirrors `WasapiLoopbackCapturer`). -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it. -#![deny(clippy::undocumented_unsafe_blocks)] - use super::{audio_control, MicBackendStats, VirtualMic, SAMPLE_RATE}; use anyhow::{anyhow, Context, Result}; use std::collections::VecDeque; diff --git a/crates/punktfunk-host/src/gamestream/audio.rs b/crates/punktfunk-host/src/gamestream/audio.rs index 2a2e1cff..8442453c 100644 --- a/crates/punktfunk-host/src/gamestream/audio.rs +++ b/crates/punktfunk-host/src/gamestream/audio.rs @@ -17,9 +17,6 @@ //! data packets are consumed immediately and missing parity only costs loss recovery — so //! the validated stereo path stays byte-identical (data packets only, exactly as before). -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it. -#![deny(clippy::undocumented_unsafe_blocks)] - #[cfg(any(target_os = "linux", target_os = "windows", test))] use crate::audio::SAMPLE_RATE; #[cfg(any(target_os = "linux", target_os = "windows"))] diff --git a/crates/punktfunk-host/src/gamestream/stream.rs b/crates/punktfunk-host/src/gamestream/stream.rs index 41f5d824..49c8ef3c 100644 --- a/crates/punktfunk-host/src/gamestream/stream.rs +++ b/crates/punktfunk-host/src/gamestream/stream.rs @@ -3,9 +3,6 @@ //! either real portal desktop capture (`PUNKTFUNK_VIDEO_SOURCE=portal`, the portal PipeWire path) or //! a synthetic test pattern (default). Runs on its own native thread. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it. -#![deny(clippy::undocumented_unsafe_blocks)] - use super::video::{FrameType, VideoPacketizer}; use super::VIDEO_PORT; use crate::capture::{self, Capturer, FastSyntheticCapturer}; diff --git a/crates/punktfunk-host/src/linux/drm_sync.rs b/crates/punktfunk-host/src/linux/drm_sync.rs index a5989d82..d3f9fe22 100644 --- a/crates/punktfunk-host/src/linux/drm_sync.rs +++ b/crates/punktfunk-host/src/linux/drm_sync.rs @@ -8,8 +8,6 @@ //! verified (ioctl numbers + a live signal→wait round trip), ready to wire in the moment a producer //! gains working `SPA_META_SyncTimeline`. #![allow(dead_code)] -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] //! //! Compositors that render directly into the PipeWire buffer pool (Mutter's virtual //! monitors) hand buffers over at GPU-submit time; on drivers without implicit dmabuf diff --git a/crates/punktfunk-host/src/linux/gpuclocks.rs b/crates/punktfunk-host/src/linux/gpuclocks.rs index 62c467da..acf7660c 100644 --- a/crates/punktfunk-host/src/linux/gpuclocks.rs +++ b/crates/punktfunk-host/src/linux/gpuclocks.rs @@ -37,8 +37,6 @@ //! self-heals. Deliberately //! NOT default-on: it defeats idle downclocking for the whole box and is wrong on //! battery-powered hosts. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] use std::os::raw::{c_char, c_int, c_uint, c_void}; use std::sync::{Mutex, OnceLock}; diff --git a/crates/punktfunk-host/src/main.rs b/crates/punktfunk-host/src/main.rs index 9c5b4484..60022dd2 100644 --- a/crates/punktfunk-host/src/main.rs +++ b/crates/punktfunk-host/src/main.rs @@ -13,16 +13,10 @@ // Scaffold: trait methods and config paths are defined ahead of their backends. #![allow(dead_code)] -// Unsafe-proof program: every `unsafe {}` / `unsafe impl` in the crate must carry a `// SAFETY:` -// proof of why it is sound. This crate-root deny is the permanent, catch-all gate (it also covers -// any future module); individual files keep their own `#![deny(...)]` as belt-and-suspenders. -#![deny(clippy::undocumented_unsafe_blocks)] -// The companion gate: a proof only covers what it is attached to, and an `unsafe fn` body without -// this lint needs no blocks at all — so an unproven FFI call could hide inside one and satisfy the -// deny above. The workspace sets `unsafe_op_in_unsafe_fn` to `warn` (a ratchet across ~590 sites); -// this crate is at zero, so it denies. Keep the marker only where a caller can actually violate +// Unsafe-proof program (both lints now enforced by the workspace `[workspace.lints]` tables): +// every `unsafe {}` / `unsafe impl` carries a `// SAFETY:` proof, and `unsafe fn` bodies need +// explicit blocks. Keep the `unsafe fn` marker only where a caller can actually violate // something — a raw pointer or a borrowed `HANDLE` parameter, as in `service::spawn_host`. -#![deny(unsafe_op_in_unsafe_fn)] mod audio; mod bringup; diff --git a/crates/punktfunk-host/src/native.rs b/crates/punktfunk-host/src/native.rs index 263e3bd6..f8d5b8c7 100644 --- a/crates/punktfunk-host/src/native.rs +++ b/crates/punktfunk-host/src/native.rs @@ -22,9 +22,6 @@ //! Trust: the host serves with its persistent identity (`~/.config/punktfunk/cert.pem`, shared //! with GameStream pairing) and logs the SHA-256 fingerprint clients pin. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use anyhow::{anyhow, Context, Result}; use punktfunk_core::config::{CompositorPref, FecConfig, FecScheme, GamepadPref, Role}; use punktfunk_core::input::{InputEvent, InputKind}; diff --git a/crates/punktfunk-host/src/windows/crash.rs b/crates/punktfunk-host/src/windows/crash.rs index 01a5c4f6..fb0e4885 100644 --- a/crates/punktfunk-host/src/windows/crash.rs +++ b/crates/punktfunk-host/src/windows/crash.rs @@ -9,7 +9,6 @@ //! diagnosis. The Rust-panic analogue (a panic hook that tees into `tracing`) lives in `main()`. // Every `unsafe` block in this file carries a `// SAFETY:` proof (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] use windows::Win32::Foundation::HMODULE; use windows::Win32::System::Diagnostics::Debug::{ diff --git a/crates/punktfunk-host/src/windows/interactive.rs b/crates/punktfunk-host/src/windows/interactive.rs index 719aebe4..1ffc1b51 100644 --- a/crates/punktfunk-host/src/windows/interactive.rs +++ b/crates/punktfunk-host/src/windows/interactive.rs @@ -14,13 +14,8 @@ //! that is correct for launching *our own* streamer, but a store launcher needs the real user's token //! for activation + auth). The host process itself stays SYSTEM. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] -// …and the proofs only cover the whole file once an `unsafe fn` body needs its own blocks: the -// workspace sets `unsafe_op_in_unsafe_fn` to `warn`, which is a ratchet, not a floor. This module is -// at zero, so hold it there — `merged_env_block`'s pointer walk is the one real contract here, and -// it must not silently re-absorb the FFI calls around it. -#![deny(unsafe_op_in_unsafe_fn)] +// This module is at zero `unsafe fn` markers; hold it there — `merged_env_block`'s pointer walk +// is the one real contract here, and it must not silently re-absorb the FFI calls around it. use anyhow::{bail, Context, Result}; use std::path::Path; diff --git a/crates/punktfunk-host/src/windows/service.rs b/crates/punktfunk-host/src/windows/service.rs index efdbb2da..8f0c1fab 100644 --- a/crates/punktfunk-host/src/windows/service.rs +++ b/crates/punktfunk-host/src/windows/service.rs @@ -25,9 +25,6 @@ //! loaded into the service's environment and carried to the host child. Logs land in //! `%ProgramData%\punktfunk\logs\`. -// Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). -#![deny(clippy::undocumented_unsafe_blocks)] - use anyhow::{bail, Context, Result}; use std::ffi::{c_void, OsString}; use std::os::windows::io::{AsRawHandle, FromRawHandle, OwnedHandle}; diff --git a/crates/punktfunk-host/vendor/usbip-sim/Cargo.toml b/crates/punktfunk-host/vendor/usbip-sim/Cargo.toml index 0f1a06a9..fe572326 100644 --- a/crates/punktfunk-host/vendor/usbip-sim/Cargo.toml +++ b/crates/punktfunk-host/vendor/usbip-sim/Cargo.toml @@ -1,3 +1,7 @@ +# Vendored snapshot — like pf-bitstream/vendor/cros-codecs, deliberately NOT opted into the +# workspace [lints] tables: upstream code stays as close to pristine as the trim allows, so a +# re-sync against upstream stays a diff, not an archaeology dig. (Zero `unsafe` today anyway.) +# # Vendored + trimmed copy of the `usbip` crate (jiegec/usbip v0.8.0, MIT), reduced to the # USB/IP *server simulation* path only: we present a virtual Steam Deck and let the local # `vhci_hcd` attach it. The upstream crate hard-depends on `rusb`→`libusb1-sys` (for its USB diff --git a/crates/punktfunk-tray/src/main.rs b/crates/punktfunk-tray/src/main.rs index 387e2a7e..6f6eef46 100644 --- a/crates/punktfunk-tray/src/main.rs +++ b/crates/punktfunk-tray/src/main.rs @@ -11,7 +11,6 @@ //! details. Windows-subsystem binary — a console exe in the HKLM Run key would flash a terminal //! window at every sign-in. // Unsafe-proof program: every `unsafe {}` in the tray carries a `// SAFETY:` proof. -#![deny(clippy::undocumented_unsafe_blocks)] #![cfg_attr(windows, windows_subsystem = "windows")] #[cfg(target_os = "linux")] diff --git a/crates/pyrowave-sys/src/lib.rs b/crates/pyrowave-sys/src/lib.rs index 9b91a0e8..df5f68b3 100644 --- a/crates/pyrowave-sys/src/lib.rs +++ b/crates/pyrowave-sys/src/lib.rs @@ -23,6 +23,8 @@ mod tests { #[test] fn api_version_matches_vendored_pin() { let (mut major, mut minor, mut patch) = (0u32, 0u32, 0u32); + // SAFETY: the version query writes three u32s through live local out-pointers and + // touches no device or global state. unsafe { pyrowave_get_api_version(&mut major, &mut minor, &mut patch) }; assert_eq!((major, minor, patch), (0, 4, 0), "vendored pyrowave API version moved — re-check the §4.2 protocol coupling before bumping"); } diff --git a/packaging/windows/drivers/Cargo.toml b/packaging/windows/drivers/Cargo.toml index 76ff5e8b..837613b0 100644 --- a/packaging/windows/drivers/Cargo.toml +++ b/packaging/windows/drivers/Cargo.toml @@ -15,6 +15,17 @@ version = "0.0.1" license = "MIT OR Apache-2.0" publish = false +# The same unsafe discipline as the main workspace (see its Cargo.toml for the full rationale). +# Restated here because THIS IS A SEPARATE WORKSPACE: the main tree's [workspace.lints] does not +# reach these crates, so any "workspace-wide" lint claim has to be made here too or it is false +# for the driver surface. Every member opts in with `[lints] workspace = true`. +# (`unsafe_op_in_unsafe_fn` is already the edition-2024 default; deny pins it explicitly.) +[workspace.lints.rust] +unsafe_op_in_unsafe_fn = "deny" + +[workspace.lints.clippy] +undocumented_unsafe_blocks = "deny" + [workspace.dependencies] wdk = "0.4.1" wdk-sys = "0.5.1" diff --git a/packaging/windows/drivers/pf-gamepad/Cargo.toml b/packaging/windows/drivers/pf-gamepad/Cargo.toml index a39bc8c3..24343c3b 100644 --- a/packaging/windows/drivers/pf-gamepad/Cargo.toml +++ b/packaging/windows/drivers/pf-gamepad/Cargo.toml @@ -32,3 +32,6 @@ pf-umdf-util.workspace = true default = ["hid"] hid = ["wdk-sys/hid"] nightly = ["wdk-sys/nightly", "wdk/nightly"] + +[lints] +workspace = true diff --git a/packaging/windows/drivers/pf-gamepad/src/lib.rs b/packaging/windows/drivers/pf-gamepad/src/lib.rs index cd60fb3a..958ba612 100644 --- a/packaging/windows/drivers/pf-gamepad/src/lib.rs +++ b/packaging/windows/drivers/pf-gamepad/src/lib.rs @@ -16,8 +16,6 @@ #![allow(non_snake_case, non_upper_case_globals, clippy::missing_safety_doc)] // Every remaining `unsafe {}` (all WDF setup FFI) must carry a `// SAFETY:` proof. -#![deny(unsafe_op_in_unsafe_fn)] -#![deny(clippy::undocumented_unsafe_blocks)] use core::sync::atomic::{AtomicPtr, AtomicU32, Ordering}; diff --git a/packaging/windows/drivers/pf-mouse/Cargo.toml b/packaging/windows/drivers/pf-mouse/Cargo.toml index 64fb4400..9dfa2143 100644 --- a/packaging/windows/drivers/pf-mouse/Cargo.toml +++ b/packaging/windows/drivers/pf-mouse/Cargo.toml @@ -30,3 +30,6 @@ pf-umdf-util.workspace = true default = ["hid"] hid = ["wdk-sys/hid"] nightly = ["wdk-sys/nightly", "wdk/nightly"] + +[lints] +workspace = true diff --git a/packaging/windows/drivers/pf-mouse/src/lib.rs b/packaging/windows/drivers/pf-mouse/src/lib.rs index a7b4ffbd..da6fce01 100644 --- a/packaging/windows/drivers/pf-mouse/src/lib.rs +++ b/packaging/windows/drivers/pf-mouse/src/lib.rs @@ -23,8 +23,6 @@ #![allow(non_snake_case, non_upper_case_globals, clippy::missing_safety_doc)] // Every remaining `unsafe {}` (all WDF setup FFI) must carry a `// SAFETY:` proof. -#![deny(unsafe_op_in_unsafe_fn)] -#![deny(clippy::undocumented_unsafe_blocks)] use core::sync::atomic::{AtomicPtr, AtomicU32, Ordering}; diff --git a/packaging/windows/drivers/pf-umdf-util/Cargo.toml b/packaging/windows/drivers/pf-umdf-util/Cargo.toml index a5a03134..6855abc4 100644 --- a/packaging/windows/drivers/pf-umdf-util/Cargo.toml +++ b/packaging/windows/drivers/pf-umdf-util/Cargo.toml @@ -15,3 +15,6 @@ description = "punktfunk UMDF driver util: safe shared-memory + sealed-channel + [dependencies] wdk-sys.workspace = true pf-driver-proto.workspace = true + +[lints] +workspace = true diff --git a/packaging/windows/drivers/pf-umdf-util/src/lib.rs b/packaging/windows/drivers/pf-umdf-util/src/lib.rs index c5992bd2..9abf12f0 100644 --- a/packaging/windows/drivers/pf-umdf-util/src/lib.rs +++ b/packaging/windows/drivers/pf-umdf-util/src/lib.rs @@ -19,12 +19,9 @@ //! `pf_gamepad`/`pf_mouse` tell the host, over the device stack, which process is serving this //! devnode. That is what the host trusts instead of the LocalService-writable bootstrap mailbox. //! -//! Lint gates (mirrored in every driver crate, enforced by the drivers CI clippy step): -//! `unsafe_op_in_unsafe_fn` + `clippy::undocumented_unsafe_blocks` — every remaining `unsafe {}` -//! must carry a `// SAFETY:` proof. - -#![deny(unsafe_op_in_unsafe_fn)] -#![deny(clippy::undocumented_unsafe_blocks)] +//! Lint gates (workspace-wide via this workspace's `[workspace.lints]`, enforced by the drivers +//! CI clippy step): `unsafe_op_in_unsafe_fn` + `clippy::undocumented_unsafe_blocks` — every +//! remaining `unsafe {}` must carry a `// SAFETY:` proof. pub mod channel; pub mod hid; diff --git a/packaging/windows/drivers/pf-vdisplay/Cargo.toml b/packaging/windows/drivers/pf-vdisplay/Cargo.toml index 884d44bb..e408a0af 100644 --- a/packaging/windows/drivers/pf-vdisplay/Cargo.toml +++ b/packaging/windows/drivers/pf-vdisplay/Cargo.toml @@ -42,3 +42,6 @@ features = [ "Win32_Graphics_Dxgi", "Win32_Graphics_Dxgi_Common", ] + +[lints] +workspace = true diff --git a/packaging/windows/drivers/pf-vdisplay/src/lib.rs b/packaging/windows/drivers/pf-vdisplay/src/lib.rs index b92fead1..4665282b 100644 --- a/packaging/windows/drivers/pf-vdisplay/src/lib.rs +++ b/packaging/windows/drivers/pf-vdisplay/src/lib.rs @@ -14,8 +14,6 @@ // proof. An IddCx display driver is inherently FFI-bound (D3D11 / IddCx DDIs / cross-process shared // textures), so it can't be unsafe-FREE the way the gamepad drivers now are (their logic moved onto the // safe `pf_umdf_util` layer); these gates make it unsafe-AUDITED instead, and stop it regressing. -#![deny(unsafe_op_in_unsafe_fn)] -#![deny(clippy::undocumented_unsafe_blocks)] #[macro_use] mod log; diff --git a/packaging/windows/drivers/pf-xusb/Cargo.toml b/packaging/windows/drivers/pf-xusb/Cargo.toml index 8cf59986..924a5e1a 100644 --- a/packaging/windows/drivers/pf-xusb/Cargo.toml +++ b/packaging/windows/drivers/pf-xusb/Cargo.toml @@ -29,3 +29,6 @@ pf-umdf-util.workspace = true [features] default = [] nightly = ["wdk-sys/nightly", "wdk/nightly"] + +[lints] +workspace = true diff --git a/packaging/windows/drivers/pf-xusb/src/lib.rs b/packaging/windows/drivers/pf-xusb/src/lib.rs index 4a8ce4c0..6711c810 100644 --- a/packaging/windows/drivers/pf-xusb/src/lib.rs +++ b/packaging/windows/drivers/pf-xusb/src/lib.rs @@ -22,8 +22,6 @@ #![allow(non_snake_case, non_upper_case_globals, clippy::missing_safety_doc)] // Every remaining `unsafe {}` (all WDF setup FFI) must carry a `// SAFETY:` proof. -#![deny(unsafe_op_in_unsafe_fn)] -#![deny(clippy::undocumented_unsafe_blocks)] use core::sync::atomic::{AtomicBool, AtomicPtr, AtomicU32, Ordering}; use pf_driver_proto::gamepad::XusbShm; diff --git a/packaging/windows/drivers/wdk-iddcx/Cargo.toml b/packaging/windows/drivers/wdk-iddcx/Cargo.toml index f22a9457..9bee212b 100644 --- a/packaging/windows/drivers/wdk-iddcx/Cargo.toml +++ b/packaging/windows/drivers/wdk-iddcx/Cargo.toml @@ -12,3 +12,6 @@ publish = false [dependencies] wdk-sys = { workspace = true, features = ["iddcx"] } + +[lints] +workspace = true diff --git a/packaging/windows/drivers/wdk-iddcx/src/lib.rs b/packaging/windows/drivers/wdk-iddcx/src/lib.rs index 45c8573f..428101af 100644 --- a/packaging/windows/drivers/wdk-iddcx/src/lib.rs +++ b/packaging/windows/drivers/wdk-iddcx/src/lib.rs @@ -12,8 +12,6 @@ #![allow(non_snake_case, clippy::missing_safety_doc)] // P0 lint (audit §8): require explicit `unsafe {}` blocks inside `unsafe fn`s + a `// SAFETY:` proof on // each (this crate is the IddCx DDI dispatch layer — inherently unsafe, so audited, not unsafe-free). -#![deny(unsafe_op_in_unsafe_fn)] -#![deny(clippy::undocumented_unsafe_blocks)] pub use wdk_sys::iddcx; diff --git a/packaging/windows/drivers/wdk-probe/Cargo.toml b/packaging/windows/drivers/wdk-probe/Cargo.toml index 9036ef27..d2b768e6 100644 --- a/packaging/windows/drivers/wdk-probe/Cargo.toml +++ b/packaging/windows/drivers/wdk-probe/Cargo.toml @@ -27,3 +27,6 @@ wdk.workspace = true # do its WDF/DXGI types resolve to wdk-sys's (so the generated module compiles)? wdk-sys = { workspace = true, features = ["iddcx"] } pf-driver-proto.workspace = true + +[lints] +workspace = true diff --git a/packaging/windows/drivers/wdk-probe/src/lib.rs b/packaging/windows/drivers/wdk-probe/src/lib.rs index 723c0d19..d3213ba8 100644 --- a/packaging/windows/drivers/wdk-probe/src/lib.rs +++ b/packaging/windows/drivers/wdk-probe/src/lib.rs @@ -5,8 +5,6 @@ //! shared `pf-driver-proto` ABI crate (no_std + bytemuck) across the workspace boundary. #![allow(non_snake_case)] -#![deny(unsafe_op_in_unsafe_fn)] -#![deny(clippy::undocumented_unsafe_blocks)] mod iddcx_rt; mod iddcx_surface_assert; diff --git a/tools/display-disturb/src/main.rs b/tools/display-disturb/src/main.rs index 83556808..6ed80cc6 100644 --- a/tools/display-disturb/src/main.rs +++ b/tools/display-disturb/src/main.rs @@ -20,7 +20,6 @@ //! `display-disturb modeset [--interval-ms 2000]` // Unsafe-proof program: every `unsafe {}` in this tool carries a `// SAFETY:` proof. -#![deny(clippy::undocumented_unsafe_blocks)] #[cfg(not(target_os = "windows"))] fn main() {