Fix memory safety problem in CGDataProvider::from_buffer().
The wrapper for that function made no attempt to ensure that the buffer would stay alive, and as a result use-after-free could easily occur. The fix is to require that the buffer be stuffed in an `Arc` box and to teach Core Graphics how to release the `Arc` when it's done with it.
This commit is contained in:
+1
-1
@@ -3,7 +3,7 @@ name = "core-graphics"
|
||||
description = "Bindings to Core Graphics for OS X"
|
||||
homepage = "https://github.com/servo/core-graphics-rs"
|
||||
repository = "https://github.com/servo/core-graphics-rs"
|
||||
version = "0.11.0"
|
||||
version = "0.12.0"
|
||||
authors = ["The Servo Project Developers"]
|
||||
license = "MIT / Apache-2.0"
|
||||
|
||||
|
||||
+16
-7
@@ -11,7 +11,8 @@ use core_foundation::base::{CFRelease, CFRetain, CFTypeID, TCFType};
|
||||
use core_foundation::data::{CFData, CFDataRef};
|
||||
|
||||
use libc::{c_void, size_t, off_t};
|
||||
use std::ptr;
|
||||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
|
||||
@@ -43,13 +44,21 @@ impl CGDataProvider {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_buffer(buffer: &[u8]) -> Self {
|
||||
/// Creates a data provider from the given reference-counted buffer.
|
||||
///
|
||||
/// The `CGDataProvider` object takes ownership of the reference. Once the data provider
|
||||
/// is destroyed, the reference count of the buffer is automatically decremented.
|
||||
pub fn from_buffer(buffer: Arc<Vec<u8>>) -> Self {
|
||||
unsafe {
|
||||
let result = CGDataProviderCreateWithData(ptr::null_mut(),
|
||||
buffer.as_ptr() as *const c_void,
|
||||
buffer.len() as size_t,
|
||||
None);
|
||||
CGDataProvider::from_ptr(result)
|
||||
let ptr = (*buffer).as_ptr() as *const c_void;
|
||||
let len = buffer.len() as size_t;
|
||||
let info = mem::transmute::<Arc<Vec<u8>>, *mut c_void>(buffer);
|
||||
let result = CGDataProviderCreateWithData(info, ptr, len, Some(release));
|
||||
return CGDataProvider::from_ptr(result);
|
||||
}
|
||||
|
||||
unsafe extern "C" fn release(info: *mut c_void, _: *const c_void, _: size_t) {
|
||||
drop(mem::transmute::<*mut c_void, Arc<Vec<u8>>>(info))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user