Assessment reports>Pinocchio and p-token>High findings>Log trait missing ,unsafe
Category: Coding Mistakes

Log trait missing unsafe

High Impact
High Severity
Medium Likelihood

Description

The Log trait in the log crate is used to mark a type as loggable. It requires the implementer to provide the implementation of (at least) write_with_args, which takes a buffer of MaybeUninit<u8> and parameters relevant for logging. It then returns the amount of bytes that it had written to.

/// Trait to specify the log behavior for a type.
pub trait Log {
    #[inline(always)]
    fn debug(&self, buffer: &mut [MaybeUninit<u8>]) -> usize {
        self.debug_with_args(buffer, &[])
    }

    #[inline(always)]
    fn debug_with_args(&self, buffer: &mut [MaybeUninit<u8>], args: &[Argument]) -> usize {
        self.write_with_args(buffer, args)
    }

    #[inline(always)]
    fn write(&self, buffer: &mut [MaybeUninit<u8>]) -> usize {
        self.write_with_args(buffer, &[])
    }

!    fn write_with_args(&self, buffer: &mut [MaybeUninit<u8>], parameters: &[Argument]) -> usize;
}

This buffer, passed from the Logger struct, is ultimately then read from to log the message.

The implementation of write_with_args has memory safety implications. If a usize is returned that does not accurately reflect the number of bytes consecutively written to the buffer, this can result in undefined behavior by reading from an uninitialized MaybeUninit<u8>. In Rust, if the implementation of a trait can result in undefined behavior, it must be marked with unsafe to communicate in the type signature that the implication of this trait has memory safety implications.

Impact

Undefined behavior can result from an incorrect implementation of Log, despite the trait not being an unsafe trait. This could result in reading uninitialized memory in otherwise safe Rust.

Recommendations

Either mark Log as unsafe, or change the signature to use &[u8].

Remediation

Zellic © 2025Back to top ↑