mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 21:13:37 +00:00
Support libc::getenv
in mir interpreter
This commit is contained in:
parent
cc5664c5a2
commit
9b636e2326
4 changed files with 83 additions and 1 deletions
|
@ -130,6 +130,7 @@ impl ChangeFixture {
|
|||
let mut default_crate_root: Option<FileId> = None;
|
||||
let mut default_target_data_layout: Option<String> = None;
|
||||
let mut default_cfg = CfgOptions::default();
|
||||
let mut default_env = Env::new_for_test_fixture();
|
||||
|
||||
let mut file_set = FileSet::default();
|
||||
let mut current_source_root_kind = SourceRootKind::Local;
|
||||
|
@ -200,6 +201,7 @@ impl ChangeFixture {
|
|||
assert!(default_crate_root.is_none());
|
||||
default_crate_root = Some(file_id);
|
||||
default_cfg = meta.cfg;
|
||||
default_env.extend(meta.env.iter().map(|(x, y)| (x.to_owned(), y.to_owned())));
|
||||
default_target_data_layout = meta.target_data_layout;
|
||||
}
|
||||
|
||||
|
@ -220,7 +222,7 @@ impl ChangeFixture {
|
|||
None,
|
||||
default_cfg,
|
||||
Default::default(),
|
||||
Env::new_for_test_fixture(),
|
||||
default_env,
|
||||
false,
|
||||
CrateOrigin::Local { repo: None, name: None },
|
||||
default_target_data_layout
|
||||
|
|
|
@ -686,6 +686,12 @@ impl fmt::Display for Edition {
|
|||
}
|
||||
}
|
||||
|
||||
impl Extend<(String, String)> for Env {
|
||||
fn extend<T: IntoIterator<Item = (String, String)>>(&mut self, iter: T) {
|
||||
self.entries.extend(iter);
|
||||
}
|
||||
}
|
||||
|
||||
impl FromIterator<(String, String)> for Env {
|
||||
fn from_iter<T: IntoIterator<Item = (String, String)>>(iter: T) -> Self {
|
||||
Env { entries: FromIterator::from_iter(iter) }
|
||||
|
|
|
@ -473,6 +473,38 @@ impl Evaluator<'_> {
|
|||
self.write_memory_using_ref(destination.addr, destination.size)?.fill(0);
|
||||
Ok(())
|
||||
}
|
||||
"getenv" => {
|
||||
let [name] = args else {
|
||||
return Err(MirEvalError::TypeError("libc::write args are not provided"));
|
||||
};
|
||||
let mut name_buf = vec![];
|
||||
let name = {
|
||||
let mut index = Address::from_bytes(name.get(self)?)?;
|
||||
loop {
|
||||
let byte = self.read_memory(index, 1)?[0];
|
||||
index = index.offset(1);
|
||||
if byte == 0 {
|
||||
break;
|
||||
}
|
||||
name_buf.push(byte);
|
||||
}
|
||||
String::from_utf8_lossy(&name_buf)
|
||||
};
|
||||
let value = self.db.crate_graph()[self.crate_id].env.get(&name);
|
||||
match value {
|
||||
None => {
|
||||
// Write null as fail
|
||||
self.write_memory_using_ref(destination.addr, destination.size)?.fill(0);
|
||||
}
|
||||
Some(mut value) => {
|
||||
value.push('\0');
|
||||
let addr = self.heap_allocate(value.len(), 1)?;
|
||||
self.write_memory(addr, value.as_bytes())?;
|
||||
self.write_memory(destination.addr, &addr.to_bytes())?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
_ => not_supported!("unknown external function {as_str}"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -729,6 +729,48 @@ fn main() {
|
|||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn posix_getenv() {
|
||||
check_pass(
|
||||
r#"
|
||||
//- /main.rs env:foo=bar
|
||||
|
||||
type c_char = u8;
|
||||
|
||||
extern "C" {
|
||||
pub fn getenv(s: *const c_char) -> *mut c_char;
|
||||
}
|
||||
|
||||
fn should_not_reach() {
|
||||
_ // FIXME: replace this function with panic when that works
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let result = getenv(b"foo\0" as *const _);
|
||||
if *result != b'b' {
|
||||
should_not_reach();
|
||||
}
|
||||
let result = (result as usize + 1) as *const c_char;
|
||||
if *result != b'a' {
|
||||
should_not_reach();
|
||||
}
|
||||
let result = (result as usize + 1) as *const c_char;
|
||||
if *result != b'r' {
|
||||
should_not_reach();
|
||||
}
|
||||
let result = (result as usize + 1) as *const c_char;
|
||||
if *result != 0 {
|
||||
should_not_reach();
|
||||
}
|
||||
let result = getenv(b"not found\0" as *const _);
|
||||
if result as usize != 0 {
|
||||
should_not_reach();
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn posix_tls() {
|
||||
check_pass(
|
||||
|
|
Loading…
Reference in a new issue