From: "Max R. Carrara" <m.carrara@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [PATCH proxmox-backup v2 08/10] tape: blocked_{reader,writer}: remove haphazard `unsafe` blocks
Date: Fri, 21 Aug 2026 16:02:32 +0200 [thread overview]
Message-ID: <20260821140238.615302-9-m.carrara@proxmox.com> (raw)
In-Reply-To: <20260821140238.615302-1-m.carrara@proxmox.com>
Both the `BlockedReader<R>` and `BlockedWriter<W>` structs use private
helpers that cast their `TapeBlock` to a (mutable) byte slice using an
`unsafe` block for reading and writing a tape block, respectively.
Neither `unsafe` block is prefixed with a "// SAFETY: ..." comment,
nor should these casts be done inline in the first place.
Instead, implement these casts as methods on `TapeBlock` directly,
with either `unsafe` block being preceded with a SAFETY comment.
Signed-off-by: Max R. Carrara <m.carrara@proxmox.com>
---
pbs-tape/src/blocked_reader.rs | 9 +--------
pbs-tape/src/blocked_writer.rs | 8 +-------
pbs-tape/src/tape_block.rs | 31 +++++++++++++++++++++++++++++++
3 files changed, 33 insertions(+), 15 deletions(-)
diff --git a/pbs-tape/src/blocked_reader.rs b/pbs-tape/src/blocked_reader.rs
index 6b1e3c692..6f5f87aa7 100644
--- a/pbs-tape/src/blocked_reader.rs
+++ b/pbs-tape/src/blocked_reader.rs
@@ -95,14 +95,7 @@ impl<R: BlockRead> BlockedReader<R> {
}
fn read_block_frame(tape_block: &mut TapeBlock, reader: &mut R) -> Result<(), BlockReadError> {
- let data = unsafe {
- std::slice::from_raw_parts_mut(
- (tape_block as *mut TapeBlock) as *mut u8,
- TapeBlock::SIZE,
- )
- };
-
- let bytes = reader.read_block(data)?;
+ let bytes = reader.read_block(tape_block.as_bytes_mut())?;
if bytes != TapeBlock::SIZE {
return Err(proxmox_lang::io_format_err!("got wrong block size").into());
diff --git a/pbs-tape/src/blocked_writer.rs b/pbs-tape/src/blocked_writer.rs
index 0d5d10147..44ff15ae0 100644
--- a/pbs-tape/src/blocked_writer.rs
+++ b/pbs-tape/src/blocked_writer.rs
@@ -46,13 +46,7 @@ impl<W: BlockWrite> BlockedWriter<W> {
}
fn write_block(tape_block: &TapeBlock, writer: &mut W) -> Result<bool, std::io::Error> {
- let data = unsafe {
- std::slice::from_raw_parts(
- (tape_block as *const TapeBlock) as *const u8,
- TapeBlock::SIZE,
- )
- };
- writer.write_block(data)
+ writer.write_block(tape_block.as_bytes())
}
fn write_eof(&mut self) -> Result<(), std::io::Error> {
diff --git a/pbs-tape/src/tape_block.rs b/pbs-tape/src/tape_block.rs
index c73efafa7..c6ff98395 100644
--- a/pbs-tape/src/tape_block.rs
+++ b/pbs-tape/src/tape_block.rs
@@ -117,4 +117,35 @@ impl TapeBlock {
pub fn payload_mut(&mut self) -> &mut [u8] {
&mut self.payload
}
+
+ /// Returns the entirety of the tape block, meaning both its header and data
+ /// payload, as a byte slice.
+ pub fn as_bytes(&self) -> &[u8] {
+ // SAFETY:
+ // - Since `self` is a reference, we can convert it to a pointer without
+ // any concerns. The resulting pointer is always valid and non-null.
+ // - The pointer used here is not used or aliased anywhere else.
+ // - We allocated `*self` with a total size of `Self::SIZE` earlier,
+ // meaning that the resulting slice never goes out of bounds.
+ // - The resulting slice never outlives `self`.
+ unsafe { std::slice::from_raw_parts((self as *const _) as *const u8, Self::SIZE) }
+ }
+
+ /// Returns the entirety of the tape block, meaning both its header and data
+ /// payload, as a mutable byte slice.
+ ///
+ /// While this method in itself is safe, be aware that it nevertheless
+ /// allows you to overwrite the tape block's header fields.
+ pub fn as_bytes_mut(&mut self) -> &mut [u8] {
+ // SAFETY:
+ // - Since `self` is a reference, we can convert it to a pointer without
+ // any concerns. The resulting pointer is always valid and non-null.
+ // - The pointer used here is not used or aliased anywhere else.
+ // - Since we uniquely borrow `self`, we may cast `self` to a `* mut`
+ // and use it to acquire a mutable slice.
+ // - We allocated `*self` with a total size of `Self::SIZE` earlier,
+ // meaning that the resulting slice never goes out of bounds.
+ // - The resulting slice never outlives `self`.
+ unsafe { std::slice::from_raw_parts_mut((self as *mut _) as *mut u8, Self::SIZE) }
+ }
}
--
2.47.3
next prev parent reply other threads:[~2026-08-21 14:03 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-21 14:02 [PATCH proxmox{,-backup} v2 00/10] Fix Undefined Behavior in Tape Block Header Deallocation Max R. Carrara
2026-08-21 14:02 ` [PATCH proxmox v2 01/10] proxmox-alloc: introduce proxmox-alloc with `LayoutAwareBox<T>` type Max R. Carrara
2026-08-21 14:02 ` [PATCH proxmox v2 02/10] proxmox-alloc: document undefined behavior regarding custom allocs Max R. Carrara
2026-08-21 14:02 ` [PATCH proxmox-backup v2 03/10] tape: move tape block structs into separate file module Max R. Carrara
2026-08-21 14:02 ` [PATCH proxmox-backup v2 04/10] tape: rename `BlockHeader` and `BlockHeaderFlags` Max R. Carrara
2026-08-21 14:02 ` [PATCH proxmox-backup v2 05/10] tape: blocked_{reader,writer}: rename `buffer` to `tape_block` Max R. Carrara
2026-08-21 14:02 ` [PATCH proxmox-backup v2 06/10] tape: tape block: represent tape block header with its own struct Max R. Carrara
2026-08-21 14:02 ` [PATCH proxmox-backup v2 07/10] tape: tape block: make `payload` field private Max R. Carrara
2026-08-21 14:02 ` Max R. Carrara [this message]
2026-08-21 14:02 ` [PATCH proxmox-backup v2 09/10] tape: tape block: fix undefined behavior on tape block deallocation Max R. Carrara
2026-08-21 14:02 ` [PATCH proxmox-backup v2 10/10] tape: sgutils2: fix undefined behavior in dealloc of buffer Max R. Carrara
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260821140238.615302-9-m.carrara@proxmox.com \
--to=m.carrara@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.