core::rt: Fix a use after free in uv 'write'

This commit is contained in:
Brian Anderson 2013-04-22 19:20:31 -07:00
parent a292d51750
commit 8a2f9cae21
4 changed files with 21 additions and 12 deletions

View File

@ -301,7 +301,8 @@ struct WatcherData {
write_cb: Option<ConnectionCallback>,
connect_cb: Option<ConnectionCallback>,
close_cb: Option<NullCallback>,
alloc_cb: Option<AllocCallback>
alloc_cb: Option<AllocCallback>,
buf: Option<Buf>
}
pub fn install_watcher_data<H, W: Watcher + NativeHandle<*H>>(watcher: &mut W) {
@ -311,7 +312,8 @@ pub fn install_watcher_data<H, W: Watcher + NativeHandle<*H>>(watcher: &mut W) {
write_cb: None,
connect_cb: None,
close_cb: None,
alloc_cb: None
alloc_cb: None,
buf: None
};
let data = transmute::<~WatcherData, *c_void>(data);
uvll::set_data_for_uv_handle(watcher.native_handle(), data);

View File

@ -107,21 +107,25 @@ pub impl StreamWatcher {
let req = WriteRequest::new();
let buf = vec_to_uv_buf(msg);
// XXX: Allocation
let bufs = ~[buf];
assert!(data.buf.is_none());
data.buf = Some(buf);
let bufs = [buf];
unsafe {
assert!(0 == uvll::write(req.native_handle(),
self.native_handle(),
&bufs, write_cb));
bufs, write_cb));
}
// XXX: Freeing immediately after write. Is this ok?
let _v = vec_from_uv_buf(buf);
extern fn write_cb(req: *uvll::uv_write_t, status: c_int) {
let write_request: WriteRequest = NativeHandle::from_native_handle(req);
let mut stream_watcher = write_request.stream();
write_request.delete();
let cb = get_watcher_data(&mut stream_watcher).write_cb.swap_unwrap();
let cb = {
let data = get_watcher_data(&mut stream_watcher);
let _vec = vec_from_uv_buf(data.buf.swap_unwrap());
let cb = data.write_cb.swap_unwrap();
cb
};
let status = status_to_maybe_uv_error(stream_watcher.native_handle(), status);
cb(stream_watcher, status);
}

View File

@ -445,7 +445,7 @@ fn test_read_read_read() {
let io = local_sched::unsafe_borrow_io();
let mut listener = io.bind(addr).unwrap();
let mut stream = listener.listen().unwrap();
let mut buf = [0, .. 2048];
let mut buf = [1, .. 2048];
let mut total_bytes_written = 0;
while total_bytes_written < MAX {
stream.write(buf);
@ -465,6 +465,9 @@ fn test_read_read_read() {
let nread = stream.read(buf).unwrap();
rtdebug!("read %u bytes", nread as uint);
total_bytes_read += nread;
for uint::range(0, nread) |i| {
assert!(buf[i] == 1);
}
}
rtdebug!("read %u bytes total", total_bytes_read as uint);
stream.close();

View File

@ -219,9 +219,9 @@ pub unsafe fn accept(server: *c_void, client: *c_void) -> c_int {
return rust_uv_accept(server as *c_void, client as *c_void);
}
pub unsafe fn write<T>(req: *uv_write_t, stream: *T, buf_in: *~[uv_buf_t], cb: *u8) -> c_int {
let buf_ptr = vec::raw::to_ptr(*buf_in);
let buf_cnt = vec::len(*buf_in) as i32;
pub unsafe fn write<T>(req: *uv_write_t, stream: *T, buf_in: &[uv_buf_t], cb: *u8) -> c_int {
let buf_ptr = vec::raw::to_ptr(buf_in);
let buf_cnt = vec::len(buf_in) as i32;
return rust_uv_write(req as *c_void, stream as *c_void, buf_ptr, buf_cnt, cb);
}
pub unsafe fn read_start(stream: *uv_stream_t, on_alloc: *u8, on_read: *u8) -> c_int {