From 937fe847d70c24dd4c4444281be80cb1b5b8321e Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 20 Jul 2026 13:50:40 +0100 Subject: [PATCH 1/7] Add translation-time snprintf generation --- .../converter/models/converter_refcount.cpp | 38 +++++++++++++++++++ .../converter/models/converter_refcount.h | 2 + 2 files changed, 40 insertions(+) diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index 9bee3eb9..ffd6d5c4 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -1048,12 +1048,50 @@ void ConverterRefCount::ConvertPrintf(clang::CallExpr *expr) { StrCat(')'); } +void ConverterRefCount::ConvertSnprintf(clang::CallExpr *expr) { + std::string format; + if (auto *str = clang::dyn_cast( + expr->getArg(2)->IgnoreImplicit())) { + format = GetEscapedStringLiteral(str); + } else { + llvm::errs() << "Unknown snprintf format: "; + expr->getArg(2)->dump(); + llvm::errs() << '\n'; + exit(1); + } + auto types = printf2fmt(format); + + StrCat("({ let __s = format!(", format); + unsigned j = 0; + for (unsigned i = 3, e = expr->getNumArgs(); i < e; ++i) { + StrCat(token::kComma); + Convert(expr->getArg(i)); + if (types[j]) { + StrCat(keyword::kAs, types[j]); + } + ++j; + } + StrCat("); let __b = __s.as_bytes(); let __size = ("); + Convert(expr->getArg(1)); + StrCat(") as usize; if __size > 0 {", + "let __n = ::std::cmp::min(__b.len(), __size - 1); ("); + Convert(expr->getArg(0)); + StrCat(").with_slice_mut(__n + 1, |__dst| {", + "__dst[..__n].copy_from_slice(&__b[..__n]); __dst[__n] = 0; }); }", + "__b.len() as i32 })"); +} + bool ConverterRefCount::VisitCallExpr(clang::CallExpr *expr) { if (IsBuiltinVaStart(expr) || IsBuiltinVaEnd(expr) || IsBuiltinVaCopy(expr)) { ConvertVAArgCall(expr); return false; } + if (Mapper::ToString(expr->getCallee()).starts_with("int snprintf")) { + ConvertSnprintf(expr); + return false; + } + if (expr->isCallToStdMove()) { if (IsUniquePtr(expr->getArg(0)->getType())) { StrCat(std::format("{}.take()", ConvertLValue(expr->getArg(0)))); diff --git a/cpp2rust/converter/models/converter_refcount.h b/cpp2rust/converter/models/converter_refcount.h index 1108ab71..b98b40ed 100644 --- a/cpp2rust/converter/models/converter_refcount.h +++ b/cpp2rust/converter/models/converter_refcount.h @@ -82,6 +82,8 @@ class ConverterRefCount final : public Converter { void ConvertPrintf(clang::CallExpr *expr) override; + void ConvertSnprintf(clang::CallExpr *expr); + void EmitFnPtrCall(clang::Expr *callee) override; void From 4e5b9bd375c0a5085a12586e3e2d83d14bc46444 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 20 Jul 2026 13:50:49 +0100 Subject: [PATCH 2/7] Delete snprintf rule --- rules/stdio/tgt_refcount.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/rules/stdio/tgt_refcount.rs b/rules/stdio/tgt_refcount.rs index 0dba24cb..d069916c 100644 --- a/rules/stdio/tgt_refcount.rs +++ b/rules/stdio/tgt_refcount.rs @@ -213,16 +213,6 @@ fn f19(a0: Ptr<::std::fs::File>, a1: i64, a2: i32) -> i32 { } } -fn f21(a0: Ptr, a1: usize, a2: Ptr, va: &[VaArg]) -> i32 { - panic!( - "snprintf is not supported in the refcount model (buf_is_null={}, size={}, fmt={:?}, varargs={})", - a0.is_null(), - a1, - a2.to_rust_string(), - va.len() - ) -} - fn f22(a0: Ptr, a1: Ptr) -> i32 { match ::std::fs::rename(a0.to_rust_string(), a1.to_rust_string()) { Ok(()) => 0, From ce44aeaa1542e49940ef3ea46e9d00a2a32984e0 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 20 Jul 2026 13:51:58 +0100 Subject: [PATCH 3/7] Add snprintf test --- tests/unit/out/refcount/snprintf.rs | 200 ++++++++++++++++++++++++++++ tests/unit/out/unsafe/snprintf.rs | 124 +++++++++++++++++ tests/unit/snprintf.c | 21 +++ 3 files changed, 345 insertions(+) create mode 100644 tests/unit/out/refcount/snprintf.rs create mode 100644 tests/unit/out/unsafe/snprintf.rs create mode 100644 tests/unit/snprintf.c diff --git a/tests/unit/out/refcount/snprintf.rs b/tests/unit/out/refcount/snprintf.rs new file mode 100644 index 00000000..f2ac5cfc --- /dev/null +++ b/tests/unit/out/refcount/snprintf.rs @@ -0,0 +1,200 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let buf: Value> = Rc::new(RefCell::new( + (0..32).map(|_| ::default()).collect::>(), + )); + assert!( + (((({ + let __s = format!("x={} y={}", -3_i32, 7_u32); + let __b = __s.as_bytes(); + let __size = (::std::mem::size_of::<[u8; 32]>()) as usize; + if __size > 0 { + let __n = ::std::cmp::min(__b.len(), __size - 1); + (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { + __dst[..__n].copy_from_slice(&__b[..__n]); + __dst[__n] = 0; + }); + } + __b.len() as i32 + }) == 8) as i32) + != 0) + ); + assert!( + ((({ + let mut __it1 = (buf.as_pointer() as Ptr).to_c_string_iterator(); + let mut __it2 = Ptr::from_string_literal(b"x=-3 y=7").to_c_string_iterator(); + loop { + let __c1 = __it1.next(); + let __c2 = __it2.next(); + if __c1 != __c2 { + break (__c1.unwrap_or(0) as i32) - (__c2.unwrap_or(0) as i32); + } + if __c1.is_none() { + break 0; + } + } + } == 0) as i32) + != 0) + ); + assert!( + (((({ + let __s = format!("{}", Ptr::from_string_literal(b"hello")); + let __b = __s.as_bytes(); + let __size = (4_usize) as usize; + if __size > 0 { + let __n = ::std::cmp::min(__b.len(), __size - 1); + (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { + __dst[..__n].copy_from_slice(&__b[..__n]); + __dst[__n] = 0; + }); + } + __b.len() as i32 + }) == 5) as i32) + != 0) + ); + assert!( + ((({ + let mut __it1 = (buf.as_pointer() as Ptr).to_c_string_iterator(); + let mut __it2 = Ptr::from_string_literal(b"hel").to_c_string_iterator(); + loop { + let __c1 = __it1.next(); + let __c2 = __it2.next(); + if __c1 != __c2 { + break (__c1.unwrap_or(0) as i32) - (__c2.unwrap_or(0) as i32); + } + if __c1.is_none() { + break 0; + } + } + } == 0) as i32) + != 0) + ); + assert!( + (((({ + let __s = format!("{:05}|{:02x}", 42, 255); + let __b = __s.as_bytes(); + let __size = (::std::mem::size_of::<[u8; 32]>()) as usize; + if __size > 0 { + let __n = ::std::cmp::min(__b.len(), __size - 1); + (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { + __dst[..__n].copy_from_slice(&__b[..__n]); + __dst[__n] = 0; + }); + } + __b.len() as i32 + }) == 8) as i32) + != 0) + ); + assert!( + ((({ + let mut __it1 = (buf.as_pointer() as Ptr).to_c_string_iterator(); + let mut __it2 = Ptr::from_string_literal(b"00042|ff").to_c_string_iterator(); + loop { + let __c1 = __it1.next(); + let __c2 = __it2.next(); + if __c1 != __c2 { + break (__c1.unwrap_or(0) as i32) - (__c2.unwrap_or(0) as i32); + } + if __c1.is_none() { + break 0; + } + } + } == 0) as i32) + != 0) + ); + assert!( + (((({ + let __s = format!("{}%", 65 as u8 as char); + let __b = __s.as_bytes(); + let __size = (::std::mem::size_of::<[u8; 32]>()) as usize; + if __size > 0 { + let __n = ::std::cmp::min(__b.len(), __size - 1); + (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { + __dst[..__n].copy_from_slice(&__b[..__n]); + __dst[__n] = 0; + }); + } + __b.len() as i32 + }) == 2) as i32) + != 0) + ); + assert!( + ((({ + let mut __it1 = (buf.as_pointer() as Ptr).to_c_string_iterator(); + let mut __it2 = Ptr::from_string_literal(b"A%").to_c_string_iterator(); + loop { + let __c1 = __it1.next(); + let __c2 = __it2.next(); + if __c1 != __c2 { + break (__c1.unwrap_or(0) as i32) - (__c2.unwrap_or(0) as i32); + } + if __c1.is_none() { + break 0; + } + } + } == 0) as i32) + != 0) + ); + assert!( + (((({ + let __s = format!("{} {} {}", -1_i64, 1_u64, (9 as usize)); + let __b = __s.as_bytes(); + let __size = (::std::mem::size_of::<[u8; 32]>()) as usize; + if __size > 0 { + let __n = ::std::cmp::min(__b.len(), __size - 1); + (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { + __dst[..__n].copy_from_slice(&__b[..__n]); + __dst[__n] = 0; + }); + } + __b.len() as i32 + }) == 6) as i32) + != 0) + ); + assert!( + ((({ + let mut __it1 = (buf.as_pointer() as Ptr).to_c_string_iterator(); + let mut __it2 = Ptr::from_string_literal(b"-1 1 9").to_c_string_iterator(); + loop { + let __c1 = __it1.next(); + let __c2 = __it2.next(); + if __c1 != __c2 { + break (__c1.unwrap_or(0) as i32) - (__c2.unwrap_or(0) as i32); + } + if __c1.is_none() { + break 0; + } + } + } == 0) as i32) + != 0) + ); + (*buf.borrow_mut())[(0) as usize] = (('Z' as i32) as u8); + assert!( + (((({ + let __s = format!("{}", 123); + let __b = __s.as_bytes(); + let __size = (0_usize) as usize; + if __size > 0 { + let __n = ::std::cmp::min(__b.len(), __size - 1); + (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { + __dst[..__n].copy_from_slice(&__b[..__n]); + __dst[__n] = 0; + }); + } + __b.len() as i32 + }) == 3) as i32) + != 0) + ); + assert!((((((*buf.borrow())[(0) as usize] as i32) == ('Z' as i32)) as i32) != 0)); + return 0; +} diff --git a/tests/unit/out/unsafe/snprintf.rs b/tests/unit/out/unsafe/snprintf.rs new file mode 100644 index 00000000..a492dace --- /dev/null +++ b/tests/unit/out/unsafe/snprintf.rs @@ -0,0 +1,124 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut buf: [libc::c_char; 32] = [(0 as libc::c_char); 32]; + assert!( + ((((unsafe { + libc::snprintf( + buf.as_mut_ptr() as *mut libc::c_char, + ::std::mem::size_of::<[libc::c_char; 32]>() as usize, + (c"x=%d y=%u".as_ptr().cast_mut()).cast_const() as *const libc::c_char, + (-3_i32), + (7_u32), + ) + }) == (8)) as i32) + != 0) + ); + assert!( + ((((libc::strcmp( + (buf.as_mut_ptr()).cast_const(), + (c"x=-3 y=7".as_ptr().cast_mut()).cast_const() + )) == (0)) as i32) + != 0) + ); + assert!( + ((((unsafe { + libc::snprintf( + buf.as_mut_ptr() as *mut libc::c_char, + 4_usize as usize, + (c"%s".as_ptr().cast_mut()).cast_const() as *const libc::c_char, + (c"hello".as_ptr().cast_mut()), + ) + }) == (5)) as i32) + != 0) + ); + assert!( + ((((libc::strcmp( + (buf.as_mut_ptr()).cast_const(), + (c"hel".as_ptr().cast_mut()).cast_const() + )) == (0)) as i32) + != 0) + ); + assert!( + ((((unsafe { + libc::snprintf( + buf.as_mut_ptr() as *mut libc::c_char, + ::std::mem::size_of::<[libc::c_char; 32]>() as usize, + (c"%05d|%02x".as_ptr().cast_mut()).cast_const() as *const libc::c_char, + (42), + (255), + ) + }) == (8)) as i32) + != 0) + ); + assert!( + ((((libc::strcmp( + (buf.as_mut_ptr()).cast_const(), + (c"00042|ff".as_ptr().cast_mut()).cast_const() + )) == (0)) as i32) + != 0) + ); + assert!( + ((((unsafe { + libc::snprintf( + buf.as_mut_ptr() as *mut libc::c_char, + ::std::mem::size_of::<[libc::c_char; 32]>() as usize, + (c"%c%%".as_ptr().cast_mut()).cast_const() as *const libc::c_char, + (65), + ) + }) == (2)) as i32) + != 0) + ); + assert!( + ((((libc::strcmp( + (buf.as_mut_ptr()).cast_const(), + (c"A%".as_ptr().cast_mut()).cast_const() + )) == (0)) as i32) + != 0) + ); + assert!( + ((((unsafe { + libc::snprintf( + buf.as_mut_ptr() as *mut libc::c_char, + ::std::mem::size_of::<[libc::c_char; 32]>() as usize, + (c"%ld %lu %zu".as_ptr().cast_mut()).cast_const() as *const libc::c_char, + (-1_i64), + (1_u64), + (9 as usize), + ) + }) == (6)) as i32) + != 0) + ); + assert!( + ((((libc::strcmp( + (buf.as_mut_ptr()).cast_const(), + (c"-1 1 9".as_ptr().cast_mut()).cast_const() + )) == (0)) as i32) + != 0) + ); + buf[(0) as usize] = (('Z' as i32) as libc::c_char); + assert!( + ((((unsafe { + libc::snprintf( + buf.as_mut_ptr() as *mut libc::c_char, + 0_usize as usize, + (c"%d".as_ptr().cast_mut()).cast_const() as *const libc::c_char, + (123), + ) + }) == (3)) as i32) + != 0) + ); + assert!(((((buf[(0) as usize] as i32) == ('Z' as i32)) as i32) != 0)); + return 0; +} diff --git a/tests/unit/snprintf.c b/tests/unit/snprintf.c new file mode 100644 index 00000000..c7571b55 --- /dev/null +++ b/tests/unit/snprintf.c @@ -0,0 +1,21 @@ +#include +#include +#include + +int main() { + char buf[32]; + assert(snprintf(buf, sizeof(buf), "x=%d y=%u", -3, 7u) == 8); + assert(strcmp(buf, "x=-3 y=7") == 0); + assert(snprintf(buf, 4, "%s", "hello") == 5); + assert(strcmp(buf, "hel") == 0); + assert(snprintf(buf, sizeof(buf), "%05d|%02x", 42, 255) == 8); + assert(strcmp(buf, "00042|ff") == 0); + assert(snprintf(buf, sizeof(buf), "%c%%", 65) == 2); + assert(strcmp(buf, "A%") == 0); + assert(snprintf(buf, sizeof(buf), "%ld %lu %zu", -1L, 1UL, (size_t)9) == 6); + assert(strcmp(buf, "-1 1 9") == 0); + buf[0] = 'Z'; + assert(snprintf(buf, 0, "%d", 123) == 3); + assert(buf[0] == 'Z'); + return 0; +} From 302530bbd65a5861c451cc0bd99effc8f3875419 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 20 Jul 2026 15:07:03 +0100 Subject: [PATCH 4/7] Revert "Add translation-time snprintf generation" This reverts commit 937fe847d70c24dd4c4444281be80cb1b5b8321e. --- .../converter/models/converter_refcount.cpp | 38 ------------------- .../converter/models/converter_refcount.h | 2 - 2 files changed, 40 deletions(-) diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index ffd6d5c4..9bee3eb9 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -1048,50 +1048,12 @@ void ConverterRefCount::ConvertPrintf(clang::CallExpr *expr) { StrCat(')'); } -void ConverterRefCount::ConvertSnprintf(clang::CallExpr *expr) { - std::string format; - if (auto *str = clang::dyn_cast( - expr->getArg(2)->IgnoreImplicit())) { - format = GetEscapedStringLiteral(str); - } else { - llvm::errs() << "Unknown snprintf format: "; - expr->getArg(2)->dump(); - llvm::errs() << '\n'; - exit(1); - } - auto types = printf2fmt(format); - - StrCat("({ let __s = format!(", format); - unsigned j = 0; - for (unsigned i = 3, e = expr->getNumArgs(); i < e; ++i) { - StrCat(token::kComma); - Convert(expr->getArg(i)); - if (types[j]) { - StrCat(keyword::kAs, types[j]); - } - ++j; - } - StrCat("); let __b = __s.as_bytes(); let __size = ("); - Convert(expr->getArg(1)); - StrCat(") as usize; if __size > 0 {", - "let __n = ::std::cmp::min(__b.len(), __size - 1); ("); - Convert(expr->getArg(0)); - StrCat(").with_slice_mut(__n + 1, |__dst| {", - "__dst[..__n].copy_from_slice(&__b[..__n]); __dst[__n] = 0; }); }", - "__b.len() as i32 })"); -} - bool ConverterRefCount::VisitCallExpr(clang::CallExpr *expr) { if (IsBuiltinVaStart(expr) || IsBuiltinVaEnd(expr) || IsBuiltinVaCopy(expr)) { ConvertVAArgCall(expr); return false; } - if (Mapper::ToString(expr->getCallee()).starts_with("int snprintf")) { - ConvertSnprintf(expr); - return false; - } - if (expr->isCallToStdMove()) { if (IsUniquePtr(expr->getArg(0)->getType())) { StrCat(std::format("{}.take()", ConvertLValue(expr->getArg(0)))); diff --git a/cpp2rust/converter/models/converter_refcount.h b/cpp2rust/converter/models/converter_refcount.h index b98b40ed..1108ab71 100644 --- a/cpp2rust/converter/models/converter_refcount.h +++ b/cpp2rust/converter/models/converter_refcount.h @@ -82,8 +82,6 @@ class ConverterRefCount final : public Converter { void ConvertPrintf(clang::CallExpr *expr) override; - void ConvertSnprintf(clang::CallExpr *expr); - void EmitFnPtrCall(clang::Expr *callee) override; void From 1855ff482851809433334e2ce34422588274524d Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 20 Jul 2026 15:08:11 +0100 Subject: [PATCH 5/7] Add libcc2rs::format_c --- libcc2rs/Cargo.toml | 1 + libcc2rs/src/format.rs | 64 +++++++++++++++++++++++++++++++++++++ libcc2rs/src/lib.rs | 3 ++ rules/stdio/tgt_refcount.rs | 13 ++++++++ 4 files changed, 81 insertions(+) create mode 100644 libcc2rs/src/format.rs diff --git a/libcc2rs/Cargo.toml b/libcc2rs/Cargo.toml index 6370ac02..a1761abf 100644 --- a/libcc2rs/Cargo.toml +++ b/libcc2rs/Cargo.toml @@ -8,3 +8,4 @@ libcc2rs-macros = { path = "../libcc2rs-macros", version = "0.1.0" } libc = "0.2" nix = { version = "0.30", features = ["socket", "net", "fs", "poll", "time", "user", "dir", "term", "event", "hostname"] } jiff = "0.2" +sprintf = "0.4" diff --git a/libcc2rs/src/format.rs b/libcc2rs/src/format.rs new file mode 100644 index 00000000..d33eb062 --- /dev/null +++ b/libcc2rs/src/format.rs @@ -0,0 +1,64 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +use sprintf::parser::{ConversionType, FormatElement, parse_format_string}; +use sprintf::{Printf, vsprintfp}; + +use crate::va_args::{VaArg, VaArgGet}; + +pub fn format_c(fmt: &str, va: &[VaArg]) -> String { + let elements = match parse_format_string(fmt) { + Ok(elements) => elements, + Err(e) => panic!("format_c: cannot parse {fmt:?}: {e:?}"), + }; + let mut args: Vec> = Vec::new(); + let mut pos = 0; + for element in &elements { + if let FormatElement::Format(spec) = element { + if spec.conversion_type == ConversionType::PercentSign { + continue; + } + let arg = &va[pos]; + args.push(match spec.conversion_type { + ConversionType::DecInt => match arg { + VaArg::Int(v) => Box::new(*v), + VaArg::UInt(v) => Box::new(*v), + VaArg::Long(v) => Box::new(*v), + VaArg::ULong(v) => Box::new(*v), + _ => panic!("format_c: integer conversion expects an integer argument"), + }, + ConversionType::OctInt + | ConversionType::HexIntLower + | ConversionType::HexIntUpper => match arg { + VaArg::Int(v) => Box::new(*v as u32), + VaArg::UInt(v) => Box::new(*v), + VaArg::Long(v) => Box::new(*v as u64), + VaArg::ULong(v) => Box::new(*v), + VaArg::Ptr(p) => Box::new(p.to_int()), + VaArg::RawPtr(v) => Box::new(*v as usize), + VaArg::Double(_) => { + panic!("format_c: integer conversion expects an integer argument") + } + }, + ConversionType::Char => Box::new(i32::get(arg) as u8 as char), + ConversionType::String => match arg { + VaArg::Ptr(v) => Box::new(v.reinterpret_cast::().to_rust_string()), + _ => panic!("format_c: %s expects a string argument"), + }, + ConversionType::DecFloatLower + | ConversionType::DecFloatUpper + | ConversionType::SciFloatLower + | ConversionType::SciFloatUpper + | ConversionType::CompactFloatLower + | ConversionType::CompactFloatUpper => Box::new(f64::get(arg)), + ConversionType::PercentSign => panic!("format_c: %% consumes no argument"), + }); + pos += 1; + } + } + let refs: Vec<&dyn Printf> = args.iter().map(|arg| arg.as_ref()).collect(); + match vsprintfp(&elements, &refs) { + Ok(s) => s, + Err(e) => panic!("format_c: cannot format {fmt:?}: {e:?}"), + } +} diff --git a/libcc2rs/src/lib.rs b/libcc2rs/src/lib.rs index e9046a7f..f2e5b6fd 100644 --- a/libcc2rs/src/lib.rs +++ b/libcc2rs/src/lib.rs @@ -37,4 +37,7 @@ pub use compat::*; mod va_args; pub use va_args::*; +mod format; +pub use format::*; + pub use libcc2rs_macros::{goto, goto_block, switch}; diff --git a/rules/stdio/tgt_refcount.rs b/rules/stdio/tgt_refcount.rs index d069916c..94a1a879 100644 --- a/rules/stdio/tgt_refcount.rs +++ b/rules/stdio/tgt_refcount.rs @@ -213,6 +213,19 @@ fn f19(a0: Ptr<::std::fs::File>, a1: i64, a2: i32) -> i32 { } } +fn f21(a0: Ptr, a1: usize, a2: Ptr, va: &[VaArg]) -> i32 { + let __s = libcc2rs::format_c(&a2.to_rust_string(), va); + let __b = __s.as_bytes(); + if a1 > 0 { + let __n = ::std::cmp::min(__b.len(), a1 - 1); + a0.with_slice_mut(__n + 1, |__dst| { + __dst[..__n].copy_from_slice(&__b[..__n]); + __dst[__n] = 0; + }); + } + __b.len() as i32 +} + fn f22(a0: Ptr, a1: Ptr) -> i32 { match ::std::fs::rename(a0.to_rust_string(), a1.to_rust_string()) { Ok(()) => 0, From 48556107c2184a9f3a3f26493fa4db97fa4fbd2b Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 20 Jul 2026 15:08:35 +0100 Subject: [PATCH 6/7] Update tests --- tests/unit/out/refcount/snprintf.rs | 375 +++++++++++++++++++++++++--- tests/unit/out/unsafe/snprintf.rs | 160 +++++++++++- tests/unit/snprintf.c | 23 +- 3 files changed, 516 insertions(+), 42 deletions(-) diff --git a/tests/unit/out/refcount/snprintf.rs b/tests/unit/out/refcount/snprintf.rs index f2ac5cfc..30163277 100644 --- a/tests/unit/out/refcount/snprintf.rs +++ b/tests/unit/out/refcount/snprintf.rs @@ -14,19 +14,21 @@ fn main_0() -> i32 { (0..32).map(|_| ::default()).collect::>(), )); assert!( - (((({ - let __s = format!("x={} y={}", -3_i32, 7_u32); + ((({ + let __s = libcc2rs::format_c( + &Ptr::from_string_literal(b"x=%d y=%u").to_rust_string(), + &[(-3_i32).into(), (7_u32).into()], + ); let __b = __s.as_bytes(); - let __size = (::std::mem::size_of::<[u8; 32]>()) as usize; - if __size > 0 { - let __n = ::std::cmp::min(__b.len(), __size - 1); + if ::std::mem::size_of::<[u8; 32]>() > 0 { + let __n = ::std::cmp::min(__b.len(), ::std::mem::size_of::<[u8; 32]>() - 1); (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { __dst[..__n].copy_from_slice(&__b[..__n]); __dst[__n] = 0; }); } __b.len() as i32 - }) == 8) as i32) + } == 8) as i32) != 0) ); assert!( @@ -47,19 +49,21 @@ fn main_0() -> i32 { != 0) ); assert!( - (((({ - let __s = format!("{}", Ptr::from_string_literal(b"hello")); + ((({ + let __s = libcc2rs::format_c( + &Ptr::from_string_literal(b"%s").to_rust_string(), + &[(Ptr::from_string_literal(b"hello")).into()], + ); let __b = __s.as_bytes(); - let __size = (4_usize) as usize; - if __size > 0 { - let __n = ::std::cmp::min(__b.len(), __size - 1); + if 4_usize > 0 { + let __n = ::std::cmp::min(__b.len(), 4_usize - 1); (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { __dst[..__n].copy_from_slice(&__b[..__n]); __dst[__n] = 0; }); } __b.len() as i32 - }) == 5) as i32) + } == 5) as i32) != 0) ); assert!( @@ -80,25 +84,132 @@ fn main_0() -> i32 { != 0) ); assert!( - (((({ - let __s = format!("{:05}|{:02x}", 42, 255); + ((({ + let __s = libcc2rs::format_c( + &Ptr::from_string_literal(b"%05d|%x|%X").to_rust_string(), + &[(42).into(), (255).into(), (255).into()], + ); + let __b = __s.as_bytes(); + if ::std::mem::size_of::<[u8; 32]>() > 0 { + let __n = ::std::cmp::min(__b.len(), ::std::mem::size_of::<[u8; 32]>() - 1); + (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { + __dst[..__n].copy_from_slice(&__b[..__n]); + __dst[__n] = 0; + }); + } + __b.len() as i32 + } == 11) as i32) + != 0) + ); + assert!( + ((({ + let mut __it1 = (buf.as_pointer() as Ptr).to_c_string_iterator(); + let mut __it2 = Ptr::from_string_literal(b"00042|ff|FF").to_c_string_iterator(); + loop { + let __c1 = __it1.next(); + let __c2 = __it2.next(); + if __c1 != __c2 { + break (__c1.unwrap_or(0) as i32) - (__c2.unwrap_or(0) as i32); + } + if __c1.is_none() { + break 0; + } + } + } == 0) as i32) + != 0) + ); + assert!( + ((({ + let __s = libcc2rs::format_c( + &Ptr::from_string_literal(b"%.2f").to_rust_string(), + &[(3.14159E+0).into()], + ); + let __b = __s.as_bytes(); + if ::std::mem::size_of::<[u8; 32]>() > 0 { + let __n = ::std::cmp::min(__b.len(), ::std::mem::size_of::<[u8; 32]>() - 1); + (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { + __dst[..__n].copy_from_slice(&__b[..__n]); + __dst[__n] = 0; + }); + } + __b.len() as i32 + } == 4) as i32) + != 0) + ); + assert!( + ((({ + let mut __it1 = (buf.as_pointer() as Ptr).to_c_string_iterator(); + let mut __it2 = Ptr::from_string_literal(b"3.14").to_c_string_iterator(); + loop { + let __c1 = __it1.next(); + let __c2 = __it2.next(); + if __c1 != __c2 { + break (__c1.unwrap_or(0) as i32) - (__c2.unwrap_or(0) as i32); + } + if __c1.is_none() { + break 0; + } + } + } == 0) as i32) + != 0) + ); + assert!( + ((({ + let __s = libcc2rs::format_c( + &Ptr::from_string_literal(b"%-6s|").to_rust_string(), + &[(Ptr::from_string_literal(b"ab")).into()], + ); + let __b = __s.as_bytes(); + if ::std::mem::size_of::<[u8; 32]>() > 0 { + let __n = ::std::cmp::min(__b.len(), ::std::mem::size_of::<[u8; 32]>() - 1); + (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { + __dst[..__n].copy_from_slice(&__b[..__n]); + __dst[__n] = 0; + }); + } + __b.len() as i32 + } == 7) as i32) + != 0) + ); + assert!( + ((({ + let mut __it1 = (buf.as_pointer() as Ptr).to_c_string_iterator(); + let mut __it2 = Ptr::from_string_literal(b"ab |").to_c_string_iterator(); + loop { + let __c1 = __it1.next(); + let __c2 = __it2.next(); + if __c1 != __c2 { + break (__c1.unwrap_or(0) as i32) - (__c2.unwrap_or(0) as i32); + } + if __c1.is_none() { + break 0; + } + } + } == 0) as i32) + != 0) + ); + assert!( + ((({ + let __s = libcc2rs::format_c( + &Ptr::from_string_literal(b"%*d").to_rust_string(), + &[(4).into(), (7).into()], + ); let __b = __s.as_bytes(); - let __size = (::std::mem::size_of::<[u8; 32]>()) as usize; - if __size > 0 { - let __n = ::std::cmp::min(__b.len(), __size - 1); + if ::std::mem::size_of::<[u8; 32]>() > 0 { + let __n = ::std::cmp::min(__b.len(), ::std::mem::size_of::<[u8; 32]>() - 1); (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { __dst[..__n].copy_from_slice(&__b[..__n]); __dst[__n] = 0; }); } __b.len() as i32 - }) == 8) as i32) + } == 4) as i32) != 0) ); assert!( ((({ let mut __it1 = (buf.as_pointer() as Ptr).to_c_string_iterator(); - let mut __it2 = Ptr::from_string_literal(b"00042|ff").to_c_string_iterator(); + let mut __it2 = Ptr::from_string_literal(b" 7").to_c_string_iterator(); loop { let __c1 = __it1.next(); let __c2 = __it2.next(); @@ -113,19 +224,56 @@ fn main_0() -> i32 { != 0) ); assert!( - (((({ - let __s = format!("{}%", 65 as u8 as char); + ((({ + let __s = libcc2rs::format_c( + &Ptr::from_string_literal(b"%.3s").to_rust_string(), + &[(Ptr::from_string_literal(b"abcdef")).into()], + ); + let __b = __s.as_bytes(); + if ::std::mem::size_of::<[u8; 32]>() > 0 { + let __n = ::std::cmp::min(__b.len(), ::std::mem::size_of::<[u8; 32]>() - 1); + (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { + __dst[..__n].copy_from_slice(&__b[..__n]); + __dst[__n] = 0; + }); + } + __b.len() as i32 + } == 3) as i32) + != 0) + ); + assert!( + ((({ + let mut __it1 = (buf.as_pointer() as Ptr).to_c_string_iterator(); + let mut __it2 = Ptr::from_string_literal(b"abc").to_c_string_iterator(); + loop { + let __c1 = __it1.next(); + let __c2 = __it2.next(); + if __c1 != __c2 { + break (__c1.unwrap_or(0) as i32) - (__c2.unwrap_or(0) as i32); + } + if __c1.is_none() { + break 0; + } + } + } == 0) as i32) + != 0) + ); + assert!( + ((({ + let __s = libcc2rs::format_c( + &Ptr::from_string_literal(b"%c%%").to_rust_string(), + &[(65).into()], + ); let __b = __s.as_bytes(); - let __size = (::std::mem::size_of::<[u8; 32]>()) as usize; - if __size > 0 { - let __n = ::std::cmp::min(__b.len(), __size - 1); + if ::std::mem::size_of::<[u8; 32]>() > 0 { + let __n = ::std::cmp::min(__b.len(), ::std::mem::size_of::<[u8; 32]>() - 1); (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { __dst[..__n].copy_from_slice(&__b[..__n]); __dst[__n] = 0; }); } __b.len() as i32 - }) == 2) as i32) + } == 2) as i32) != 0) ); assert!( @@ -146,19 +294,56 @@ fn main_0() -> i32 { != 0) ); assert!( - (((({ - let __s = format!("{} {} {}", -1_i64, 1_u64, (9 as usize)); + ((({ + let __s = libcc2rs::format_c( + &Ptr::from_string_literal(b"%+d % d").to_rust_string(), + &[(5).into(), (5).into()], + ); + let __b = __s.as_bytes(); + if ::std::mem::size_of::<[u8; 32]>() > 0 { + let __n = ::std::cmp::min(__b.len(), ::std::mem::size_of::<[u8; 32]>() - 1); + (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { + __dst[..__n].copy_from_slice(&__b[..__n]); + __dst[__n] = 0; + }); + } + __b.len() as i32 + } == 5) as i32) + != 0) + ); + assert!( + ((({ + let mut __it1 = (buf.as_pointer() as Ptr).to_c_string_iterator(); + let mut __it2 = Ptr::from_string_literal(b"+5 5").to_c_string_iterator(); + loop { + let __c1 = __it1.next(); + let __c2 = __it2.next(); + if __c1 != __c2 { + break (__c1.unwrap_or(0) as i32) - (__c2.unwrap_or(0) as i32); + } + if __c1.is_none() { + break 0; + } + } + } == 0) as i32) + != 0) + ); + assert!( + ((({ + let __s = libcc2rs::format_c( + &Ptr::from_string_literal(b"%ld %lu %zu").to_rust_string(), + &[(-1_i64).into(), (1_u64).into(), (9 as usize).into()], + ); let __b = __s.as_bytes(); - let __size = (::std::mem::size_of::<[u8; 32]>()) as usize; - if __size > 0 { - let __n = ::std::cmp::min(__b.len(), __size - 1); + if ::std::mem::size_of::<[u8; 32]>() > 0 { + let __n = ::std::cmp::min(__b.len(), ::std::mem::size_of::<[u8; 32]>() - 1); (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { __dst[..__n].copy_from_slice(&__b[..__n]); __dst[__n] = 0; }); } __b.len() as i32 - }) == 6) as i32) + } == 6) as i32) != 0) ); assert!( @@ -178,23 +363,139 @@ fn main_0() -> i32 { } == 0) as i32) != 0) ); + assert!( + ((({ + let __s = libcc2rs::format_c( + &Ptr::from_string_literal(b"%e").to_rust_string(), + &[(1.2345678E+3).into()], + ); + let __b = __s.as_bytes(); + if ::std::mem::size_of::<[u8; 32]>() > 0 { + let __n = ::std::cmp::min(__b.len(), ::std::mem::size_of::<[u8; 32]>() - 1); + (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { + __dst[..__n].copy_from_slice(&__b[..__n]); + __dst[__n] = 0; + }); + } + __b.len() as i32 + } == 12) as i32) + != 0) + ); + assert!( + ((({ + let mut __it1 = (buf.as_pointer() as Ptr).to_c_string_iterator(); + let mut __it2 = Ptr::from_string_literal(b"1.234568e+03").to_c_string_iterator(); + loop { + let __c1 = __it1.next(); + let __c2 = __it2.next(); + if __c1 != __c2 { + break (__c1.unwrap_or(0) as i32) - (__c2.unwrap_or(0) as i32); + } + if __c1.is_none() { + break 0; + } + } + } == 0) as i32) + != 0) + ); + assert!( + ((({ + let __s = libcc2rs::format_c( + &Ptr::from_string_literal(b"%g").to_rust_string(), + &[(1.234567E+6).into()], + ); + let __b = __s.as_bytes(); + if ::std::mem::size_of::<[u8; 32]>() > 0 { + let __n = ::std::cmp::min(__b.len(), ::std::mem::size_of::<[u8; 32]>() - 1); + (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { + __dst[..__n].copy_from_slice(&__b[..__n]); + __dst[__n] = 0; + }); + } + __b.len() as i32 + } == 11) as i32) + != 0) + ); + assert!( + ((({ + let mut __it1 = (buf.as_pointer() as Ptr).to_c_string_iterator(); + let mut __it2 = Ptr::from_string_literal(b"1.23457e+06").to_c_string_iterator(); + loop { + let __c1 = __it1.next(); + let __c2 = __it2.next(); + if __c1 != __c2 { + break (__c1.unwrap_or(0) as i32) - (__c2.unwrap_or(0) as i32); + } + if __c1.is_none() { + break 0; + } + } + } == 0) as i32) + != 0) + ); (*buf.borrow_mut())[(0) as usize] = (('Z' as i32) as u8); assert!( - (((({ - let __s = format!("{}", 123); + ((({ + let __s = libcc2rs::format_c( + &Ptr::from_string_literal(b"%d").to_rust_string(), + &[(123).into()], + ); let __b = __s.as_bytes(); - let __size = (0_usize) as usize; - if __size > 0 { - let __n = ::std::cmp::min(__b.len(), __size - 1); + if 0_usize > 0 { + let __n = ::std::cmp::min(__b.len(), 0_usize - 1); (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { __dst[..__n].copy_from_slice(&__b[..__n]); __dst[__n] = 0; }); } __b.len() as i32 - }) == 3) as i32) + } == 3) as i32) != 0) ); assert!((((((*buf.borrow())[(0) as usize] as i32) == ('Z' as i32)) as i32) != 0)); + let fmt: Value> = Rc::new(RefCell::new( + (0..8).map(|_| ::default()).collect::>(), + )); + (*fmt.borrow_mut())[(0) as usize] = (('%' as i32) as u8); + (*fmt.borrow_mut())[(1) as usize] = (('5' as i32) as u8); + (*fmt.borrow_mut())[(2) as usize] = (('.' as i32) as u8); + (*fmt.borrow_mut())[(3) as usize] = (('1' as i32) as u8); + (*fmt.borrow_mut())[(4) as usize] = (('f' as i32) as u8); + (*fmt.borrow_mut())[(5) as usize] = 0_u8; + assert!( + ((({ + let __s = libcc2rs::format_c( + &(fmt.as_pointer() as Ptr).to_rust_string(), + &[(3.26E+0).into()], + ); + let __b = __s.as_bytes(); + if ::std::mem::size_of::<[u8; 32]>() > 0 { + let __n = ::std::cmp::min(__b.len(), ::std::mem::size_of::<[u8; 32]>() - 1); + (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { + __dst[..__n].copy_from_slice(&__b[..__n]); + __dst[__n] = 0; + }); + } + __b.len() as i32 + } == 5) as i32) + != 0) + ); + assert!( + ((({ + let mut __it1 = (buf.as_pointer() as Ptr).to_c_string_iterator(); + let mut __it2 = Ptr::from_string_literal(b" 3.3").to_c_string_iterator(); + loop { + let __c1 = __it1.next(); + let __c2 = __it2.next(); + if __c1 != __c2 { + break (__c1.unwrap_or(0) as i32) - (__c2.unwrap_or(0) as i32); + } + if __c1.is_none() { + break 0; + } + } + } == 0) as i32) + != 0) + ); return 0; } diff --git a/tests/unit/out/unsafe/snprintf.rs b/tests/unit/out/unsafe/snprintf.rs index a492dace..f1329c98 100644 --- a/tests/unit/out/unsafe/snprintf.rs +++ b/tests/unit/out/unsafe/snprintf.rs @@ -55,17 +55,91 @@ unsafe fn main_0() -> i32 { libc::snprintf( buf.as_mut_ptr() as *mut libc::c_char, ::std::mem::size_of::<[libc::c_char; 32]>() as usize, - (c"%05d|%02x".as_ptr().cast_mut()).cast_const() as *const libc::c_char, + (c"%05d|%x|%X".as_ptr().cast_mut()).cast_const() as *const libc::c_char, (42), (255), + (255), ) - }) == (8)) as i32) + }) == (11)) as i32) + != 0) + ); + assert!( + ((((libc::strcmp( + (buf.as_mut_ptr()).cast_const(), + (c"00042|ff|FF".as_ptr().cast_mut()).cast_const() + )) == (0)) as i32) + != 0) + ); + assert!( + ((((unsafe { + libc::snprintf( + buf.as_mut_ptr() as *mut libc::c_char, + ::std::mem::size_of::<[libc::c_char; 32]>() as usize, + (c"%.2f".as_ptr().cast_mut()).cast_const() as *const libc::c_char, + (3.14159E+0), + ) + }) == (4)) as i32) + != 0) + ); + assert!( + ((((libc::strcmp( + (buf.as_mut_ptr()).cast_const(), + (c"3.14".as_ptr().cast_mut()).cast_const() + )) == (0)) as i32) + != 0) + ); + assert!( + ((((unsafe { + libc::snprintf( + buf.as_mut_ptr() as *mut libc::c_char, + ::std::mem::size_of::<[libc::c_char; 32]>() as usize, + (c"%-6s|".as_ptr().cast_mut()).cast_const() as *const libc::c_char, + (c"ab".as_ptr().cast_mut()), + ) + }) == (7)) as i32) + != 0) + ); + assert!( + ((((libc::strcmp( + (buf.as_mut_ptr()).cast_const(), + (c"ab |".as_ptr().cast_mut()).cast_const() + )) == (0)) as i32) + != 0) + ); + assert!( + ((((unsafe { + libc::snprintf( + buf.as_mut_ptr() as *mut libc::c_char, + ::std::mem::size_of::<[libc::c_char; 32]>() as usize, + (c"%*d".as_ptr().cast_mut()).cast_const() as *const libc::c_char, + (4), + (7), + ) + }) == (4)) as i32) + != 0) + ); + assert!( + ((((libc::strcmp( + (buf.as_mut_ptr()).cast_const(), + (c" 7".as_ptr().cast_mut()).cast_const() + )) == (0)) as i32) + != 0) + ); + assert!( + ((((unsafe { + libc::snprintf( + buf.as_mut_ptr() as *mut libc::c_char, + ::std::mem::size_of::<[libc::c_char; 32]>() as usize, + (c"%.3s".as_ptr().cast_mut()).cast_const() as *const libc::c_char, + (c"abcdef".as_ptr().cast_mut()), + ) + }) == (3)) as i32) != 0) ); assert!( ((((libc::strcmp( (buf.as_mut_ptr()).cast_const(), - (c"00042|ff".as_ptr().cast_mut()).cast_const() + (c"abc".as_ptr().cast_mut()).cast_const() )) == (0)) as i32) != 0) ); @@ -87,6 +161,25 @@ unsafe fn main_0() -> i32 { )) == (0)) as i32) != 0) ); + assert!( + ((((unsafe { + libc::snprintf( + buf.as_mut_ptr() as *mut libc::c_char, + ::std::mem::size_of::<[libc::c_char; 32]>() as usize, + (c"%+d % d".as_ptr().cast_mut()).cast_const() as *const libc::c_char, + (5), + (5), + ) + }) == (5)) as i32) + != 0) + ); + assert!( + ((((libc::strcmp( + (buf.as_mut_ptr()).cast_const(), + (c"+5 5".as_ptr().cast_mut()).cast_const() + )) == (0)) as i32) + != 0) + ); assert!( ((((unsafe { libc::snprintf( @@ -107,6 +200,42 @@ unsafe fn main_0() -> i32 { )) == (0)) as i32) != 0) ); + assert!( + ((((unsafe { + libc::snprintf( + buf.as_mut_ptr() as *mut libc::c_char, + ::std::mem::size_of::<[libc::c_char; 32]>() as usize, + (c"%e".as_ptr().cast_mut()).cast_const() as *const libc::c_char, + (1.2345678E+3), + ) + }) == (12)) as i32) + != 0) + ); + assert!( + ((((libc::strcmp( + (buf.as_mut_ptr()).cast_const(), + (c"1.234568e+03".as_ptr().cast_mut()).cast_const() + )) == (0)) as i32) + != 0) + ); + assert!( + ((((unsafe { + libc::snprintf( + buf.as_mut_ptr() as *mut libc::c_char, + ::std::mem::size_of::<[libc::c_char; 32]>() as usize, + (c"%g".as_ptr().cast_mut()).cast_const() as *const libc::c_char, + (1.234567E+6), + ) + }) == (11)) as i32) + != 0) + ); + assert!( + ((((libc::strcmp( + (buf.as_mut_ptr()).cast_const(), + (c"1.23457e+06".as_ptr().cast_mut()).cast_const() + )) == (0)) as i32) + != 0) + ); buf[(0) as usize] = (('Z' as i32) as libc::c_char); assert!( ((((unsafe { @@ -120,5 +249,30 @@ unsafe fn main_0() -> i32 { != 0) ); assert!(((((buf[(0) as usize] as i32) == ('Z' as i32)) as i32) != 0)); + let mut fmt: [libc::c_char; 8] = [(0 as libc::c_char); 8]; + fmt[(0) as usize] = (('%' as i32) as libc::c_char); + fmt[(1) as usize] = (('5' as i32) as libc::c_char); + fmt[(2) as usize] = (('.' as i32) as libc::c_char); + fmt[(3) as usize] = (('1' as i32) as libc::c_char); + fmt[(4) as usize] = (('f' as i32) as libc::c_char); + fmt[(5) as usize] = (0 as libc::c_char); + assert!( + ((((unsafe { + libc::snprintf( + buf.as_mut_ptr() as *mut libc::c_char, + ::std::mem::size_of::<[libc::c_char; 32]>() as usize, + (fmt.as_mut_ptr()).cast_const() as *const libc::c_char, + (3.26E+0), + ) + }) == (5)) as i32) + != 0) + ); + assert!( + ((((libc::strcmp( + (buf.as_mut_ptr()).cast_const(), + (c" 3.3".as_ptr().cast_mut()).cast_const() + )) == (0)) as i32) + != 0) + ); return 0; } diff --git a/tests/unit/snprintf.c b/tests/unit/snprintf.c index c7571b55..f3782662 100644 --- a/tests/unit/snprintf.c +++ b/tests/unit/snprintf.c @@ -8,14 +8,33 @@ int main() { assert(strcmp(buf, "x=-3 y=7") == 0); assert(snprintf(buf, 4, "%s", "hello") == 5); assert(strcmp(buf, "hel") == 0); - assert(snprintf(buf, sizeof(buf), "%05d|%02x", 42, 255) == 8); - assert(strcmp(buf, "00042|ff") == 0); + assert(snprintf(buf, sizeof(buf), "%05d|%x|%X", 42, 255, 255) == 11); + assert(strcmp(buf, "00042|ff|FF") == 0); + assert(snprintf(buf, sizeof(buf), "%.2f", 3.14159) == 4); + assert(strcmp(buf, "3.14") == 0); + assert(snprintf(buf, sizeof(buf), "%-6s|", "ab") == 7); + assert(strcmp(buf, "ab |") == 0); assert(snprintf(buf, sizeof(buf), "%c%%", 65) == 2); assert(strcmp(buf, "A%") == 0); + assert(snprintf(buf, sizeof(buf), "%+d % d", 5, 5) == 5); + assert(strcmp(buf, "+5 5") == 0); assert(snprintf(buf, sizeof(buf), "%ld %lu %zu", -1L, 1UL, (size_t)9) == 6); assert(strcmp(buf, "-1 1 9") == 0); + assert(snprintf(buf, sizeof(buf), "%e", 1234.5678) == 12); + assert(strcmp(buf, "1.234568e+03") == 0); + assert(snprintf(buf, sizeof(buf), "%g", 1234567.0) == 11); + assert(strcmp(buf, "1.23457e+06") == 0); buf[0] = 'Z'; assert(snprintf(buf, 0, "%d", 123) == 3); assert(buf[0] == 'Z'); + char fmt[8]; + fmt[0] = '%'; + fmt[1] = '5'; + fmt[2] = '.'; + fmt[3] = '1'; + fmt[4] = 'f'; + fmt[5] = 0; + assert(snprintf(buf, sizeof(buf), fmt, 3.26) == 5); + assert(strcmp(buf, " 3.3") == 0); return 0; } From 7cc69802bb507ef026d6865060c853c3d9002e9d Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 20 Jul 2026 15:18:14 +0100 Subject: [PATCH 7/7] Update tests --- tests/unit/out/refcount/snprintf.rs | 70 ----------------------------- tests/unit/out/unsafe/snprintf.rs | 37 --------------- 2 files changed, 107 deletions(-) diff --git a/tests/unit/out/refcount/snprintf.rs b/tests/unit/out/refcount/snprintf.rs index 30163277..70b92fce 100644 --- a/tests/unit/out/refcount/snprintf.rs +++ b/tests/unit/out/refcount/snprintf.rs @@ -188,76 +188,6 @@ fn main_0() -> i32 { } == 0) as i32) != 0) ); - assert!( - ((({ - let __s = libcc2rs::format_c( - &Ptr::from_string_literal(b"%*d").to_rust_string(), - &[(4).into(), (7).into()], - ); - let __b = __s.as_bytes(); - if ::std::mem::size_of::<[u8; 32]>() > 0 { - let __n = ::std::cmp::min(__b.len(), ::std::mem::size_of::<[u8; 32]>() - 1); - (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { - __dst[..__n].copy_from_slice(&__b[..__n]); - __dst[__n] = 0; - }); - } - __b.len() as i32 - } == 4) as i32) - != 0) - ); - assert!( - ((({ - let mut __it1 = (buf.as_pointer() as Ptr).to_c_string_iterator(); - let mut __it2 = Ptr::from_string_literal(b" 7").to_c_string_iterator(); - loop { - let __c1 = __it1.next(); - let __c2 = __it2.next(); - if __c1 != __c2 { - break (__c1.unwrap_or(0) as i32) - (__c2.unwrap_or(0) as i32); - } - if __c1.is_none() { - break 0; - } - } - } == 0) as i32) - != 0) - ); - assert!( - ((({ - let __s = libcc2rs::format_c( - &Ptr::from_string_literal(b"%.3s").to_rust_string(), - &[(Ptr::from_string_literal(b"abcdef")).into()], - ); - let __b = __s.as_bytes(); - if ::std::mem::size_of::<[u8; 32]>() > 0 { - let __n = ::std::cmp::min(__b.len(), ::std::mem::size_of::<[u8; 32]>() - 1); - (buf.as_pointer() as Ptr).with_slice_mut(__n + 1, |__dst| { - __dst[..__n].copy_from_slice(&__b[..__n]); - __dst[__n] = 0; - }); - } - __b.len() as i32 - } == 3) as i32) - != 0) - ); - assert!( - ((({ - let mut __it1 = (buf.as_pointer() as Ptr).to_c_string_iterator(); - let mut __it2 = Ptr::from_string_literal(b"abc").to_c_string_iterator(); - loop { - let __c1 = __it1.next(); - let __c2 = __it2.next(); - if __c1 != __c2 { - break (__c1.unwrap_or(0) as i32) - (__c2.unwrap_or(0) as i32); - } - if __c1.is_none() { - break 0; - } - } - } == 0) as i32) - != 0) - ); assert!( ((({ let __s = libcc2rs::format_c( diff --git a/tests/unit/out/unsafe/snprintf.rs b/tests/unit/out/unsafe/snprintf.rs index f1329c98..c8bfbe46 100644 --- a/tests/unit/out/unsafe/snprintf.rs +++ b/tests/unit/out/unsafe/snprintf.rs @@ -106,43 +106,6 @@ unsafe fn main_0() -> i32 { )) == (0)) as i32) != 0) ); - assert!( - ((((unsafe { - libc::snprintf( - buf.as_mut_ptr() as *mut libc::c_char, - ::std::mem::size_of::<[libc::c_char; 32]>() as usize, - (c"%*d".as_ptr().cast_mut()).cast_const() as *const libc::c_char, - (4), - (7), - ) - }) == (4)) as i32) - != 0) - ); - assert!( - ((((libc::strcmp( - (buf.as_mut_ptr()).cast_const(), - (c" 7".as_ptr().cast_mut()).cast_const() - )) == (0)) as i32) - != 0) - ); - assert!( - ((((unsafe { - libc::snprintf( - buf.as_mut_ptr() as *mut libc::c_char, - ::std::mem::size_of::<[libc::c_char; 32]>() as usize, - (c"%.3s".as_ptr().cast_mut()).cast_const() as *const libc::c_char, - (c"abcdef".as_ptr().cast_mut()), - ) - }) == (3)) as i32) - != 0) - ); - assert!( - ((((libc::strcmp( - (buf.as_mut_ptr()).cast_const(), - (c"abc".as_ptr().cast_mut()).cast_const() - )) == (0)) as i32) - != 0) - ); assert!( ((((unsafe { libc::snprintf(