Re: [PATCH v2 20/28] rust: str: add `Formatter` type

From: Dr. David Alan Gilbert
Date: Sun Dec 04 2022 - 10:41:39 EST


* ojeda@xxxxxxxxxx (ojeda@xxxxxxxxxx) wrote:
> From: Wedson Almeida Filho <wedsonaf@xxxxxxxxx>
>
> Add the `Formatter` type, which leverages `RawFormatter`,
> but fails if callers attempt to write more than will fit
> in the buffer.
>
> In order to so, implement the `RawFormatter::from_buffer()`
> constructor as well.
>
> Co-developed-by: Adam Bratschi-Kaye <ark.email@xxxxxxxxx>
> Signed-off-by: Adam Bratschi-Kaye <ark.email@xxxxxxxxx>
> Signed-off-by: Wedson Almeida Filho <wedsonaf@xxxxxxxxx>
> Reviewed-by: Gary Guo <gary@xxxxxxxxxxx>
> [Reworded, adapted for upstream and applied latest changes]
> Signed-off-by: Miguel Ojeda <ojeda@xxxxxxxxxx>
> ---
> rust/kernel/str.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 57 insertions(+)
>
> diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
> index a995db36486f..ce207d1b3d2a 100644
> --- a/rust/kernel/str.rs
> +++ b/rust/kernel/str.rs
> @@ -406,6 +406,23 @@ impl RawFormatter {
> }
> }
>
> + /// Creates a new instance of [`RawFormatter`] with the given buffer.
> + ///
> + /// # Safety
> + ///
> + /// The memory region starting at `buf` and extending for `len` bytes must be valid for writes
> + /// for the lifetime of the returned [`RawFormatter`].
> + pub(crate) unsafe fn from_buffer(buf: *mut u8, len: usize) -> Self {
> + let pos = buf as usize;
> + // INVARIANT: We ensure that `end` is never less then `buf`, and the safety requirements
> + // guarantees that the memory region is valid for writes.
> + Self {
> + pos,
> + beg: pos,
> + end: pos.saturating_add(len),
> + }
> + }
> +
> /// Returns the current insert position.
> ///
> /// N.B. It may point to invalid memory.
> @@ -439,3 +456,43 @@ impl fmt::Write for RawFormatter {
> Ok(())
> }
> }
> +
> +/// Allows formatting of [`fmt::Arguments`] into a raw buffer.
> +///
> +/// Fails if callers attempt to write more than will fit in the buffer.
> +pub(crate) struct Formatter(RawFormatter);
> +
> +impl Formatter {
> + /// Creates a new instance of [`Formatter`] with the given buffer.
> + ///
> + /// # Safety
> + ///
> + /// The memory region starting at `buf` and extending for `len` bytes must be valid for writes
> + /// for the lifetime of the returned [`Formatter`].
> + #[allow(dead_code)]
> + pub(crate) unsafe fn from_buffer(buf: *mut u8, len: usize) -> Self {
> + // SAFETY: The safety requirements of this function satisfy those of the callee.
> + Self(unsafe { RawFormatter::from_buffer(buf, len) })
> + }
> +}
> +
> +impl Deref for Formatter {
> + type Target = RawFormatter;
> +
> + fn deref(&self) -> &Self::Target {
> + &self.0
> + }
> +}
> +
> +impl fmt::Write for Formatter {
> + fn write_str(&mut self, s: &str) -> fmt::Result {
> + self.0.write_str(s)?;
> +
> + // Fail the request if we go past the end of the buffer.

Reading this for the first time, I'm surprised by this, perhaps a
bit more comment is needed? I was expecting that nothing would
let pos pass end.

Dave

> + if self.0.pos > self.0.end {
> + Err(fmt::Error)
> + } else {
> + Ok(())
> + }
> + }
> +}
> --
> 2.38.1
>
--
-----Open up your eyes, open up your mind, open up your code -------
/ Dr. David Alan Gilbert | Running GNU/Linux | Happy \
\ dave @ treblig.org | | In Hex /
\ _________________________|_____ http://www.treblig.org |_______/