Skip to content
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

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from

Conversation

muzarski
Copy link
Collaborator

Pre-review checklist

  • I have split my patch into logically separate commits.
  • All commit messages clearly explain what they change and why.
  • PR description sums up the changes and reasons why they should be introduced.
  • I have implemented Rust unit tests for the features/changes introduced.
  • I have enabled appropriate tests in .github/workflows/build.yml in gtest_filter.
  • I have enabled appropriate tests in .github/workflows/cassandra.yml in gtest_filter.

Lorak-mmk and others added 6 commits November 26, 2024 16:42
Previously `CassDataType` was just an enum, held inside `Arc`. User was
given a pointer to `CassDataType` using `Arc::as_ptr` or `Arc::into_ptr`.
There are however some functions that mutate the data - and they were
given the very same pointers.
Current code was most likely sound - but I'm not completely sure, Rust
reference is very confusing in this aspect.
It was however very confusing - when a programmer reads or writes
a function that that *mut CassDataType it is not obivious that this data
lies inside Arc and so has shared ownership.

To make this more explicit this commit puts `CassDataType` inside
UnsafeCell. Now each access needs to use `.get_unchecked()` and
`.get_mut_unchecked()` methods and an unsafe block / function, so it
will be easier to spot aliasing ^ mutability problems in the future.

In the future we can use `Arc::get_mut_unchecked()` for this purpose,
but it's not yet stabilised.
Implementation of `PartialEq` for `CassDataType` hides a
possibly unsafe operation. Let's make sure that we do not depend
on it in the code - only use it for test purposes.
Implemented new traits for the types shared between C and Rust.
Adjusted all places where ptr-to-ref (and vice-versa) conversions
appear to use the new traits API.
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_new_from_existing` - 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_new_from_existing` 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants