Skip to content

Introduce CassStr* abstractions#449

Merged
wprzytula merged 3 commits into
scylladb:masterfrom
wprzytula:introduce-cassstr-abstractions
May 21, 2026
Merged

Introduce CassStr* abstractions#449
wprzytula merged 3 commits into
scylladb:masterfrom
wprzytula:introduce-cassstr-abstractions

Conversation

@wprzytula
Copy link
Copy Markdown
Contributor

@wprzytula wprzytula commented May 12, 2026

Fixes: #301
Based on: #448


What's done

This PR introduces FFI abstractions for C string types:

  • CassStrNulTerminated - represents a nul-terminated C string passed by a pointer;
  • CassStrLenDelimited - represents a string slice passed by a pointer, paired with
  • CassStrLen - represents length of CassStrLenDelimited. I decided to make a newtype for this to increase type safety.

All abstractions are repr(transparent), and they appear in FFI functions' signatures. They provide convenient constructors and conversion methods.

What we gain

Type safety

It's now harder to misuse one of string pointer as another.

Borrow checks

Both CassStrNulTerminated and CassStrLenDelimited carry a lifetime, which prevents UAFs.

Self-documenting code

The code is much more explicit and clear in what it does with strings.

The names are a bit verbose, but this is in line with our FFI approach (see long names of CassPtr abstractions, such as CassBorrowedSharedPtr).


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 Makefile in {SCYLLA,CASSANDRA}_(NO_VALGRIND_)TEST_FILTER.
  • I added appropriate Fixes: annotations to PR description.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces CassStr* wrapper types to improve/standardize C-string ↔ Rust &str conversions across the Rust wrapper’s FFI surface, addressing the inability of the previous helpers to distinguish null pointers from invalid UTF-8 (Issue #301). It updates exported APIs and tests to use these abstractions and starts mapping conversion failures to more explicit error paths.

Changes:

  • Add CassStrWithNul, CassStrLenDelimited, CassStrLen, and PtrToStrError abstractions and migrate many FFI functions from raw *const c_char/size_t.
  • Replace ptr_to_cstr(_n) usage with typed conversions, improving error differentiation and propagating failures more intentionally in several call sites.
  • Update integration/unit tests and test utilities to use the new string wrapper APIs.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
scylla-rust-wrapper/src/argconv.rs Introduces CassStr* types and PtrToStrError; updates array-to-string helper.
scylla-rust-wrapper/src/binding.rs Migrates bind-by-name APIs to CassStr* and tightens null/empty/non-UTF8 handling.
scylla-rust-wrapper/src/cass_error.rs Changes cass_error_desc to return CassStrWithNul.
scylla-rust-wrapper/src/cluster.rs Migrates many cluster APIs to CassStr* and updates parsing/validation logic.
scylla-rust-wrapper/src/cql_types/mod.rs Changes string-returning helpers to return CassStrWithNul.
scylla-rust-wrapper/src/cql_types/data_type.rs Migrates type-name/keyspace/class-name setters and related name-based APIs to CassStr*.
scylla-rust-wrapper/src/cql_types/inet.rs Migrates inet-from-string APIs to CassStr*.
scylla-rust-wrapper/src/cql_types/user_type.rs Removes now-unneeded raw c_char import (cleanup during migration).
scylla-rust-wrapper/src/cql_types/uuid.rs Migrates uuid-from-string APIs to CassStr*.
scylla-rust-wrapper/src/exec_profile.rs Migrates exec-profile name parameters to CassStr* with improved error handling.
scylla-rust-wrapper/src/logging.rs Updates log level/file string handling to use CassStrWithNul.
scylla-rust-wrapper/src/metadata.rs Migrates metadata “by name” lookups to CassStr*.
scylla-rust-wrapper/src/query_result.rs Migrates column-by-name lookups to CassStr* and adds null/empty handling tests.
scylla-rust-wrapper/src/runtime.rs Updates runtime tests to use CassStrLenDelimited/CassStrLen.
scylla-rust-wrapper/src/session.rs Migrates connect/prepare APIs to CassStr* and updates unit tests accordingly.
scylla-rust-wrapper/src/ssl.rs Migrates SSL PEM input APIs to CassStr* and adds UTF-8 validation path.
scylla-rust-wrapper/src/statements/prepared.rs Migrates prepared-parameter-by-name APIs to CassStr* with explicit error logging.
scylla-rust-wrapper/src/statements/statement.rs Migrates statement creation/host setting to CassStr* and adds null-pointer binding tests.
scylla-rust-wrapper/src/testing/integration.rs Updates integration stubs to use CassStr* types.
scylla-rust-wrapper/src/testing/utils.rs Updates test helpers/macros to use CassStr* conversions.
scylla-rust-wrapper/tests/integration/consistency.rs Updates integration tests to call APIs with CassStrWithNul/CassStrLen*.
scylla-rust-wrapper/tests/integration/session.rs Updates integration session tests to use CassStrWithNul and new signatures.
scylla-rust-wrapper/tests/integration/utils.rs Removes old pointer helpers and updates error/message formatting to new conversions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scylla-rust-wrapper/src/ssl.rs
Comment thread scylla-rust-wrapper/src/cluster.rs Outdated
Comment thread scylla-rust-wrapper/src/cluster.rs Outdated
Comment thread scylla-rust-wrapper/src/cluster.rs Outdated
Comment thread scylla-rust-wrapper/src/metadata.rs Outdated
Comment thread scylla-rust-wrapper/src/cql_types/data_type.rs Outdated
Comment thread scylla-rust-wrapper/src/cql_types/data_type.rs Outdated
Comment thread scylla-rust-wrapper/src/cql_types/data_type.rs Outdated
Comment thread scylla-rust-wrapper/src/cql_types/data_type.rs Outdated
Comment thread scylla-rust-wrapper/src/cql_types/data_type.rs Outdated
@wprzytula wprzytula force-pushed the introduce-cassstr-abstractions branch from 03c2a77 to 9e8a8cb Compare May 12, 2026 11:34
@wprzytula wprzytula requested a review from Copilot May 12, 2026 11:34
@wprzytula wprzytula changed the title Introduce CassStr* abstractions Introduce CassStr* abstractions May 12, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 4 comments.

Comment thread scylla-rust-wrapper/src/testing/utils.rs Outdated
Comment thread scylla-rust-wrapper/src/testing/utils.rs
Comment thread scylla-rust-wrapper/src/query_result.rs
Comment thread scylla-rust-wrapper/src/query_result.rs Outdated
@wprzytula wprzytula force-pushed the introduce-cassstr-abstractions branch 2 times, most recently from e2b9deb to 928205e Compare May 12, 2026 12:01
@wprzytula wprzytula marked this pull request as ready for review May 12, 2026 12:01
@wprzytula wprzytula requested a review from Copilot May 12, 2026 12:05
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

scylla-rust-wrapper/src/ssl.rs:354

  • cass_ssl_set_private_key_n returns CASS_ERROR_SSL_INVALID_CERT when BIO_new_mem_buf fails, but this is a private-key operation and should return CASS_ERROR_SSL_INVALID_PRIVATE_KEY (consistent with the other error paths in this function).
    if bio.is_null() {
        return CassError::CASS_ERROR_SSL_INVALID_CERT;
    }

@wprzytula wprzytula force-pushed the introduce-cassstr-abstractions branch from 928205e to 5d60286 Compare May 12, 2026 12:37
@wprzytula wprzytula requested a review from Lorak-mmk May 14, 2026 20:07
Comment thread scylla-rust-wrapper/src/argconv.rs Outdated
Comment thread scylla-rust-wrapper/src/argconv.rs
Comment thread scylla-rust-wrapper/src/argconv.rs
Comment thread scylla-rust-wrapper/src/testing/utils.rs
wprzytula added a commit that referenced this pull request May 20, 2026
Fixes: #446
Ref: #301

#446 revealed issues with our handling of NULL string pointers in
user-facing APIs. Together with Claude Opus, I examined vulnerable spots
in the code:
1. Fixed UB in `binding.rs` - variations of the originally reported
issue.
2. Fixed UB/panics in `cass_row_get_column_by_name[_n]` upon null name
provided.
3. Fixed `ptr_to_cstr` to return `None` on NULL pointers instead of UB.
This made behaviour consistent with `ptr_to_cstr_n`.
4. Refactored `ptr_to_cstr[_n]` to return `Result<&'static str,
PtrToStrError>`, with `PtrToStrError` differentiating between null
pointer provided and invalid UTF-8 encoding. Migrated all callers
carefully.

### Further plans

I'm going to address #301 fully soon, by introducing borrowed `CassStr*`
FFI types: #449
Introduce three new FFI string wrapper types to replace raw pointer
usage:

- CassStrWithNul: wraps a CassBorrowedSharedPtr pointing to
  a NUL-terminated string
- CassStrLenDelimited: wraps a CassBorrowedSharedPtr pointing to
  a length-delimited string
- CassStrLen: wraps a size_t representing a string length, used in
  conjunction with CassStrLenDelimited

First two types carry a lifetime parameter tied to the FFI call scope,
preventing use-after-free bugs at compile time. The actual unsafe
dereference is deferred to `to_str()` methods, which validate
non-nullity and UTF-8.

Also introduces PtrToStrError for granular error reporting (null pointer
vs invalid UTF-8 vs empty string).
@wprzytula wprzytula force-pushed the introduce-cassstr-abstractions branch from 5d60286 to 600e750 Compare May 20, 2026 14:29
@wprzytula
Copy link
Copy Markdown
Contributor Author

Rebased on master.

@wprzytula wprzytula force-pushed the introduce-cassstr-abstractions branch from 600e750 to 0c6947d Compare May 20, 2026 14:30
@wprzytula
Copy link
Copy Markdown
Contributor Author

Made the new CassStr* abstractions newtypes over CassBorrowedSharedPtr.

Migrate all FFI function parameters from raw *const c_char / size_t
to the typed CassStrNulTerminated / CassStrLenDelimited wrappers.
Delete the now-unused ptr_to_cstr and ptr_to_cstr_n functions.

There are a lot of changes, but they are mostly mechanical and follow
the same pattern. I reviewed them all after Claude Opus wrote them.
@wprzytula wprzytula force-pushed the introduce-cassstr-abstractions branch from 0c6947d to 6500a24 Compare May 20, 2026 14:41
@wprzytula
Copy link
Copy Markdown
Contributor Author

Deleted the commit that introduced the unsafe blocks in the macros.

`arr_to_cstr` was a badly written helper function, whose only usage was
in the logging callback. It was unsafe, and it was not clear that it was
only safe to use on null-terminated strings. This commit replaces the
use `CassStrNulTerminated`. `arr_to_cstr` is then deleted.
@wprzytula wprzytula requested a review from Lorak-mmk May 20, 2026 16:01
Comment thread scylla-rust-wrapper/src/logging.rs
@wprzytula wprzytula merged commit 4495cd9 into scylladb:master May 21, 2026
9 checks passed
@wprzytula wprzytula deleted the introduce-cassstr-abstractions branch May 21, 2026 05:36
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.

Improve the API for cstring - rust string conversion and vice-versa

3 participants