Skip to content

Commit a194df9

Browse files
committed
Handle non-printable ASCII in str and byte arrays (#169)
`"\xff"` or `'\xff'` are valid strings/char literals in C/C++. They were not escaped and produced an invalid character that broke the compilation. After I escaped them, I realized that they cannot be translated to `\xff` in Rust `str`'s because str only accepts `\x00 - \x7f`. Byte array accepts `> \x7f`. I changed Ptr::from_string_literal to accept a byte array instead of a str. I also changed GetFmtArg to refuse to create Rust `str` that contains chars `> \x7f` and fallback to GetRawArg that produces escaped byte arrays.
1 parent 15fbe1d commit a194df9

12 files changed

Lines changed: 108 additions & 126 deletions

cpp2rust/converter/converter.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,7 +1334,11 @@ bool Converter::GetFmtArg(clang::Expr *arg, std::string &fmt,
13341334
std::string &fmt_args, std::string &fmt_trait,
13351335
std::string &fmt_width) {
13361336
std::string arg_str = Mapper::ToString(arg);
1337-
if (clang::isa<clang::StringLiteral>(arg->IgnoreImplicit())) {
1337+
if (auto *str_lit =
1338+
clang::dyn_cast<clang::StringLiteral>(arg->IgnoreImplicit())) {
1339+
if (!IsAsciiStringLiteral(str_lit)) {
1340+
return false;
1341+
}
13381342
auto str = GetEscapedStringLiteral(arg);
13391343
// Delete " from string
13401344
str.erase(std::remove(str.begin(), str.end(), '"'), str.end());
@@ -1376,6 +1380,8 @@ bool Converter::GetRawArg(clang::Expr *arg, std::string &raw_args) {
13761380
raw_args += "(&(" + str + ")[..(" + str + ").len() - 1]";
13771381
} else if (Mapper::ToString(arg).contains("std::endl")) {
13781382
raw_args += "(&[b'\\n']";
1383+
} else if (clang::isa<clang::StringLiteral>(arg->IgnoreImplicit())) {
1384+
raw_args += "(b" + GetEscapedStringLiteral(arg);
13791385
} else {
13801386
return false;
13811387
}
@@ -1811,8 +1817,9 @@ bool Converter::VisitFloatingLiteral(clang::FloatingLiteral *expr) {
18111817
}
18121818

18131819
bool Converter::VisitCharacterLiteral(clang::CharacterLiteral *expr) {
1820+
auto uc = static_cast<unsigned char>(expr->getValue());
18141821
std::string ch = GetEscapedCharLiteral(expr->getValue());
1815-
ch = "'" + std::move(ch) + "'";
1822+
ch = (uc > 0x7F ? "b'" : "'") + std::move(ch) + '\'';
18161823
{
18171824
PushParen paren(*this);
18181825
StrCat(ch, keyword::kAs, ToStringBase(expr->getType()));
@@ -1839,7 +1846,7 @@ std::string Converter::GetEscapedCharLiteral(char character) const {
18391846
return "\\0";
18401847
}
18411848
auto uc = static_cast<unsigned char>(character);
1842-
if (uc < 0x20 || uc == 0x7F) {
1849+
if (uc < 0x20 || uc >= 0x7F) {
18431850
return std::format("\\x{:02x}", uc);
18441851
}
18451852
return std::string(1, character);

tests/unit/out/refcount/enum_int_interop.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -116,16 +116,16 @@ pub fn classify_option_5(option: i32) -> i32 {
116116
'switch: {
117117
let __match_cond = (*option.borrow());
118118
match __match_cond {
119-
__v if __v == (Option::OPT_NONE as i32) => {
119+
v if v == (Option::OPT_NONE as i32) => {
120120
return -1_i32;
121121
}
122-
__v if __v == (Option::OPT_A as i32) => {
122+
v if v == (Option::OPT_A as i32) => {
123123
return 1;
124124
}
125-
__v if __v == (Option::OPT_B as i32) => {
125+
v if v == (Option::OPT_B as i32) => {
126126
return 2;
127127
}
128-
__v if __v == (Option::OPT_C as i32) => {
128+
v if v == (Option::OPT_C as i32) => {
129129
return 3;
130130
}
131131
_ => {
@@ -153,13 +153,13 @@ fn main_0() -> i32 {
153153
'switch: {
154154
let __match_cond = ((*c.borrow()) as i32);
155155
match __match_cond {
156-
__v if __v == 0 => {
156+
v if v == 0 => {
157157
break 'switch;
158158
}
159-
__v if __v == 1 => {
159+
v if v == 1 => {
160160
return 1;
161161
}
162-
__v if __v == 2 => {
162+
v if v == 2 => {
163163
return 2;
164164
}
165165
_ => {
@@ -215,13 +215,13 @@ fn main_0() -> i32 {
215215
'switch: {
216216
let __match_cond = ((*t.borrow()) as i32);
217217
match __match_cond {
218-
__v if __v == (Tag::TAG_ZERO as i32) => {
218+
v if v == (Tag::TAG_ZERO as i32) => {
219219
return 90;
220220
}
221-
__v if __v == 1 => {
221+
v if v == 1 => {
222222
return 91;
223223
}
224-
__v if __v == 2 => {
224+
v if v == 2 => {
225225
break 'switch;
226226
}
227227
_ => {}

tests/unit/out/refcount/enum_int_interop_c.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,17 +81,17 @@ thread_local!(
8181
thread_local!(
8282
pub static entries_3: Value<Box<[Entry]>> = Rc::new(RefCell::new(Box::new([
8383
Entry {
84-
name: Rc::new(RefCell::new(Ptr::from_string_literal("first"))),
84+
name: Rc::new(RefCell::new(Ptr::from_string_literal(b"first"))),
8585
color: Rc::new(RefCell::new(Color::RED)),
8686
opt: Rc::new(RefCell::new(Option::OPT_NONE)),
8787
},
8888
Entry {
89-
name: Rc::new(RefCell::new(Ptr::from_string_literal("second"))),
89+
name: Rc::new(RefCell::new(Ptr::from_string_literal(b"second"))),
9090
color: Rc::new(RefCell::new(Color::GREEN)),
9191
opt: Rc::new(RefCell::new(Option::OPT_A)),
9292
},
9393
Entry {
94-
name: Rc::new(RefCell::new(Ptr::from_string_literal("third"))),
94+
name: Rc::new(RefCell::new(Ptr::from_string_literal(b"third"))),
9595
color: Rc::new(RefCell::new(Color::BLUE)),
9696
opt: Rc::new(RefCell::new(Option::OPT_C)),
9797
},

tests/unit/out/refcount/string.rs

Lines changed: 67 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ fn main_0() -> i32 {
4141
assert!((*s1.borrow())
4242
.iter()
4343
.copied()
44-
.take((*s1.borrow()).len().saturating_sub(1))
44+
.take((*s1.borrow()).len() - 1)
4545
.eq(Ptr::from_string_literal(b"hello").to_c_string_iterator()));
4646
let p1: Value<Ptr<u8>> = Rc::new(RefCell::new((s1.as_pointer() as Ptr<u8>)));
4747
assert!(((((*p1.borrow()).offset((0) as isize).read()) as i32) == (('h' as u8) as i32)));
@@ -98,11 +98,8 @@ fn main_0() -> i32 {
9898
(*i.borrow_mut()).prefix_inc();
9999
}
100100
let s3: Value<Vec<u8>> = Rc::new(RefCell::new({
101-
let mut __tmp1 = (*s2.borrow())[(2_u64) as usize
102-
..::std::cmp::min(
103-
(2_u64 + 5_u64) as usize,
104-
(*s2.borrow()).len().saturating_sub(1),
105-
)]
101+
let mut __tmp1 = (*s2.borrow())
102+
[(2_u64) as usize..::std::cmp::min((2_u64 + 5_u64) as usize, (*s2.borrow()).len() - 1)]
106103
.to_vec();
107104
__tmp1.push(0);
108105
__tmp1
@@ -123,18 +120,20 @@ fn main_0() -> i32 {
123120
let s4: Value<Vec<u8>> = Rc::new(RefCell::new({
124121
let mut __tmp1 = (*s1.borrow())[(1_u64) as usize
125122
..::std::cmp::min(
126-
(1_u64 + {
127-
let __lookup: Vec<u8> = Ptr::from_string_literal(b"l")
128-
.to_c_string_iterator()
129-
.collect();
130-
(*s1.borrow())
123+
(1_u64
124+
+ match (*s1.borrow())
131125
.iter()
132-
.take((*s1.borrow()).len().saturating_sub(1))
133-
.rposition(|&x| __lookup.contains(&x))
134-
.map(|idx| idx as u64)
135-
.unwrap_or(u64::MAX)
136-
}) as usize,
137-
(*s1.borrow()).len().saturating_sub(1),
126+
.take((*s1.borrow()).len() - 1)
127+
.rposition(|&x| {
128+
Ptr::from_string_literal(b"l")
129+
.to_c_string_iterator()
130+
.position(|ch| ch == x)
131+
.is_some()
132+
}) {
133+
Some(idx) => idx as u64,
134+
None => u64::MAX,
135+
}) as usize,
136+
(*s1.borrow()).len() - 1,
138137
)]
139138
.to_vec();
140139
__tmp1.push(0);
@@ -211,7 +210,7 @@ fn main_0() -> i32 {
211210
assert!((*string.borrow())
212211
.iter()
213212
.copied()
214-
.take((*string.borrow()).len().saturating_sub(1))
213+
.take((*string.borrow()).len() - 1)
215214
.eq(Ptr::from_string_literal(b"bar").to_c_string_iterator()));
216215
{
217216
(*string.borrow_mut()).pop();
@@ -240,7 +239,7 @@ fn main_0() -> i32 {
240239
assert!((*string.borrow())
241240
.iter()
242241
.copied()
243-
.take((*string.borrow()).len().saturating_sub(1))
242+
.take((*string.borrow()).len() - 1)
244243
.eq(Ptr::from_string_literal(b"bar").to_c_string_iterator()));
245244
{
246245
(*string.borrow_mut()).pop();
@@ -390,10 +389,7 @@ fn main_0() -> i32 {
390389
);
391390
let substr_0: Value<Vec<u8>> = Rc::new(RefCell::new({
392391
let mut __tmp1 = (*result.borrow())[(5_u64) as usize
393-
..::std::cmp::min(
394-
(5_u64 + 3_u64) as usize,
395-
(*result.borrow()).len().saturating_sub(1),
396-
)]
392+
..::std::cmp::min((5_u64 + 3_u64) as usize, (*result.borrow()).len() - 1)]
397393
.to_vec();
398394
__tmp1.push(0);
399395
__tmp1
@@ -419,10 +415,7 @@ fn main_0() -> i32 {
419415
);
420416
let substr_1: Value<Vec<u8>> = Rc::new(RefCell::new({
421417
let mut __tmp1 = (*result.borrow())[(0_u64) as usize
422-
..::std::cmp::min(
423-
(0_u64 + 5_u64) as usize,
424-
(*result.borrow()).len().saturating_sub(1),
425-
)]
418+
..::std::cmp::min((0_u64 + 5_u64) as usize, (*result.borrow()).len() - 1)]
426419
.to_vec();
427420
__tmp1.push(0);
428421
__tmp1
@@ -460,10 +453,7 @@ fn main_0() -> i32 {
460453
);
461454
let substr_2: Value<Vec<u8>> = Rc::new(RefCell::new({
462455
let mut __tmp1 = (*result.borrow())[(0_u64) as usize
463-
..::std::cmp::min(
464-
(0_u64 + 15_u64) as usize,
465-
(*result.borrow()).len().saturating_sub(1),
466-
)]
456+
..::std::cmp::min((0_u64 + 15_u64) as usize, (*result.borrow()).len() - 1)]
467457
.to_vec();
468458
__tmp1.push(0);
469459
__tmp1
@@ -517,52 +507,58 @@ fn main_0() -> i32 {
517507
.read()) as i32)
518508
== (('o' as u8) as i32))
519509
);
520-
let pos: Value<u64> = Rc::new(RefCell::new({
521-
let __lookup: Vec<u8> = Ptr::from_string_literal(b"b")
522-
.to_c_string_iterator()
523-
.collect();
524-
(*result.borrow())
510+
let pos: Value<u64> = Rc::new(RefCell::new(
511+
match (*result.borrow())
525512
.iter()
526-
.take((*result.borrow()).len().saturating_sub(1))
527-
.rposition(|&x| __lookup.contains(&x))
528-
.map(|idx| idx as u64)
529-
.unwrap_or(u64::MAX)
530-
}));
513+
.take((*result.borrow()).len() - 1)
514+
.rposition(|&x| {
515+
Ptr::from_string_literal(b"b")
516+
.to_c_string_iterator()
517+
.position(|ch| ch == x)
518+
.is_some()
519+
}) {
520+
Some(idx) => idx as u64,
521+
None => u64::MAX,
522+
},
523+
));
531524
assert!(((*pos.borrow()) == 0_u64));
532-
(*pos.borrow_mut()) = {
533-
let __lookup: Vec<u8> = Ptr::from_string_literal(b"f")
534-
.to_c_string_iterator()
535-
.collect();
536-
(*result.borrow())
537-
.iter()
538-
.take((*result.borrow()).len().saturating_sub(1))
539-
.rposition(|&x| __lookup.contains(&x))
540-
.map(|idx| idx as u64)
541-
.unwrap_or(u64::MAX)
525+
(*pos.borrow_mut()) = match (*result.borrow())
526+
.iter()
527+
.take((*result.borrow()).len() - 1)
528+
.rposition(|&x| {
529+
Ptr::from_string_literal(b"f")
530+
.to_c_string_iterator()
531+
.position(|ch| ch == x)
532+
.is_some()
533+
}) {
534+
Some(idx) => idx as u64,
535+
None => u64::MAX,
542536
};
543537
assert!(((*pos.borrow()) == 5_u64));
544-
(*pos.borrow_mut()) = {
545-
let __lookup: Vec<u8> = Ptr::from_string_literal(b"o")
546-
.to_c_string_iterator()
547-
.collect();
548-
(*result.borrow())
549-
.iter()
550-
.take((*result.borrow()).len().saturating_sub(1))
551-
.rposition(|&x| __lookup.contains(&x))
552-
.map(|idx| idx as u64)
553-
.unwrap_or(u64::MAX)
538+
(*pos.borrow_mut()) = match (*result.borrow())
539+
.iter()
540+
.take((*result.borrow()).len() - 1)
541+
.rposition(|&x| {
542+
Ptr::from_string_literal(b"o")
543+
.to_c_string_iterator()
544+
.position(|ch| ch == x)
545+
.is_some()
546+
}) {
547+
Some(idx) => idx as u64,
548+
None => u64::MAX,
554549
};
555550
assert!(((*pos.borrow()) == 7_u64));
556-
(*pos.borrow_mut()) = {
557-
let __lookup: Vec<u8> = Ptr::from_string_literal(b"x")
558-
.to_c_string_iterator()
559-
.collect();
560-
(*result.borrow())
561-
.iter()
562-
.take((*result.borrow()).len().saturating_sub(1))
563-
.rposition(|&x| __lookup.contains(&x))
564-
.map(|idx| idx as u64)
565-
.unwrap_or(u64::MAX)
551+
(*pos.borrow_mut()) = match (*result.borrow())
552+
.iter()
553+
.take((*result.borrow()).len() - 1)
554+
.rposition(|&x| {
555+
Ptr::from_string_literal(b"x")
556+
.to_c_string_iterator()
557+
.position(|ch| ch == x)
558+
.is_some()
559+
}) {
560+
Some(idx) => idx as u64,
561+
None => u64::MAX,
566562
};
567563
assert!(((*pos.borrow()) == (-1_i64 as u64)));
568564
let string_to_cast: Value<Vec<u8>> = Rc::new(RefCell::new(

tests/unit/out/refcount/string2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ fn main_0() -> i32 {
2626
assert!((*arr.borrow())
2727
.iter()
2828
.copied()
29-
.take((*arr.borrow()).len().saturating_sub(1))
29+
.take((*arr.borrow()).len() - 1)
3030
.eq(Ptr::from_string_literal(b"fbo").to_c_string_iterator()));
3131
return 0;
3232
}

tests/unit/out/refcount/string_literals.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,5 @@ fn main_0() -> i32 {
6060
let _str: Ptr<u8> = (immutable_empty_arr.as_pointer() as Ptr<u8>);
6161
foo_const_1(_str)
6262
});
63-
let inited_through_init_list: Value<Box<[u8]>> = Rc::new(RefCell::new(Box::<[u8]>::from(
64-
b"papanasi cu smantana\0".as_slice(),
65-
)));
66-
({
67-
let _str: Ptr<u8> = (inited_through_init_list.as_pointer() as Ptr<u8>);
68-
foo_const_1(_str)
69-
});
7063
return 0;
7164
}

tests/unit/out/refcount/string_literals_c.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,5 @@ fn main_0() -> i32 {
9191
let _str: Ptr<u8> = (immutable_empty_arr.as_pointer() as Ptr<u8>);
9292
foo_const_1(_str)
9393
});
94-
let inited_through_init_list: Value<Box<[u8]>> = Rc::new(RefCell::new(Box::<[u8]>::from(
95-
b"papanasi cu smantana\0".as_slice(),
96-
)));
97-
({
98-
let _str: Ptr<u8> = (inited_through_init_list.as_pointer() as Ptr<u8>);
99-
foo_const_1(_str)
100-
});
10194
return 0;
10295
}

tests/unit/out/refcount/va_arg_conditional.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ fn main_0() -> i32 {
2525
(((({
2626
let _verbose: i32 = 1;
2727
let _fmt: Ptr<u8> = Ptr::from_string_literal(b"%d");
28-
conditional_log_0(_verbose, _fmt, &[(42).into()])
28+
conditional_log_0(_verbose, _fmt, &[42.into()])
2929
}) == 42) as i32)
3030
!= 0)
3131
);
3232
assert!(
3333
(((({
3434
let _verbose: i32 = 0;
3535
let _fmt: Ptr<u8> = Ptr::from_string_literal(b"%d");
36-
conditional_log_0(_verbose, _fmt, &[(99).into()])
36+
conditional_log_0(_verbose, _fmt, &[99.into()])
3737
}) == -1_i32) as i32)
3838
!= 0)
3939
);

0 commit comments

Comments
 (0)