refactor(ffi): check pointer arguments for NULL (#2624)
This changes all the extern C functions in `hyper::ffi` to check passed pointer arguments for being `NULL` before trying to use them. Before, we would just assume the programmer had passed a good pointer, which could result in segmentation faults. Now: - In debug builds, it will assert they aren't null, and so if they are, a message identifying the argument name will be printed and then the process will crash. - In release builds, it will still check for null, but if found, it will return early, with a return value indicating failure if the return type allows (such as returning NULL, or `HYPERE_INVALID_ARG`). Closes #2620
This commit is contained in:
		| @@ -40,11 +40,7 @@ ffi_fn! { | ||||
| ffi_fn! { | ||||
|     /// Free a `hyper_body *`. | ||||
|     fn hyper_body_free(body: *mut hyper_body) { | ||||
|         if body.is_null() { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         drop(unsafe { Box::from_raw(body) }); | ||||
|         drop(non_null!(Box::from_raw(body) ?= ())); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -61,7 +57,7 @@ ffi_fn! { | ||||
|     /// However, it MUST NOT be used or freed until the related task completes. | ||||
|     fn hyper_body_data(body: *mut hyper_body) -> *mut hyper_task { | ||||
|         // This doesn't take ownership of the Body, so don't allow destructor | ||||
|         let mut body = ManuallyDrop::new(unsafe { Box::from_raw(body) }); | ||||
|         let mut body = ManuallyDrop::new(non_null!(Box::from_raw(body) ?= ptr::null_mut())); | ||||
|  | ||||
|         Box::into_raw(hyper_task::boxed(async move { | ||||
|             body.0.data().await.map(|res| res.map(hyper_buf)) | ||||
| @@ -81,11 +77,7 @@ ffi_fn! { | ||||
|     /// | ||||
|     /// This will consume the `hyper_body *`, you shouldn't use it anymore or free it. | ||||
|     fn hyper_body_foreach(body: *mut hyper_body, func: hyper_body_foreach_callback, userdata: *mut c_void) -> *mut hyper_task { | ||||
|         if body.is_null() { | ||||
|             return ptr::null_mut(); | ||||
|         } | ||||
|  | ||||
|         let mut body = unsafe { Box::from_raw(body) }; | ||||
|         let mut body = non_null!(Box::from_raw(body) ?= ptr::null_mut()); | ||||
|         let userdata = UserDataPointer(userdata); | ||||
|  | ||||
|         Box::into_raw(hyper_task::boxed(async move { | ||||
| @@ -103,7 +95,7 @@ ffi_fn! { | ||||
| ffi_fn! { | ||||
|     /// Set userdata on this body, which will be passed to callback functions. | ||||
|     fn hyper_body_set_userdata(body: *mut hyper_body, userdata: *mut c_void) { | ||||
|         let b = unsafe { &mut *body }; | ||||
|         let b = non_null!(&mut *body ?= ()); | ||||
|         b.0.as_ffi_mut().userdata = userdata; | ||||
|     } | ||||
| } | ||||
| @@ -129,7 +121,7 @@ ffi_fn! { | ||||
|     /// If some error has occurred, you can return `HYPER_POLL_ERROR` to abort | ||||
|     /// the body. | ||||
|     fn hyper_body_set_data_func(body: *mut hyper_body, func: hyper_body_data_callback) { | ||||
|         let b = unsafe { &mut *body }; | ||||
|         let b = non_null!{ &mut *body ?= () }; | ||||
|         b.0.as_ffi_mut().data_func = func; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| use std::ptr; | ||||
| use std::sync::Arc; | ||||
|  | ||||
| use libc::c_int; | ||||
| @@ -37,15 +38,8 @@ ffi_fn! { | ||||
|     /// The returned `hyper_task *` must be polled with an executor until the | ||||
|     /// handshake completes, at which point the value can be taken. | ||||
|     fn hyper_clientconn_handshake(io: *mut hyper_io, options: *mut hyper_clientconn_options) -> *mut hyper_task { | ||||
|         if io.is_null() { | ||||
|             return std::ptr::null_mut(); | ||||
|         } | ||||
|         if options.is_null() { | ||||
|             return std::ptr::null_mut(); | ||||
|         } | ||||
|  | ||||
|         let options = unsafe { Box::from_raw(options) }; | ||||
|         let io = unsafe { Box::from_raw(io) }; | ||||
|         let options = non_null! { Box::from_raw(options) ?= ptr::null_mut() }; | ||||
|         let io = non_null! { Box::from_raw(io) ?= ptr::null_mut() }; | ||||
|  | ||||
|         Box::into_raw(hyper_task::boxed(async move { | ||||
|             options.builder.handshake::<_, crate::Body>(io) | ||||
| @@ -66,19 +60,12 @@ ffi_fn! { | ||||
|     /// Returns a task that needs to be polled until it is ready. When ready, the | ||||
|     /// task yields a `hyper_response *`. | ||||
|     fn hyper_clientconn_send(conn: *mut hyper_clientconn, req: *mut hyper_request) -> *mut hyper_task { | ||||
|         if conn.is_null() { | ||||
|             return std::ptr::null_mut(); | ||||
|         } | ||||
|         if req.is_null() { | ||||
|             return std::ptr::null_mut(); | ||||
|         } | ||||
|  | ||||
|         let mut req = unsafe { Box::from_raw(req) }; | ||||
|         let mut req = non_null! { Box::from_raw(req) ?= ptr::null_mut() }; | ||||
|  | ||||
|         // Update request with original-case map of headers | ||||
|         req.finalize_request(); | ||||
|  | ||||
|         let fut = unsafe { &mut *conn }.tx.send_request(req.0); | ||||
|         let fut = non_null! { &mut *conn ?= ptr::null_mut() }.tx.send_request(req.0); | ||||
|  | ||||
|         let fut = async move { | ||||
|             fut.await.map(hyper_response::wrap) | ||||
| @@ -91,7 +78,7 @@ ffi_fn! { | ||||
| ffi_fn! { | ||||
|     /// Free a `hyper_clientconn *`. | ||||
|     fn hyper_clientconn_free(conn: *mut hyper_clientconn) { | ||||
|         drop(unsafe { Box::from_raw(conn) }); | ||||
|         drop(non_null! { Box::from_raw(conn) ?= () }); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -119,7 +106,7 @@ ffi_fn! { | ||||
| ffi_fn! { | ||||
|     /// Free a `hyper_clientconn_options *`. | ||||
|     fn hyper_clientconn_options_free(opts: *mut hyper_clientconn_options) { | ||||
|         drop(unsafe { Box::from_raw(opts) }); | ||||
|         drop(non_null! { Box::from_raw(opts) ?= () }); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -128,9 +115,9 @@ ffi_fn! { | ||||
|     /// | ||||
|     /// This does not consume the `options` or the `exec`. | ||||
|     fn hyper_clientconn_options_exec(opts: *mut hyper_clientconn_options, exec: *const hyper_executor) { | ||||
|         let opts = unsafe { &mut *opts }; | ||||
|         let opts = non_null! { &mut *opts ?= () }; | ||||
|  | ||||
|         let exec = unsafe { Arc::from_raw(exec) }; | ||||
|         let exec = non_null! { Arc::from_raw(exec) ?= () }; | ||||
|         let weak_exec = hyper_executor::downgrade(&exec); | ||||
|         std::mem::forget(exec); | ||||
|  | ||||
| @@ -146,7 +133,7 @@ ffi_fn! { | ||||
|     fn hyper_clientconn_options_http2(opts: *mut hyper_clientconn_options, enabled: c_int) -> hyper_code { | ||||
|         #[cfg(feature = "http2")] | ||||
|         { | ||||
|             let opts = unsafe { &mut *opts }; | ||||
|             let opts = non_null! { &mut *opts ?= hyper_code::HYPERE_INVALID_ARG }; | ||||
|             opts.builder.http2_only(enabled != 0); | ||||
|             hyper_code::HYPERE_OK | ||||
|         } | ||||
| @@ -168,7 +155,7 @@ ffi_fn! { | ||||
|     /// | ||||
|     /// If enabled, see `hyper_response_headers_raw()` for usage. | ||||
|     fn hyper_clientconn_options_headers_raw(opts: *mut hyper_clientconn_options, enabled: c_int) -> hyper_code { | ||||
|         let opts = unsafe { &mut *opts }; | ||||
|         let opts = non_null! { &mut *opts ?= hyper_code::HYPERE_INVALID_ARG }; | ||||
|         opts.builder.http1_headers_raw(enabled != 0); | ||||
|         hyper_code::HYPERE_OK | ||||
|     } | ||||
|   | ||||
| @@ -58,14 +58,14 @@ impl hyper_error { | ||||
| ffi_fn! { | ||||
|     /// Frees a `hyper_error`. | ||||
|     fn hyper_error_free(err: *mut hyper_error) { | ||||
|         drop(unsafe { Box::from_raw(err) }); | ||||
|         drop(non_null!(Box::from_raw(err) ?= ())); | ||||
|     } | ||||
| } | ||||
|  | ||||
| ffi_fn! { | ||||
|     /// Get an equivalent `hyper_code` from this error. | ||||
|     fn hyper_error_code(err: *const hyper_error) -> hyper_code { | ||||
|         unsafe { &*err }.code() | ||||
|         non_null!(&*err ?= hyper_code::HYPERE_INVALID_ARG).code() | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -80,6 +80,6 @@ ffi_fn! { | ||||
|         let dst = unsafe { | ||||
|             std::slice::from_raw_parts_mut(dst, dst_len) | ||||
|         }; | ||||
|         unsafe { &*err }.print_to(dst) | ||||
|         non_null!(&*err ?= 0).print_to(dst) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -48,7 +48,7 @@ ffi_fn! { | ||||
| ffi_fn! { | ||||
|     /// Free an HTTP request if not going to send it on a client. | ||||
|     fn hyper_request_free(req: *mut hyper_request) { | ||||
|         drop(unsafe { Box::from_raw(req) }); | ||||
|         drop(non_null!(Box::from_raw(req) ?= ())); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -58,9 +58,10 @@ ffi_fn! { | ||||
|         let bytes = unsafe { | ||||
|             std::slice::from_raw_parts(method, method_len as usize) | ||||
|         }; | ||||
|         let req = non_null!(&mut *req ?= hyper_code::HYPERE_INVALID_ARG); | ||||
|         match Method::from_bytes(bytes) { | ||||
|             Ok(m) => { | ||||
|                 *unsafe { &mut *req }.0.method_mut() = m; | ||||
|                 *req.0.method_mut() = m; | ||||
|                 hyper_code::HYPERE_OK | ||||
|             }, | ||||
|             Err(_) => { | ||||
| @@ -76,9 +77,10 @@ ffi_fn! { | ||||
|         let bytes = unsafe { | ||||
|             std::slice::from_raw_parts(uri, uri_len as usize) | ||||
|         }; | ||||
|         let req = non_null!(&mut *req ?= hyper_code::HYPERE_INVALID_ARG); | ||||
|         match Uri::from_maybe_shared(bytes) { | ||||
|             Ok(u) => { | ||||
|                 *unsafe { &mut *req }.0.uri_mut() = u; | ||||
|                 *req.0.uri_mut() = u; | ||||
|                 hyper_code::HYPERE_OK | ||||
|             }, | ||||
|             Err(_) => { | ||||
| @@ -98,7 +100,8 @@ ffi_fn! { | ||||
|     fn hyper_request_set_version(req: *mut hyper_request, version: c_int) -> hyper_code { | ||||
|         use http::Version; | ||||
|  | ||||
|         *unsafe { &mut *req }.0.version_mut() = match version { | ||||
|         let req = non_null!(&mut *req ?= hyper_code::HYPERE_INVALID_ARG); | ||||
|         *req.0.version_mut() = match version { | ||||
|             super::HYPER_HTTP_VERSION_NONE => Version::HTTP_11, | ||||
|             super::HYPER_HTTP_VERSION_1_0 => Version::HTTP_10, | ||||
|             super::HYPER_HTTP_VERSION_1_1 => Version::HTTP_11, | ||||
| @@ -130,8 +133,9 @@ ffi_fn! { | ||||
|     /// This takes ownership of the `hyper_body *`, you must not use it or | ||||
|     /// free it after setting it on the request. | ||||
|     fn hyper_request_set_body(req: *mut hyper_request, body: *mut hyper_body) -> hyper_code { | ||||
|         let body = unsafe { Box::from_raw(body) }; | ||||
|         *unsafe { &mut *req }.0.body_mut() = body.0; | ||||
|         let body = non_null!(Box::from_raw(body) ?= hyper_code::HYPERE_INVALID_ARG); | ||||
|         let req = non_null!(&mut *req ?= hyper_code::HYPERE_INVALID_ARG); | ||||
|         *req.0.body_mut() = body.0; | ||||
|         hyper_code::HYPERE_OK | ||||
|     } | ||||
| } | ||||
| @@ -157,7 +161,8 @@ ffi_fn! { | ||||
|             func: callback, | ||||
|             data: UserDataPointer(data), | ||||
|         }; | ||||
|         unsafe { &mut *req }.0.extensions_mut().insert(ext); | ||||
|         let req = non_null!(&mut *req ?= hyper_code::HYPERE_INVALID_ARG); | ||||
|         req.0.extensions_mut().insert(ext); | ||||
|         hyper_code::HYPERE_OK | ||||
|     } | ||||
| } | ||||
| @@ -176,7 +181,7 @@ impl hyper_request { | ||||
| ffi_fn! { | ||||
|     /// Free an HTTP response after using it. | ||||
|     fn hyper_response_free(resp: *mut hyper_response) { | ||||
|         drop(unsafe { Box::from_raw(resp) }); | ||||
|         drop(non_null!(Box::from_raw(resp) ?= ())); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -185,7 +190,7 @@ ffi_fn! { | ||||
|     /// | ||||
|     /// It will always be within the range of 100-599. | ||||
|     fn hyper_response_status(resp: *const hyper_response) -> u16 { | ||||
|         unsafe { &*resp }.0.status().as_u16() | ||||
|         non_null!(&*resp ?= 0).0.status().as_u16() | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -200,7 +205,7 @@ ffi_fn! { | ||||
|     /// Use `hyper_response_reason_phrase_len()` to get the length of this | ||||
|     /// buffer. | ||||
|     fn hyper_response_reason_phrase(resp: *const hyper_response) -> *const u8 { | ||||
|         unsafe { &*resp }.reason_phrase().as_ptr() | ||||
|         non_null!(&*resp ?= std::ptr::null()).reason_phrase().as_ptr() | ||||
|     } ?= std::ptr::null() | ||||
| } | ||||
|  | ||||
| @@ -209,7 +214,7 @@ ffi_fn! { | ||||
|     /// | ||||
|     /// Use `hyper_response_reason_phrase()` to get the buffer pointer. | ||||
|     fn hyper_response_reason_phrase_len(resp: *const hyper_response) -> size_t { | ||||
|         unsafe { &*resp }.reason_phrase().len() | ||||
|         non_null!(&*resp ?= 0).reason_phrase().len() | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -226,7 +231,8 @@ ffi_fn! { | ||||
|     /// The buffer is not null-terminated, see the `hyper_buf` functions for | ||||
|     /// getting the bytes and length. | ||||
|     fn hyper_response_headers_raw(resp: *const hyper_response) -> *const hyper_buf { | ||||
|         match unsafe { &*resp }.0.extensions().get::<RawHeaders>() { | ||||
|         let resp = non_null!(&*resp ?= std::ptr::null()); | ||||
|         match resp.0.extensions().get::<RawHeaders>() { | ||||
|             Some(raw) => &raw.0, | ||||
|             None => std::ptr::null(), | ||||
|         } | ||||
| @@ -245,7 +251,7 @@ ffi_fn! { | ||||
|     fn hyper_response_version(resp: *const hyper_response) -> c_int { | ||||
|         use http::Version; | ||||
|  | ||||
|         match unsafe { &*resp }.0.version() { | ||||
|         match non_null!(&*resp ?= 0).0.version() { | ||||
|             Version::HTTP_10 => super::HYPER_HTTP_VERSION_1_0, | ||||
|             Version::HTTP_11 => super::HYPER_HTTP_VERSION_1_1, | ||||
|             Version::HTTP_2 => super::HYPER_HTTP_VERSION_2, | ||||
| @@ -269,7 +275,7 @@ ffi_fn! { | ||||
|     /// | ||||
|     /// It is safe to free the response even after taking ownership of its body. | ||||
|     fn hyper_response_body(resp: *mut hyper_response) -> *mut hyper_body { | ||||
|         let body = std::mem::take(unsafe { &mut *resp }.0.body_mut()); | ||||
|         let body = std::mem::take(non_null!(&mut *resp ?= std::ptr::null_mut()).0.body_mut()); | ||||
|         Box::into_raw(Box::new(hyper_body(body))) | ||||
|     } ?= std::ptr::null_mut() | ||||
| } | ||||
| @@ -331,7 +337,7 @@ ffi_fn! { | ||||
|     /// The callback should return `HYPER_ITER_CONTINUE` to keep iterating, or | ||||
|     /// `HYPER_ITER_BREAK` to stop. | ||||
|     fn hyper_headers_foreach(headers: *const hyper_headers, func: hyper_headers_foreach_callback, userdata: *mut c_void) { | ||||
|         let headers = unsafe { &*headers }; | ||||
|         let headers = non_null!(&*headers ?= ()); | ||||
|         // For each header name/value pair, there may be a value in the casemap | ||||
|         // that corresponds to the HeaderValue. So, we iterator all the keys, | ||||
|         // and for each one, try to pair the originally cased name with the value. | ||||
| @@ -366,7 +372,7 @@ ffi_fn! { | ||||
|     /// | ||||
|     /// This overwrites any previous value set for the header. | ||||
|     fn hyper_headers_set(headers: *mut hyper_headers, name: *const u8, name_len: size_t, value: *const u8, value_len: size_t) -> hyper_code { | ||||
|         let headers = unsafe { &mut *headers }; | ||||
|         let headers = non_null!(&mut *headers ?= hyper_code::HYPERE_INVALID_ARG); | ||||
|         match unsafe { raw_name_value(name, name_len, value, value_len) } { | ||||
|             Ok((name, value, orig_name)) => { | ||||
|                 headers.headers.insert(&name, value); | ||||
| @@ -384,7 +390,7 @@ ffi_fn! { | ||||
|     /// If there were already existing values for the name, this will append the | ||||
|     /// new value to the internal list. | ||||
|     fn hyper_headers_add(headers: *mut hyper_headers, name: *const u8, name_len: size_t, value: *const u8, value_len: size_t) -> hyper_code { | ||||
|         let headers = unsafe { &mut *headers }; | ||||
|         let headers = non_null!(&mut *headers ?= hyper_code::HYPERE_INVALID_ARG); | ||||
|  | ||||
|         match unsafe { raw_name_value(name, name_len, value, value_len) } { | ||||
|             Ok((name, value, orig_name)) => { | ||||
|   | ||||
| @@ -46,7 +46,7 @@ ffi_fn! { | ||||
|     /// This is typically only useful if you aren't going to pass ownership | ||||
|     /// of the IO handle to hyper, such as with `hyper_clientconn_handshake()`. | ||||
|     fn hyper_io_free(io: *mut hyper_io) { | ||||
|         drop(unsafe { Box::from_raw(io) }); | ||||
|         drop(non_null!(Box::from_raw(io) ?= ())); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -55,7 +55,7 @@ ffi_fn! { | ||||
|     /// | ||||
|     /// This value is passed as an argument to the read and write callbacks. | ||||
|     fn hyper_io_set_userdata(io: *mut hyper_io, data: *mut c_void) { | ||||
|         unsafe { &mut *io }.userdata = data; | ||||
|         non_null!(&mut *io ?= ()).userdata = data; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -77,7 +77,7 @@ ffi_fn! { | ||||
|     /// If there is an irrecoverable error reading data, then `HYPER_IO_ERROR` | ||||
|     /// should be the return value. | ||||
|     fn hyper_io_set_read(io: *mut hyper_io, func: hyper_io_read_callback) { | ||||
|         unsafe { &mut *io }.read = func; | ||||
|         non_null!(&mut *io ?= ()).read = func; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -96,7 +96,7 @@ ffi_fn! { | ||||
|     /// If there is an irrecoverable error reading data, then `HYPER_IO_ERROR` | ||||
|     /// should be the return value. | ||||
|     fn hyper_io_set_write(io: *mut hyper_io, func: hyper_io_write_callback) { | ||||
|         unsafe { &mut *io }.write = func; | ||||
|         non_null!(&mut *io ?= ()).write = func; | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -29,3 +29,25 @@ macro_rules! ffi_fn { | ||||
|         ffi_fn!($(#[$doc])* fn $name($($arg: $arg_ty),*) -> () $body); | ||||
|     }; | ||||
| } | ||||
|  | ||||
| macro_rules! non_null { | ||||
|     ($ptr:ident, $eval:expr, $err:expr) => {{ | ||||
|         debug_assert!(!$ptr.is_null(), "{:?} must not be null", stringify!($ptr)); | ||||
|         if $ptr.is_null() { | ||||
|             return $err; | ||||
|         } | ||||
|         unsafe { $eval } | ||||
|     }}; | ||||
|     (&*$ptr:ident ?= $err:expr) => {{ | ||||
|         non_null!($ptr, &*$ptr, $err) | ||||
|     }}; | ||||
|     (&mut *$ptr:ident ?= $err:expr) => {{ | ||||
|         non_null!($ptr, &mut *$ptr, $err) | ||||
|     }}; | ||||
|     (Box::from_raw($ptr:ident) ?= $err:expr) => {{ | ||||
|         non_null!($ptr, Box::from_raw($ptr), $err) | ||||
|     }}; | ||||
|     (Arc::from_raw($ptr:ident) ?= $err:expr) => {{ | ||||
|         non_null!($ptr, Arc::from_raw($ptr), $err) | ||||
|     }}; | ||||
| } | ||||
|   | ||||
| @@ -195,7 +195,7 @@ ffi_fn! { | ||||
| ffi_fn! { | ||||
|     /// Frees an executor and any incomplete tasks still part of it. | ||||
|     fn hyper_executor_free(exec: *const hyper_executor) { | ||||
|         drop(unsafe { Arc::from_raw(exec) }); | ||||
|         drop(non_null!(Arc::from_raw(exec) ?= ())); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -205,11 +205,8 @@ ffi_fn! { | ||||
|     /// The executor takes ownership of the task, it should not be accessed | ||||
|     /// again unless returned back to the user with `hyper_executor_poll`. | ||||
|     fn hyper_executor_push(exec: *const hyper_executor, task: *mut hyper_task) -> hyper_code { | ||||
|         if exec.is_null() || task.is_null() { | ||||
|             return hyper_code::HYPERE_INVALID_ARG; | ||||
|         } | ||||
|         let exec = unsafe { &*exec }; | ||||
|         let task = unsafe { Box::from_raw(task) }; | ||||
|         let exec = non_null!(&*exec ?= hyper_code::HYPERE_INVALID_ARG); | ||||
|         let task = non_null!(Box::from_raw(task) ?= hyper_code::HYPERE_INVALID_ARG); | ||||
|         exec.spawn(task); | ||||
|         hyper_code::HYPERE_OK | ||||
|     } | ||||
| @@ -223,9 +220,7 @@ ffi_fn! { | ||||
|     /// | ||||
|     /// If there are no ready tasks, this returns `NULL`. | ||||
|     fn hyper_executor_poll(exec: *const hyper_executor) -> *mut hyper_task { | ||||
|         // We only want an `&Arc` in here, so wrap in a `ManuallyDrop` so we | ||||
|         // don't accidentally trigger a ref_dec of the Arc. | ||||
|         let exec = unsafe { &*exec }; | ||||
|         let exec = non_null!(&*exec ?= ptr::null_mut()); | ||||
|         match exec.poll_next() { | ||||
|             Some(task) => Box::into_raw(task), | ||||
|             None => ptr::null_mut(), | ||||
| @@ -274,7 +269,7 @@ impl Future for TaskFuture { | ||||
| ffi_fn! { | ||||
|     /// Free a task. | ||||
|     fn hyper_task_free(task: *mut hyper_task) { | ||||
|         drop(unsafe { Box::from_raw(task) }); | ||||
|         drop(non_null!(Box::from_raw(task) ?= ())); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -286,11 +281,7 @@ ffi_fn! { | ||||
|     /// | ||||
|     /// Use `hyper_task_type` to determine the type of the `void *` return value. | ||||
|     fn hyper_task_value(task: *mut hyper_task) -> *mut c_void { | ||||
|         if task.is_null() { | ||||
|             return ptr::null_mut(); | ||||
|         } | ||||
|  | ||||
|         let task = unsafe { &mut *task }; | ||||
|         let task = non_null!(&mut *task ?= ptr::null_mut()); | ||||
|  | ||||
|         if let Some(val) = task.output.take() { | ||||
|             let p = Box::into_raw(val) as *mut c_void; | ||||
| @@ -309,13 +300,9 @@ ffi_fn! { | ||||
| ffi_fn! { | ||||
|     /// Query the return type of this task. | ||||
|     fn hyper_task_type(task: *mut hyper_task) -> hyper_task_return_type { | ||||
|         if task.is_null() { | ||||
|             // instead of blowing up spectacularly, just say this null task | ||||
|             // doesn't have a value to retrieve. | ||||
|             return hyper_task_return_type::HYPER_TASK_EMPTY; | ||||
|         } | ||||
|  | ||||
|         unsafe { &*task }.output_type() | ||||
|         // instead of blowing up spectacularly, just say this null task | ||||
|         // doesn't have a value to retrieve. | ||||
|         non_null!(&*task ?= hyper_task_return_type::HYPER_TASK_EMPTY).output_type() | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -336,11 +323,7 @@ ffi_fn! { | ||||
| ffi_fn! { | ||||
|     /// Retrieve the userdata that has been set via `hyper_task_set_userdata`. | ||||
|     fn hyper_task_userdata(task: *mut hyper_task) -> *mut c_void { | ||||
|         if task.is_null() { | ||||
|             return ptr::null_mut(); | ||||
|         } | ||||
|  | ||||
|         unsafe { &*task }.userdata.0 | ||||
|         non_null!(&*task ?= ptr::null_mut()).userdata.0 | ||||
|     } ?= ptr::null_mut() | ||||
| } | ||||
|  | ||||
| @@ -403,7 +386,7 @@ impl hyper_context<'_> { | ||||
| ffi_fn! { | ||||
|     /// Copies a waker out of the task context. | ||||
|     fn hyper_context_waker(cx: *mut hyper_context<'_>) -> *mut hyper_waker { | ||||
|         let waker = unsafe { &mut *cx }.0.waker().clone(); | ||||
|         let waker = non_null!(&mut *cx ?= ptr::null_mut()).0.waker().clone(); | ||||
|         Box::into_raw(Box::new(hyper_waker { waker })) | ||||
|     } ?= ptr::null_mut() | ||||
| } | ||||
| @@ -413,7 +396,7 @@ ffi_fn! { | ||||
| ffi_fn! { | ||||
|     /// Free a waker that hasn't been woken. | ||||
|     fn hyper_waker_free(waker: *mut hyper_waker) { | ||||
|         drop(unsafe { Box::from_raw(waker) }); | ||||
|         drop(non_null!(Box::from_raw(waker) ?= ())); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -422,7 +405,7 @@ ffi_fn! { | ||||
|     /// | ||||
|     /// NOTE: This consumes the waker. You should not use or free the waker afterwards. | ||||
|     fn hyper_waker_wake(waker: *mut hyper_waker) { | ||||
|         let waker = unsafe { Box::from_raw(waker) }; | ||||
|         let waker = non_null!(Box::from_raw(waker) ?= ()); | ||||
|         waker.waker.wake(); | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user