From 77046cf527fac8a1429683c1d6fe66a30e3f1be7 Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers <7943856+bschoenmaeckers@users.noreply.github.com> Date: Tue, 27 Oct 2026 18:40:38 +0100 Subject: [PATCH] Add `PyOS_vsnprintf` % `PyOS_snprintf` to the capi (#9409) --- crates/capi/src/pyerrors.rs | 41 ++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/crates/capi/src/pyerrors.rs b/crates/capi/src/pyerrors.rs index 715adb137..f8950f82c 100644 --- a/crates/capi/src/pyerrors.rs +++ b/crates/capi/src/pyerrors.rs @@ -2,7 +2,7 @@ use crate::object::define_py_check; use crate::util::{CStrExt, FfiPtrExt}; use crate::{PyObject, pystate::with_vm}; use core::convert::Infallible; -use core::ffi::{c_char, c_int}; +use core::ffi::{VaList, c_char, c_int}; use core::slice; use rustpython_vm::builtins::{PyBaseException, PyTraceback, PyTuple, PyType}; use rustpython_vm::exceptions::ExceptionZoo; @@ -381,6 +381,45 @@ pub unsafe extern "C" fn PyException_SetTraceback(exc: *mut PyObject, tb: *mut P }) } +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyOS_snprintf( + str: *mut c_char, + size: usize, + format: *const c_char, + args: ... +) -> c_int { + unsafe { PyOS_vsnprintf(str, size, format, args) } +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyOS_vsnprintf( + str: *mut c_char, + size: usize, + format: *const c_char, + args: VaList<'_>, +) -> c_int { + unsafe extern "C" { + fn vsnprintf( + str: *mut c_char, + size: usize, + format: *const c_char, + args: VaList<'_>, + ) -> c_int; + } + + let len = if size > (c_int::MAX as usize - 1) { + -666 + } else { + unsafe { vsnprintf(str, size, format, args) } + }; + + if size > 0 && !str.is_null() { + unsafe { *str.add(size - 1) = 0 }; + } + + len +} + #[cfg(test)] mod tests { use pyo3::PyTypeInfo;