Skip to content

Commit b1aa88c

Browse files
authored
Call printf rule when the format string is not static (#508)
1 parent cd937fa commit b1aa88c

18 files changed

Lines changed: 381 additions & 190 deletions

‎cpp2rust/converter/converter.cpp‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2279,8 +2279,13 @@ std::optional<Converter::TempMaterializationCtx>
22792279
Converter::ConvertCallExpr(clang::CallExpr *expr) {
22802280
auto *callee = expr->getCallee();
22812281

2282-
if (auto fn = Printer::ToString(ctx_, callee);
2283-
fn.starts_with("int printf") || fn.starts_with("int fprintf")) {
2282+
auto fn = Printer::ToString(ctx_, callee);
2283+
bool is_printf = fn.starts_with("int printf");
2284+
bool is_fprintf = fn.starts_with("int fprintf");
2285+
unsigned format_arg = is_fprintf ? 1 : 0;
2286+
if ((is_printf || is_fprintf) &&
2287+
clang::isa<clang::StringLiteral>(
2288+
expr->getArg(format_arg)->IgnoreImplicit())) {
22842289
ConvertPrintf(expr);
22852290
} else if (IsTransparentStdCall(expr)) {
22862291
Convert(expr->getArg(0));

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,16 +1252,8 @@ static std::vector<const char *> printf2fmt(std::string &format) {
12521252
void ConverterRefCount::ConvertPrintf(clang::CallExpr *expr) {
12531253
bool is_fprintf =
12541254
Printer::ToString(ctx_, expr->getCallee()).starts_with("int fprintf");
1255-
std::string format;
1256-
if (auto *str = clang::dyn_cast<clang::StringLiteral>(
1257-
expr->getArg(is_fprintf)->IgnoreImplicit())) {
1258-
format = GetEscapedStringLiteral(str);
1259-
} else {
1260-
llvm::errs() << "Unknown fprintf format: ";
1261-
expr->getArg(1)->dump();
1262-
llvm::errs() << '\n';
1263-
exit(1);
1264-
}
1255+
auto format = GetEscapedStringLiteral(clang::cast<clang::StringLiteral>(
1256+
expr->getArg(is_fprintf)->IgnoreImplicit()));
12651257
bool ends_newline = format.ends_with("\\n\"");
12661258

12671259
auto fd = is_fprintf ? Printer::ToString(ctx_, expr->getArg(0)) : "stdout";

‎rules/stdio/src.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,7 @@ int f25(void) { return SEEK_SET; }
7676
int f26(void) { return SEEK_CUR; }
7777

7878
int f27(void) { return SEEK_END; }
79+
80+
int (*f28)(FILE *, const char *, ...) = fprintf;
81+
82+
int (*f29)(const char *, ...) = printf;

‎rules/stdio/tgt_refcount.rs‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,3 +189,13 @@ fn f23(a0: Ptr<CFile>) -> i32 {
189189
fn f24(a0: Ptr<CFile>, a1: Ptr<i8>, a2: i32, a3: usize) -> i32 {
190190
0
191191
}
192+
193+
fn f28(a0: Ptr<CFile>, a1: Ptr<i8>, va: &[VaArg]) -> i32 {
194+
let __s = libcc2rs::format_c(&a1.to_rust_string(), va);
195+
a0.with_mut(|__f| __f.write(__s.as_bytes())) as i32
196+
}
197+
198+
fn f29(a0: Ptr<i8>, va: &[VaArg]) -> i32 {
199+
let __s = libcc2rs::format_c(&a0.to_rust_string(), va);
200+
libcc2rs::c_stdout().with_mut(|__f| __f.write(__s.as_bytes())) as i32
201+
}

‎rules/stdio/tgt_unsafe.rs‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,11 @@ unsafe fn f26() -> i32 {
116116
unsafe fn f27() -> i32 {
117117
::libc::SEEK_END
118118
}
119+
120+
unsafe extern "C" {
121+
fn f28(a0: *mut ::libc::FILE, a1: *const libc::c_char, ...) -> i32;
122+
}
123+
124+
unsafe extern "C" {
125+
fn f29(a0: *const libc::c_char, ...) -> i32;
126+
}

‎tests/unit/out/refcount/printfs.rs‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,27 @@ pub fn fn_0(mut v: Vec<i8>) -> Vec<i8> {
1818
pub fn fn2_1(v: Ptr<Vec<i8>>) -> Ptr<Vec<i8>> {
1919
return (v).clone();
2020
}
21+
pub fn log_to_2(mut out: Ptr<CFile>, mut fmt: Ptr<i8>, mut args_2: Ptr<i8>, mut args_3: i32) {
22+
{
23+
let __s = libcc2rs::format_c(
24+
&fmt.to_rust_string(),
25+
&[((args_2).clone()).into(), (args_3).into()],
26+
);
27+
out.with_mut(|__f| __f.write(__s.as_bytes())) as i32
28+
};
29+
}
30+
pub fn log_to_3(mut out: Ptr<CFile>, mut fmt: Ptr<i8>, mut args: i32) {
31+
{
32+
let __s = libcc2rs::format_c(&fmt.to_rust_string(), &[(args).into()]);
33+
out.with_mut(|__f| __f.write(__s.as_bytes())) as i32
34+
};
35+
}
36+
pub fn log_fmt_4(mut fmt: Ptr<i8>, mut v: i32) {
37+
{
38+
let __s = libcc2rs::format_c(&fmt.to_rust_string(), &[(v).into()]);
39+
libcc2rs::c_stdout().with_mut(|__f| __f.write(__s.as_bytes())) as i32
40+
};
41+
}
2142
pub fn main() {
2243
__cpp2rust_init_globals();
2344
std::process::exit(main_0());
@@ -53,6 +74,22 @@ fn main_0() -> i32 {
5374
"{}",
5475
(Ptr::<Vec<i8>>::decay(&({ fn2_1(s.as_pointer(),) })) as Ptr<i8>)
5576
);
77+
({
78+
log_to_2(
79+
libcc2rs::c_stdout(),
80+
Ptr::<i8>::from_string_literal(b"%s %d\n"),
81+
Ptr::<i8>::from_string_literal(b"runtime"),
82+
4,
83+
)
84+
});
85+
({
86+
log_to_3(
87+
libcc2rs::c_stderr(),
88+
Ptr::<i8>::from_string_literal(b"%d\n"),
89+
5,
90+
)
91+
});
92+
({ log_fmt_4(Ptr::<i8>::from_string_literal(b"%d\n"), 6) });
5693
println!("{{}} {} {}", 5_u64, (-6_i32 as i64));
5794
return 0;
5895
}

‎tests/unit/out/unsafe/c_string_embedded_nul.rs‎

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,22 @@ unsafe fn main_0() -> i32 {
2828
let s = (buf.as_mut_ptr()).cast_const();
2929
std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1).to_vec()
3030
};
31-
printf(c"%zu\n".as_ptr() as *const i8, (s.len() - 1));
32-
printf(
33-
c"%zu %zu\n".as_ptr() as *const i8,
34-
libc::strlen((buf.as_mut_ptr()).cast_const()),
35-
match s.iter().rposition(|&c| {
36-
::std::ffi::CStr::from_ptr((buf.as_mut_ptr()).cast_const())
37-
.to_str()
38-
.unwrap()
39-
.contains(c as u8 as char)
40-
}) {
41-
Some(idx) => idx,
42-
None => usize::MAX,
43-
},
44-
);
31+
(unsafe { libc::printf(c"%zu\n".as_ptr() as *const libc::c_char, (s.len() - 1)) });
32+
(unsafe {
33+
libc::printf(
34+
c"%zu %zu\n".as_ptr() as *const libc::c_char,
35+
(libc::strlen((buf.as_mut_ptr()).cast_const())),
36+
(match s.iter().rposition(|&c| {
37+
::std::ffi::CStr::from_ptr((buf.as_mut_ptr()).cast_const())
38+
.to_str()
39+
.unwrap()
40+
.contains(c as u8 as char)
41+
}) {
42+
Some(idx) => idx,
43+
None => usize::MAX,
44+
}),
45+
)
46+
});
4547
let mut lit: *const libc::c_char = (&[
4648
(120 as libc::c_char),
4749
(121 as libc::c_char),
@@ -55,7 +57,7 @@ unsafe fn main_0() -> i32 {
5557
let s = lit;
5658
std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1).to_vec()
5759
};
58-
printf(c"%zu\n".as_ptr() as *const i8, (t.len() - 1));
60+
(unsafe { libc::printf(c"%zu\n".as_ptr() as *const libc::c_char, (t.len() - 1)) });
5961
return 0;
6062
}
6163
pub unsafe fn __cpp2rust_init_globals() {}

‎tests/unit/out/unsafe/char_signed.rs‎

Lines changed: 54 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -21,50 +21,69 @@ pub fn main() {
2121
unsafe fn main_0() -> i32 {
2222
let mut c: libc::c_char = (-56 as libc::c_char);
2323
let mut widened: i32 = (c as i32);
24-
printf(
25-
c"%d %d\n".as_ptr() as *const i8,
26-
widened,
27-
(unsafe { to_int_0((b'\xff' as libc::c_char)) }),
28-
);
29-
printf(c"%d\n".as_ptr() as *const i8, (((c as i32) < (0)) as i32));
24+
(unsafe {
25+
libc::printf(
26+
c"%d %d\n".as_ptr() as *const libc::c_char,
27+
(widened),
28+
(unsafe { to_int_0((b'\xff' as libc::c_char)) }),
29+
)
30+
});
31+
(unsafe {
32+
libc::printf(
33+
c"%d\n".as_ptr() as *const libc::c_char,
34+
(((c as i32) < (0)) as i32),
35+
)
36+
});
3037
let mut lit: [libc::c_char; 4] = std::mem::transmute(*b"\xe9t\xe9\0");
3138
let mut ulit: [u8; 4] = std::mem::transmute(*b"\xe9t\xe9\0");
32-
printf(
33-
c"%d %d\n".as_ptr() as *const i8,
34-
(lit[(0) as usize] as i32),
35-
(ulit[(0) as usize] as i32),
36-
);
37-
printf(
38-
c"%d\n".as_ptr() as *const i8,
39-
((unsafe { is_negative_1((lit.as_mut_ptr()).cast_const()) }) as i32),
40-
);
39+
(unsafe {
40+
libc::printf(
41+
c"%d %d\n".as_ptr() as *const libc::c_char,
42+
(lit[(0) as usize] as i32),
43+
(ulit[(0) as usize] as i32),
44+
)
45+
});
46+
(unsafe {
47+
libc::printf(
48+
c"%d\n".as_ptr() as *const libc::c_char,
49+
((unsafe { is_negative_1((lit.as_mut_ptr()).cast_const()) }) as i32),
50+
)
51+
});
4152
let mut u8s: *const libc::c_char = c"\xc3\xa9".as_ptr();
42-
printf(
43-
c"%d %d\n".as_ptr() as *const i8,
44-
((*u8s.offset((0) as isize)) as i32),
45-
((*u8s.offset((1) as isize)) as i32),
46-
);
53+
(unsafe {
54+
libc::printf(
55+
c"%d %d\n".as_ptr() as *const libc::c_char,
56+
((*u8s.offset((0) as isize)) as i32),
57+
((*u8s.offset((1) as isize)) as i32),
58+
)
59+
});
4760
let mut p: *const libc::c_char = c"\x80".as_ptr();
48-
printf(
49-
c"%d %d\n".as_ptr() as *const i8,
50-
((*p.offset((0) as isize)) as i32),
51-
(((*p.offset((0) as isize)) as u8) as i32),
52-
);
53-
printf(
54-
c"%d\n".as_ptr() as *const i8,
55-
(((libc::strcmp(c"\x80".as_ptr(), c"a".as_ptr())) > (0)) as i32),
56-
);
61+
(unsafe {
62+
libc::printf(
63+
c"%d %d\n".as_ptr() as *const libc::c_char,
64+
((*p.offset((0) as isize)) as i32),
65+
(((*p.offset((0) as isize)) as u8) as i32),
66+
)
67+
});
68+
(unsafe {
69+
libc::printf(
70+
c"%d\n".as_ptr() as *const libc::c_char,
71+
(((libc::strcmp(c"\x80".as_ptr(), c"a".as_ptr())) > (0)) as i32),
72+
)
73+
});
5774
let mut s: Vec<libc::c_char> = {
5875
let s = c"\xfe!".as_ptr();
5976
std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1).to_vec()
6077
};
61-
printf(
62-
c"%d %d\n".as_ptr() as *const i8,
63-
(s[(0_usize)] as i32),
64-
(s[(1_usize)] as i32),
65-
);
78+
(unsafe {
79+
libc::printf(
80+
c"%d %d\n".as_ptr() as *const libc::c_char,
81+
(s[(0_usize)] as i32),
82+
(s[(1_usize)] as i32),
83+
)
84+
});
6685
let mut sum: libc::c_char = (((c as i32) + (c as i32)) as libc::c_char);
67-
printf(c"%d\n".as_ptr() as *const i8, (sum as i32));
86+
(unsafe { libc::printf(c"%d\n".as_ptr() as *const libc::c_char, (sum as i32)) });
6887
return 0;
6988
}
7089
pub unsafe fn __cpp2rust_init_globals() {}

‎tests/unit/out/unsafe/iterators.rs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ unsafe fn main_0() -> i32 {
2323
}
2424
'loop_: for c in 0..(x.len() - 1) {
2525
let mut c = x.as_mut_ptr().add(c);
26-
printf(c"%c\n".as_ptr() as *const i8, ((*c) as i32));
26+
(unsafe { libc::printf(c"%c\n".as_ptr() as *const libc::c_char, ((*c) as i32)) });
2727
}
2828
'loop_: for c in 0..(x.len() - 1) {
2929
let mut c = x[c].clone();
30-
printf(c"%c\n".as_ptr() as *const i8, (c as i32));
30+
(unsafe { libc::printf(c"%c\n".as_ptr() as *const libc::c_char, (c as i32)) });
3131
}
3232
let mut v: Vec<*mut i32> = Vec::new();
3333
{
@@ -40,7 +40,7 @@ unsafe fn main_0() -> i32 {
4040
};
4141
'loop_: for p in 0..(v.len()) {
4242
let mut p = v[p].clone();
43-
printf(c"%d\n".as_ptr() as *const i8, (*p));
43+
(unsafe { libc::printf(c"%d\n".as_ptr() as *const libc::c_char, (*p)) });
4444
}
4545
return 0;
4646
}

‎tests/unit/out/unsafe/macros.rs‎

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,14 @@ pub unsafe fn base_name_0(mut path: *const libc::c_char) -> *const libc::c_char
1616
};
1717
}
1818
pub unsafe fn log_1(mut file: *const libc::c_char, mut line: i32, mut func: *const libc::c_char) {
19-
printf(c"%s %d %s\n".as_ptr() as *const i8, file, line, func);
19+
(unsafe {
20+
libc::printf(
21+
c"%s %d %s\n".as_ptr() as *const libc::c_char,
22+
(file),
23+
(line),
24+
(func),
25+
)
26+
});
2027
}
2128
pub unsafe fn line_2() -> i32 {
2229
return (line!() as u32 as i32);
@@ -31,12 +38,14 @@ pub fn main() {
3138
}
3239
}
3340
unsafe fn main_0() -> i32 {
34-
printf(
35-
c"%s %d %s\n".as_ptr() as *const i8,
36-
c"macros.cpp".as_ptr(),
37-
19,
38-
c"main".as_ptr(),
39-
);
41+
(unsafe {
42+
libc::printf(
43+
c"%s %d %s\n".as_ptr() as *const libc::c_char,
44+
(c"macros.cpp".as_ptr()),
45+
(19),
46+
(c"main".as_ptr()),
47+
)
48+
});
4049
(unsafe { log_1(c"macros.cpp".as_ptr(), 20, c"main".as_ptr()) });
4150
assert!(((line!() as u32) > (0_u32)));
4251
assert!(
@@ -45,7 +54,12 @@ unsafe fn main_0() -> i32 {
4554
!= (('\0' as libc::c_char) as i32))
4655
);
4756
assert!(((unsafe { line_2() }) > (0)));
48-
printf(c"%s\n".as_ptr() as *const i8, (unsafe { function_3() }));
57+
(unsafe {
58+
libc::printf(
59+
c"%s\n".as_ptr() as *const libc::c_char,
60+
(unsafe { function_3() }),
61+
)
62+
});
4963
return 0;
5064
}
5165
pub unsafe fn __cpp2rust_init_globals() {}

0 commit comments

Comments
 (0)