Skip to content

Commit 609ae54

Browse files
authored
Handle strings with interior null pointer (#222)
1 parent 1df15d7 commit 609ae54

4 files changed

Lines changed: 137 additions & 3 deletions

File tree

cpp2rust/converter/converter.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,8 +1991,15 @@ bool Converter::VisitStringLiteral(clang::StringLiteral *expr) {
19911991
GetEscapedStringLiteral(expr, 1)));
19921992
return false;
19931993
}
1994-
assert(!expr->getString().contains('\0') &&
1995-
"interior null byte in string literal");
1994+
if (expr->getString().contains('\0')) {
1995+
std::string out = "(&[";
1996+
for (unsigned char c : expr->getString()) {
1997+
out += getTypedLiteral(std::to_string(c).c_str(), CharRustType()) + ", ";
1998+
}
1999+
out += getTypedLiteral("0", CharRustType()) + "])";
2000+
StrCat(out);
2001+
return false;
2002+
}
19962003
StrCat(std::format("c{}", GetEscapedStringLiteral(expr, 0)));
19972004
return false;
19982005
}
@@ -2927,7 +2934,8 @@ bool Converter::VisitCompoundLiteralExpr(clang::CompoundLiteralExpr *expr) {
29272934

29282935
bool Converter::VisitArraySubscriptExpr(clang::ArraySubscriptExpr *expr) {
29292936
auto *base = expr->getBase();
2930-
if (base->IgnoreCasts()->getType()->isPointerType()) {
2937+
if (base->IgnoreCasts()->getType()->isPointerType() ||
2938+
clang::isa<clang::StringLiteral>(base->IgnoreCasts())) {
29312939
ConvertPointerSubscript(expr);
29322940
} else {
29332941
ConvertArraySubscript(base, expr->getIdx(), expr->getType());
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
extern crate libcc2rs;
2+
use libcc2rs::*;
3+
use std::cell::RefCell;
4+
use std::collections::BTreeMap;
5+
use std::io::prelude::*;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::AsFd;
8+
use std::rc::{Rc, Weak};
9+
pub fn sum_bytes_0(buf: Ptr<u8>, len: u32) -> i32 {
10+
let buf: Value<Ptr<u8>> = Rc::new(RefCell::new(buf));
11+
let len: Value<u32> = Rc::new(RefCell::new(len));
12+
let sum: Value<i32> = Rc::new(RefCell::new(0));
13+
let i: Value<u32> = Rc::new(RefCell::new(0_u32));
14+
'loop_: while ((*i.borrow()) < (*len.borrow())) {
15+
(*sum.borrow_mut()) += (((*buf.borrow()).offset((*i.borrow()) as isize).read()) as i32);
16+
(*i.borrow_mut()).postfix_inc();
17+
}
18+
return (*sum.borrow());
19+
}
20+
thread_local!(
21+
pub static g_packet_1: Value<Ptr<u8>> =
22+
Rc::new(RefCell::new(Ptr::from_string_literal(b"\x01\0")));
23+
);
24+
pub fn main() {
25+
std::process::exit(main_0());
26+
}
27+
fn main_0() -> i32 {
28+
let a: Value<i32> = Rc::new(RefCell::new(
29+
({ sum_bytes_0(Ptr::from_string_literal(b"\x01\0"), 2_u32) }),
30+
));
31+
let b: Value<i32> = Rc::new(RefCell::new(
32+
({ sum_bytes_0((*g_packet_1.with(Value::clone).borrow()).clone(), 2_u32) }),
33+
));
34+
assert!(((*a.borrow()) == (*b.borrow())));
35+
assert!(((*a.borrow()) == 1));
36+
let c: Value<i32> = Rc::new(RefCell::new(
37+
((b"\r\n.\r\n"[(0) as usize] as i32) + (b"\r\n.\r\n"[(3) as usize] as i32)),
38+
));
39+
assert!(((*c.borrow()) == ((('\r' as u8) as i32) + (('\r' as u8) as i32))));
40+
let idx: Value<i32> = Rc::new(RefCell::new(1));
41+
let d: Value<i32> = Rc::new(RefCell::new((b"abcd"[(*idx.borrow()) as usize] as i32)));
42+
assert!(((*d.borrow()) == (('b' as u8) as i32)));
43+
return 0;
44+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
extern crate libc;
2+
use libc::*;
3+
extern crate libcc2rs;
4+
use libcc2rs::*;
5+
use std::collections::BTreeMap;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
8+
use std::rc::Rc;
9+
pub unsafe fn sum_bytes_0(mut buf: *const libc::c_char, mut len: u32) -> i32 {
10+
let mut sum: i32 = 0;
11+
let mut i: u32 = 0_u32;
12+
'loop_: while ((i) < (len)) {
13+
sum += (((*buf.offset((i) as isize)) as u8) as i32);
14+
i.postfix_inc();
15+
}
16+
return sum;
17+
}
18+
pub static mut g_packet_1: *const libc::c_char = unsafe {
19+
(&[
20+
(1 as libc::c_char),
21+
(0 as libc::c_char),
22+
(0 as libc::c_char),
23+
])
24+
.as_ptr()
25+
};
26+
pub fn main() {
27+
unsafe {
28+
std::process::exit(main_0() as i32);
29+
}
30+
}
31+
unsafe fn main_0() -> i32 {
32+
let mut a: i32 = (unsafe {
33+
sum_bytes_0(
34+
(&[
35+
(1 as libc::c_char),
36+
(0 as libc::c_char),
37+
(0 as libc::c_char),
38+
])
39+
.as_ptr(),
40+
2_u32,
41+
)
42+
});
43+
let mut b: i32 = (unsafe { sum_bytes_0(g_packet_1, 2_u32) });
44+
assert!(((a) == (b)));
45+
assert!(((a) == (1)));
46+
let mut c: i32 = (((*c"\r\n.\r\n".as_ptr().offset((0) as isize)) as i32)
47+
+ ((*c"\r\n.\r\n".as_ptr().offset((3) as isize)) as i32));
48+
assert!(((c) == ((('\r' as libc::c_char) as i32) + (('\r' as libc::c_char) as i32))));
49+
let mut idx: i32 = 1;
50+
let mut d: i32 = ((*c"abcd".as_ptr().offset((idx) as isize)) as i32);
51+
assert!(((d) == (('b' as libc::c_char) as i32)));
52+
return 0;
53+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include <assert.h>
2+
#include <cstdio>
3+
4+
static int sum_bytes(const char *buf, unsigned len) {
5+
int sum = 0;
6+
for (unsigned i = 0; i < len; i++) {
7+
sum += (unsigned char)buf[i];
8+
}
9+
return sum;
10+
}
11+
12+
static const char *g_packet = "\x01\x00";
13+
14+
int main() {
15+
int a = sum_bytes("\x01\x00", 2);
16+
int b = sum_bytes(g_packet, 2);
17+
18+
assert(a == b);
19+
assert(a == 1);
20+
21+
int c = "\r\n.\r\n"[0] + "\r\n.\r\n"[3];
22+
assert(c == '\r' + '\r');
23+
24+
int idx = 1;
25+
int d = "abcd"[idx];
26+
assert(d == 'b');
27+
28+
return 0;
29+
}

0 commit comments

Comments
 (0)