Crate printf_wrap

Source
Expand description

Types and functions for the safe use of printf(3)-style format strings.

printf(3) (POSIX, Linux, and FreeBSD man pages) and its variants present some challenges for memory-safe use from Rust: the passed-in arguments are interpreted as different types based on the content of the format string, with each conversion specification (e.g., %s) consuming up to three arguments (e.g, %*.*d), and the %n specification even writing to memory! For memory- and type-safe use, we must make sure a given format string is only used in invocations with the correct argument number and type.

This crate contains mechanisms you can use to ensure such agreement. PrintfFmt<(A, B, ...)> wraps a format string, doing verification to ensure it can be safely used with the list of arguments corresponding to the tuple of types (A: PrintfArgument, B: PrintfArgument, ...). This verification may be performed at compile time, allowing for safe wrappers with zero runtime overhead.

A brief example of how this crate might be used:

use printf_wrap::{PrintfFmt, PrintfArgument};
use libc::{c_int, printf};

/// Safe wrapper for calling printf with two value arguments.
pub fn printf_with_2_args<T, U>(fmt: PrintfFmt<(T, U)>, arg1: T, arg2: U) -> c_int
where
    T: PrintfArgument,
    U: PrintfArgument,
{
    unsafe { printf(fmt.as_ptr(), arg1.as_c_val(), arg2.as_c_val()) }
}

fn main() {
    const MY_FMT: PrintfFmt<(u32, i32)> =
        PrintfFmt::new_or_panic("unsigned = %u, signed = %d\0");
    printf_with_2_args(MY_FMT, 42, -7);
}

The example module has a more worked-out example of this crate’s use, using printf(3) and snprintf(3) as the functions to wrap.

Only a subset of all possible printf format strings are accepted:

  • Numbered argument conversion specifications (e.g., %2$d) are not supported.
  • %lc, %ls, %C, %S, and %L[fFeEgGaA] are not supported.
  • %n is not supported.
  • The j, z, and t length modifiers are only supported if crate feature libc is enabled.

Modules§

exampleexample
An example of how to use the types and traits of this crate to safely wrap functions with printf(3)-style format strings and varargs.

Macros§

null_str
Convenience macro for creating a const NullString, including appending a null character.

Structs§

NullString
A wrapper for a 'static null-terminated string.
PrintfFmt
A type-safe wrapper around a C-style string verified to be compatible with use as a format string for printf(3)-style functions called with T as the varargs.

Traits§

LargerOfOp
Utility trait for determining which of two integer types is larger.
PrintfArgs
A list of Rust-side arguments to a printf(3)-style function.
PrintfArgsList
A PrintfArgs in a form more amenable to recursive processing.
PrintfArgument
A Rust-side argument to a safe wrapper around a printf(3)-like function.

Functions§

is_fmt_valid
Returns whether fmt is (1) a valid C-style string and (2) a format string compatible with the tuple of arguments T when used in a printf(3)-like function.

Type Aliases§

LargerOf
Type alias that better conveys LargerOfOp’s nature as a type-level function.