blob: dfa7d41ba88d35ea8aa53d87769a02e8b10707f6 [file] [log] [blame]
// Copyright 2026 The BoringSSL Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use core::{
ptr::null,
slice::{from_raw_parts, from_raw_parts_mut},
};
/// We follow the convention in [`bssl_crypto::FfiSlice`] by which we signal empty arrays as `null`.
/// An empty Rust slice has a non-zero address value, out of the necessity of enabling pointer-niche
/// optimisation.
#[allow(unused)]
pub(crate) fn slice_into_ffi_raw_parts<T>(slice: &[T]) -> (*const T, usize) {
if slice.is_empty() {
(null(), 0)
} else {
(slice.as_ptr(), slice.len())
}
}
/// Sanitize the data pointer and length and reconstitute the slice.
///
/// This method returns an empty slice if the length is 0 or the pointer is NULL.
/// # Safety
/// Caller must ensure that `'a` outlives `input`.
#[inline]
pub(crate) unsafe fn sanitize_slice<'a, T>(input: *const T, len: usize) -> Option<&'a [T]> {
if len == 0 || input.is_null() {
return Some(&[]);
}
if !input.is_aligned() || len.checked_mul(size_of::<T>())? >= isize::MAX as usize {
return None;
}
unsafe {
// Safety: the pointer and the size has been sanitised.
Some(from_raw_parts(input, len))
}
}
/// Sanitize the data pointer and length and reconstitute the mutable slice.
///
/// `capacity` counts the number of `T`s that `out` can hold, **not number of bytes**.
///
/// This method returns an empty slice if the length is 0 or the pointer is NULL.
/// # Safety
/// Caller must ensure that `'a` outlives `input`.
#[inline]
pub(crate) unsafe fn sanitise_mut_slice<'a, T>(
out: *mut T,
capacity: usize,
) -> Option<&'a mut [T]> {
if capacity == 0 || out.is_null() || !out.is_aligned() {
return Some(&mut []);
}
if capacity.checked_mul(size_of::<T>())? >= isize::MAX as usize {
return None;
}
unsafe {
// Safety: `out` is 1-aligned and `0` is a valid pattern for `u8`.
core::ptr::write_bytes(out, 0, capacity);
Some(from_raw_parts_mut(out, capacity))
}
}