core::rt: Fix a use after free in uv 'write'
This commit is contained in:
parent
a292d51750
commit
8a2f9cae21
4 changed files with 21 additions and 12 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue