-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
safety: introduce pointer types and their restrictions #208
base: master
Are you sure you want to change the base?
Conversation
f433610
to
9dadad8
Compare
9dadad8
to
7b8bb5a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The approach is very impressive.
I couldn't check all the changes, there were too much of them; I just peeked through them. I trust your meticulousness :)
7b8bb5a
to
e8d2d93
Compare
Rebased on master |
98fbac9
to
aa90f5a
Compare
v1.1: Addressed @wprzytula comments |
Waiting with review for a rebase on #207. |
Everything is up to date |
aa90f5a
to
6c2a061
Compare
v2: Improved pointer API based on @wprzytula suggestions. Thank you!
I still need to think how to address the issue in tests. It's not possible to reuse the pointer, which is not |
You could have an |
6c2a061
to
3686e0d
Compare
Applied the suggestion. At first, I did not understand how is this different from implementing |
3686e0d
to
f341734
Compare
Rebased on master |
f341734
to
8dfff0a
Compare
v2.1: improved docstrings as suggested by @wprzytula |
I've read the first few commits, and it talks about
As far as I can tell it copies the whole object, not Arc, and does not assume it is Arc-allocated. |
Sorry for the confusion. I remember that I made a mistake in some commit message, but forgot to fix it. I meant #[no_mangle]
pub unsafe extern "C" fn cass_data_type_add_sub_type(
data_type: CassSharedPtr<CassDataType>,
sub_data_type: CassSharedPtr<CassDataType>,
) -> CassError {
let data_type = ArcFFI::as_ref(&data_type).unwrap();
match data_type
.get_mut_unchecked()
.add_sub_data_type(ArcFFI::cloned_from_ptr(sub_data_type).unwrap())
{
Ok(()) => CassError::CASS_OK,
Err(e) => e,
}
} |
8dfff0a
to
d4d7b1e
Compare
Pushed fixed commit message ( |
The same mistake is present in |
ec6be4b
to
cf2dcff
Compare
Rebased on master |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not review the whole thing, because I spotted some important issues in argconv.rs. In general, please describe with more detail in precision what guarantees / requirements the types / methods require and provide. Without it it is a bit difficult to reason about the code.
scylla-rust-wrapper/src/metadata.rs
Outdated
view_meta: *const CassMaterializedViewMeta, | ||
) -> *const CassTableMeta { | ||
let view_meta = RefFFI::as_ref(view_meta); | ||
view_meta.base_table.as_ptr() | ||
|
||
match view_meta.base_table.upgrade() { | ||
Some(arc) => RefFFI::as_ptr(&arc), | ||
None => std::ptr::null(), | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible for this upgrade to fail? Or does it indicate a bug in the driver?
If it is possible, can we have a test for that?
scylla-rust-wrapper/src/future.rs
Outdated
impl BoundCallback { | ||
fn invoke(self, fut: &CassFuture) { | ||
fn invoke(self, fut_ptr: *const CassFuture) { | ||
unsafe { | ||
self.cb.unwrap()(fut as *const CassFuture, self.data); | ||
self.cb.unwrap()(fut_ptr, self.data); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this invoke
method be unsafe? It does have a requirement for its argument to be a correct (alingment, lifetime etc) pointer.
scylla-rust-wrapper/src/future.rs
Outdated
pub fn set_callback( | ||
&self, | ||
self_ptr: *const CassFuture, | ||
cb: CassFutureCallback, | ||
data: *mut c_void, | ||
) -> CassError { | ||
let mut lock = self.state.lock().unwrap(); | ||
if lock.callback.is_some() { | ||
// Another callback has been already set |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here self_ptr
should refer to the same CassFuture
as self
, right?
Can you instead make the receiver of this function an arc? self: &Arc<CassFuture>
cf2dcff
to
66b329e
Compare
v3: New
|
bc520d3
to
69d46b3
Compare
Other parts of the code make an assumption, that the pointer representing `CassDataType` was obtained from an Arc allocation. Take for example `cass_data_type_add_sub_type` - it clones an Arc. This is a bug, that was fortunately detected by applying more restrictions on the pointer types (introduced later in this PR).
The same bug as for collection types.
Again, if someone called `cass_data_type_add_sub_type` with a data type obtained from `cass_column_meta_data_type`, it would not be a pointer from an Arc allocation.
Weak::as_ptr() can return an invalid pointer. It can be even dangling (non-null). It's safer to try to upgrade to an Arc. If upgrade was successful, make use of RefFFI API to return a valid pointer. Otherwise, return non-dangling null pointer.
Before this PR, the pointer was obtained from a valid reference &CassFuture, which is totally fine. However, I want to reduce the ways one can obtain such pointer. For ArcFFI (shared pointers), I want them to be obtainable only in two ways: - `ArcFFI::as_ptr()` which accepts an &Arc - from the user, as a function parameter This way, we are guaranteed that the pointer comes from a valid Arc allocation (unless user provided pointer to some garbage, but there is no much we can do about it). If we assume that user provides a pointer returned from some prior call to API, we are guaranteed that it is valid, and comes from an Arc allocation (or is null). I don't want to allow ArcFFI api to create a pointer from a refernce, to prevent creating a pointer, from example from stack allocated object: ``` let future = CassFuture { ... }; let future_ptr = ArcFFI::as_ptr(&future); ``` This commit may not make much sense now, but all should be clear once I introduce traits restricting the pointer types later in this PR.
cpp-driver does not increase the reference count. The lifetime of the iterator is bound to the lifetime of result.
It's more readable (and safe) to have an explicit lifetime instead of lifetime-erased references.
cpp-driver assumes that session object can be prematurely dropped. This means, that we should increase the reference count in functions where we pass the session to an async block. This will prevent UAF. There actually is a test case for this (AsyncTests::Close). However, we cannot enable it yet, since it expects that prematurely dropped session awaits all async tasks and before closing.
It's required to enable the doctests for the crate. I also marked the code snippets from documentation in binding.rs with `text`. They should not be run as doc tests.
This commit introduces a `CassPtr` type, generic over pointer `Properties`. It allows specific pointer-to-reference conversions based on the guarantees provided by the pointer type.
Existing `Ref/Box/Arc`FFIs are adjusted, so they now allow interaction with new pointer type. You can say, that for a user of `argconv` API, new type is opaque. The only way to operate on it is to use the corresponding ffi API.
Disallow implementing two different APIs for specific type.
Rebased on master |
This is a follow-up to: #207.
It defines a
CassPtr
type, wrapper overOption<NonNull<T>>
, generic over the pointerProperties
. Two properties we do care about:It gives us even more guarantees about the pointers. Specifically, it gives us the guarantee about the origin of the pointer - they can only be constructed via
Box/Ref/ArcFFI
APIs. We lacked this guarantee before this PR.Pre-review checklist
[ ] I have enabled appropriate tests in.github/workflows/build.yml
ingtest_filter
.[ ] I have enabled appropriate tests in.github/workflows/cassandra.yml
ingtest_filter
.