refactor(cdict): move static initializer error policy to Rust

Keep the private static-CDict initializer in C, but return its native size_t status through the callback boundary. Rust now owns the public success-or-NULL mapping, preserving the original workspace validation, callback order, and private layout ownership while making initializer failures explicit and unit-testable.

Test Plan: ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings; cargo +nightly fmt --manifest-path rust/Cargo.toml --all -- --check; GCC and Clang syntax-only checks; make -j1 -C tests test (all 41 shell tests, fuzzer, zstd tester, and zstream tester passed).
This commit is contained in:
2026-07-20 18:00:09 +02:00
parent bfd61e6ed7
commit 0175fdb408
2 changed files with 37 additions and 26 deletions
+4 -6
View File
@@ -463,7 +463,7 @@ typedef void (*ZSTD_rust_initStaticCDictMoveWorkspace_f)(
void* context, void* cdict); void* context, void* cdict);
typedef void (*ZSTD_rust_initStaticCDictInitialize_f)( typedef void (*ZSTD_rust_initStaticCDictInitialize_f)(
void* context, void* cdict, int useRowMatchFinder); void* context, void* cdict, int useRowMatchFinder);
typedef void* (*ZSTD_rust_initStaticCDictInit_f)( typedef size_t (*ZSTD_rust_initStaticCDictInit_f)(
void* context, void* cdict); void* context, void* cdict);
typedef struct { typedef struct {
void* callbackContext; void* callbackContext;
@@ -7306,16 +7306,14 @@ static void ZSTD_rust_initStaticCDict_initialize(
dictionary->compressionLevel = ZSTD_NO_CLEVEL; dictionary->compressionLevel = ZSTD_NO_CLEVEL;
} }
static void* ZSTD_rust_initStaticCDict_init(void* opaque, void* cdict) static size_t ZSTD_rust_initStaticCDict_init(void* opaque, void* cdict)
{ {
ZSTD_rust_initStaticCDictContext const* const context = ZSTD_rust_initStaticCDictContext const* const context =
(const ZSTD_rust_initStaticCDictContext*)opaque; (const ZSTD_rust_initStaticCDictContext*)opaque;
if (ZSTD_isError( ZSTD_initCDict_internal( return ZSTD_initCDict_internal(
(ZSTD_CDict*)cdict, context->dict, context->dictSize, (ZSTD_CDict*)cdict, context->dict, context->dictSize,
context->dictLoadMethod, context->dictContentType, context->dictLoadMethod, context->dictContentType,
context->params) )) context->params);
return NULL;
return cdict;
} }
const ZSTD_CDict* ZSTD_initStaticCDict( const ZSTD_CDict* ZSTD_initStaticCDict(
+33 -20
View File
@@ -1091,7 +1091,7 @@ type InitStaticCDictCreateWorkspaceFn = unsafe extern "C" fn(*mut c_void);
type InitStaticCDictReserveObjectFn = unsafe extern "C" fn(*mut c_void) -> *mut c_void; type InitStaticCDictReserveObjectFn = unsafe extern "C" fn(*mut c_void) -> *mut c_void;
type InitStaticCDictMoveWorkspaceFn = unsafe extern "C" fn(*mut c_void, *mut c_void); type InitStaticCDictMoveWorkspaceFn = unsafe extern "C" fn(*mut c_void, *mut c_void);
type InitStaticCDictInitializeFn = unsafe extern "C" fn(*mut c_void, *mut c_void, c_int); type InitStaticCDictInitializeFn = unsafe extern "C" fn(*mut c_void, *mut c_void, c_int);
type InitStaticCDictFn = unsafe extern "C" fn(*mut c_void, *mut c_void) -> *mut c_void; type InitStaticCDictFn = unsafe extern "C" fn(*mut c_void, *mut c_void) -> usize;
/// Explicit projection for the public `ZSTD_initStaticCDict` wrapper. /// Explicit projection for the public `ZSTD_initStaticCDict` wrapper.
/// ///
@@ -1130,7 +1130,16 @@ const _: () = {
assert!(size_of::<ZSTD_rust_initStaticCDictState>() == size_of::<[usize; 12]>()); assert!(size_of::<ZSTD_rust_initStaticCDictState>() == size_of::<[usize; 12]>());
}; };
#[inline]
fn static_cdict_init_succeeded(result: usize) -> bool {
!ERR_isError(result)
}
/// Validate static CDict workspace ownership before entering the C leaf. /// Validate static CDict workspace ownership before entering the C leaf.
///
/// The C initializer returns the private `ZSTD_initCDict_internal()` result;
/// Rust owns the public pointer-or-NULL mapping so the C callback remains a
/// layout/configuration operation only.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn ZSTD_rust_initStaticCDict( pub unsafe extern "C" fn ZSTD_rust_initStaticCDict(
state: *const ZSTD_rust_initStaticCDictState, state: *const ZSTD_rust_initStaticCDictState,
@@ -1170,10 +1179,15 @@ pub unsafe extern "C" fn ZSTD_rust_initStaticCDict(
if cdict.is_null() { if cdict.is_null() {
return ptr::null_mut(); return ptr::null_mut();
} }
unsafe { let init_result = unsafe {
(state.move_workspace)(state.callback_context, cdict); (state.move_workspace)(state.callback_context, cdict);
(state.initialize)(state.callback_context, cdict, use_row_match_finder); (state.initialize)(state.callback_context, cdict, use_row_match_finder);
(state.init)(state.callback_context, cdict) (state.init)(state.callback_context, cdict)
};
if static_cdict_init_succeeded(init_result) {
cdict
} else {
ptr::null_mut()
} }
} }
@@ -5205,7 +5219,7 @@ mod tests {
init_cdict: *mut c_void, init_cdict: *mut c_void,
use_row_match_finder: c_int, use_row_match_finder: c_int,
initialized: bool, initialized: bool,
result: *mut c_void, init_result: usize,
} }
unsafe extern "C" fn init_static_cdict_test_create_workspace(context: *mut c_void) { unsafe extern "C" fn init_static_cdict_test_create_workspace(context: *mut c_void) {
@@ -5245,11 +5259,11 @@ mod tests {
unsafe extern "C" fn init_static_cdict_test_init( unsafe extern "C" fn init_static_cdict_test_init(
context: *mut c_void, context: *mut c_void,
cdict: *mut c_void, cdict: *mut c_void,
) -> *mut c_void { ) -> usize {
let probe = unsafe { &mut *context.cast::<InitStaticCDictProbe>() }; let probe = unsafe { &mut *context.cast::<InitStaticCDictProbe>() };
probe.events.push("init"); probe.events.push("init");
probe.init_cdict = cdict; probe.init_cdict = cdict;
probe.result probe.init_result
} }
fn init_static_cdict_test_state( fn init_static_cdict_test_state(
@@ -5308,12 +5322,18 @@ mod tests {
} }
} }
#[test]
fn static_cdict_initializer_maps_error_status_to_null() {
assert!(static_cdict_init_succeeded(0));
assert!(static_cdict_init_succeeded(1));
assert!(!static_cdict_init_succeeded(ERROR(
ZstdErrorCode::MemoryAllocation
)));
}
#[test] #[test]
fn init_static_cdict_rejects_an_unaligned_workspace_before_callback() { fn init_static_cdict_rejects_an_unaligned_workspace_before_callback() {
let mut probe = InitStaticCDictProbe { let mut probe = InitStaticCDictProbe::default();
result: ptr::dangling_mut(),
..Default::default()
};
let mut workspace = [0usize; 2]; let mut workspace = [0usize; 2];
let unaligned_workspace = workspace.as_mut_ptr().cast::<u8>().wrapping_add(1).cast(); let unaligned_workspace = workspace.as_mut_ptr().cast::<u8>().wrapping_add(1).cast();
let c_params = init_static_cdict_test_cparams(); let c_params = init_static_cdict_test_cparams();
@@ -5335,10 +5355,7 @@ mod tests {
#[test] #[test]
fn init_static_cdict_rejects_insufficient_workspace_before_callback() { fn init_static_cdict_rejects_insufficient_workspace_before_callback() {
let mut probe = InitStaticCDictProbe { let mut probe = InitStaticCDictProbe::default();
result: ptr::dangling_mut(),
..Default::default()
};
let mut workspace = [0usize; 1]; let mut workspace = [0usize; 1];
let c_params = init_static_cdict_test_cparams(); let c_params = init_static_cdict_test_cparams();
let state = init_static_cdict_test_state( let state = init_static_cdict_test_state(
@@ -5362,7 +5379,6 @@ mod tests {
let cdict = ptr::dangling_mut::<c_void>(); let cdict = ptr::dangling_mut::<c_void>();
let mut probe = InitStaticCDictProbe { let mut probe = InitStaticCDictProbe {
reserved_cdict: cdict, reserved_cdict: cdict,
result: ptr::dangling_mut(),
..Default::default() ..Default::default()
}; };
let c_params = init_static_cdict_test_cparams(); let c_params = init_static_cdict_test_cparams();
@@ -5379,7 +5395,7 @@ mod tests {
let result = unsafe { ZSTD_rust_initStaticCDict(&state) }; let result = unsafe { ZSTD_rust_initStaticCDict(&state) };
assert_eq!(result, probe.result); assert_eq!(result, cdict);
assert_eq!( assert_eq!(
probe.events, probe.events,
[ [
@@ -5428,7 +5444,7 @@ mod tests {
let cdict = ptr::dangling_mut::<c_void>(); let cdict = ptr::dangling_mut::<c_void>();
let mut probe = InitStaticCDictProbe { let mut probe = InitStaticCDictProbe {
reserved_cdict: cdict, reserved_cdict: cdict,
result: ptr::null_mut(), init_result: ERROR(ZstdErrorCode::MemoryAllocation),
..Default::default() ..Default::default()
}; };
let c_params = init_static_cdict_test_cparams(); let c_params = init_static_cdict_test_cparams();
@@ -5462,10 +5478,7 @@ mod tests {
#[test] #[test]
fn init_static_cdict_rejects_a_null_workspace() { fn init_static_cdict_rejects_a_null_workspace() {
let mut probe = InitStaticCDictProbe { let mut probe = InitStaticCDictProbe::default();
result: ptr::dangling_mut(),
..Default::default()
};
let c_params = init_static_cdict_test_cparams(); let c_params = init_static_cdict_test_cparams();
let state = init_static_cdict_test_state( let state = init_static_cdict_test_state(
&mut probe, &mut probe,