Skip to content

Commit 2764098

Browse files
committed
Make println!("String") work
miri complains about a memory leak when the program terminates. This may be related to thread-local dtors not running.
1 parent bea6d83 commit 2764098

File tree

1 file changed

+40
-10
lines changed

1 file changed

+40
-10
lines changed

src/terminator/mod.rs

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -367,31 +367,43 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
367367

368368
// Only trait methods can have a Self parameter.
369369

370+
// Intercept some methods (even if we can find MIR for them)
371+
if let ty::InstanceDef::Item(def_id) = instance.def {
372+
match &self.tcx.item_path_str(def_id)[..] {
373+
"std::sys::imp::fast_thread_local::register_dtor" => {
374+
// Just don't execute this one, we don't handle all this thread-local stuff anyway.
375+
self.goto_block(destination.unwrap().1);
376+
return Ok(true)
377+
}
378+
_ => {}
379+
}
380+
}
381+
370382
let mir = match self.load_mir(instance.def) {
371383
Ok(mir) => mir,
372384
Err(EvalError::NoMirFor(path)) => {
373-
match &path[..] {
374-
// let's just ignore all output for now
385+
return match &path[..] {
386+
// Intercept some methods if we cannot find their MIR.
375387
"std::io::_print" => {
388+
trace!("Ignoring output.");
376389
self.goto_block(destination.unwrap().1);
377-
return Ok(true);
390+
Ok(true)
378391
},
379-
"std::thread::Builder::new" => return Err(EvalError::Unimplemented("miri does not support threading".to_owned())),
380-
"std::env::args" => return Err(EvalError::Unimplemented("miri does not support program arguments".to_owned())),
392+
"std::thread::Builder::new" => Err(EvalError::Unimplemented("miri does not support threading".to_owned())),
393+
"std::env::args" => Err(EvalError::Unimplemented("miri does not support program arguments".to_owned())),
381394
"std::panicking::rust_panic_with_hook" |
382-
"std::rt::begin_panic_fmt" => return Err(EvalError::Panic),
395+
"std::rt::begin_panic_fmt" => Err(EvalError::Panic),
383396
"std::panicking::panicking" |
384397
"std::rt::panicking" => {
385398
let (lval, block) = destination.expect("std::rt::panicking does not diverge");
386399
// we abort on panic -> `std::rt::panicking` always returns false
387400
let bool = self.tcx.types.bool;
388401
self.write_primval(lval, PrimVal::from_bool(false), bool)?;
389402
self.goto_block(block);
390-
return Ok(true);
403+
Ok(true)
391404
}
392-
_ => {},
393-
}
394-
return Err(EvalError::NoMirFor(path));
405+
_ => Err(EvalError::NoMirFor(path)),
406+
};
395407
},
396408
Err(other) => return Err(other),
397409
};
@@ -569,6 +581,24 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
569581
}
570582
self.write_value(Value::ByVal(PrimVal::Bytes(0)), dest, dest_ty)?;
571583
}
584+
585+
"write" => {
586+
let fd = self.value_to_primval(args[0], usize)?.to_u64()?;
587+
let buf = args[1].read_ptr(&self.memory)?;
588+
let n = self.value_to_primval(args[2], usize)?.to_u64()?;
589+
trace!("Called write({:?}, {:?}, {:?})", fd, buf, n);
590+
let result = if fd == 1 { // stdout
591+
use std::io::{self, Write};
592+
593+
let buf_cont = self.memory.read_bytes(buf, n)?;
594+
let res = io::stdout().write(buf_cont);
595+
match res { Ok(n) => n as isize, Err(_) => -1 }
596+
} else {
597+
info!("Ignored output to FD {}", fd);
598+
n as isize // pretend it all went well
599+
}; // now result is the value we return back to the program
600+
self.write_primval(dest, PrimVal::Bytes(result as u128), dest_ty)?;
601+
}
572602

573603
// unix panic code inside libstd will read the return value of this function
574604
"pthread_rwlock_rdlock" => {

0 commit comments

Comments
 (0)