From 1904a31860d115fb64758cf4a119208d8e91e4d6 Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Wed, 29 Apr 2026 09:20:44 +0900 Subject: [PATCH 1/7] first version of xz to 0.0.1 --- xz-core/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xz-core/Cargo.toml b/xz-core/Cargo.toml index 1f78f660..7c698057 100644 --- a/xz-core/Cargo.toml +++ b/xz-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "xz-core" -version = "0.1.0" +version = "0.0.1" edition = "2024" license = "MIT OR Apache-2.0" description = "Pure Rust implementation of liblzma (transpiled from C via c2rust)" From 39ba6141c31cca0020906e79bd2dd2593a4ab7bb Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Wed, 29 Apr 2026 18:03:49 +0900 Subject: [PATCH 2/7] Avoid headers for internal xz-core allocations --- xz-core/src/alloc.rs | 4 +- xz-core/src/common/index.rs | 58 +++++++++++++------------ xz-core/src/common/outqueue.rs | 9 +++- xz-core/src/common/stream_decoder_mt.rs | 12 ++--- xz-core/src/common/stream_encoder_mt.rs | 8 ++-- xz-core/src/lz/lz_decoder.rs | 16 +++++-- xz-core/src/lzma/lzma2_decoder.rs | 4 +- xz-core/src/lzma/lzma2_encoder.rs | 2 +- xz-core/src/lzma/lzma_decoder.rs | 9 ++-- xz-core/src/lzma/lzma_encoder.rs | 9 ++-- xz-core/src/simple/simple_coder.rs | 14 ++++-- xz-core/src/types.rs | 1 + 12 files changed, 87 insertions(+), 59 deletions(-) diff --git a/xz-core/src/alloc.rs b/xz-core/src/alloc.rs index 9382fa9f..59f4b7b6 100644 --- a/xz-core/src/alloc.rs +++ b/xz-core/src/alloc.rs @@ -20,6 +20,6 @@ pub use rust::rust_allocator; pub use policy::{lzma_alloc, lzma_alloc_zero, lzma_free}; pub(crate) use policy::{ - internal_alloc_array, internal_alloc_bytes, internal_alloc_object, internal_alloc_zeroed_array, - internal_free, internal_free_array, internal_free_bytes, + internal_alloc_array, internal_alloc_object, internal_alloc_zeroed_array, internal_free, + internal_free_array, internal_free_bytes, }; diff --git a/xz-core/src/common/index.rs b/xz-core/src/common/index.rs index de912b30..7995a471 100644 --- a/xz-core/src/common/index.rs +++ b/xz-core/src/common/index.rs @@ -87,6 +87,23 @@ pub const INDEX_GROUP_SIZE: u32 = 512; pub const PREALLOC_MAX: usize = (SIZE_MAX as usize) .wrapping_sub(core::mem::size_of::()) .wrapping_div(core::mem::size_of::()); +#[inline] +fn index_group_size(records: size_t) -> size_t { + core::mem::size_of::() + records * core::mem::size_of::() +} +unsafe fn index_group_alloc(records: size_t, allocator: *const lzma_allocator) -> *mut index_group { + crate::alloc::internal_alloc_array::(index_group_size(records), allocator) + as *mut index_group +} +unsafe fn index_group_free(g: *mut index_group, allocator: *const lzma_allocator) { + if !g.is_null() { + crate::alloc::internal_free_array( + g as *mut u8, + index_group_size((*g).allocated), + allocator, + ); + } +} unsafe fn index_tree_init(tree: *mut index_tree) { (*tree).root = core::ptr::null_mut(); (*tree).leftmost = core::ptr::null_mut(); @@ -115,8 +132,8 @@ unsafe fn index_tree_end( index_tree_node_end((*tree).root, allocator, free_func); } } -unsafe fn index_node_free(node: *mut c_void, allocator: *const lzma_allocator) { - lzma_free(node, allocator); +unsafe fn index_group_node_free(node: *mut c_void, allocator: *const lzma_allocator) { + index_group_free(node as *mut index_group, allocator); } unsafe fn index_tree_append(tree: *mut index_tree, mut node: *mut index_tree_node) { (*node).parent = (*tree).rightmost; @@ -189,8 +206,7 @@ unsafe fn index_stream_init( block_number_base: lzma_vli, allocator: *const lzma_allocator, ) -> *mut index_stream { - let s: *mut index_stream = - lzma_alloc(core::mem::size_of::(), allocator) as *mut index_stream; + let s: *mut index_stream = crate::alloc::internal_alloc_object::(allocator); if s.is_null() { return core::ptr::null_mut(); } @@ -213,13 +229,12 @@ unsafe fn index_stream_end(node: *mut c_void, allocator: *const lzma_allocator) index_tree_end( ::core::ptr::addr_of_mut!((*s).groups), allocator, - index_node_free as unsafe fn(*mut c_void, *const lzma_allocator) -> (), + index_group_node_free as unsafe fn(*mut c_void, *const lzma_allocator) -> (), ); - lzma_free(s as *mut c_void, allocator); + crate::alloc::internal_free(s, allocator); } unsafe fn index_init_plain(allocator: *const lzma_allocator) -> *mut lzma_index { - let i: *mut lzma_index = - lzma_alloc(core::mem::size_of::(), allocator) as *mut lzma_index; + let i: *mut lzma_index = crate::alloc::internal_alloc_object::(allocator); if !i.is_null() { index_tree_init(::core::ptr::addr_of_mut!((*i).streams)); (*i).uncompressed_size = 0; @@ -238,7 +253,7 @@ pub unsafe fn lzma_index_init(allocator: *const lzma_allocator) -> *mut lzma_ind } let s: *mut index_stream = index_stream_init(0, 0, 1, 0, allocator); if s.is_null() { - lzma_free(i as *mut c_void, allocator); + crate::alloc::internal_free(i, allocator); return core::ptr::null_mut(); } index_tree_append( @@ -254,7 +269,7 @@ pub unsafe fn lzma_index_end(i: *mut lzma_index, allocator: *const lzma_allocato allocator, index_stream_end as unsafe fn(*mut c_void, *const lzma_allocator) -> (), ); - lzma_free(i as *mut c_void, allocator); + crate::alloc::internal_free(i, allocator); } } pub unsafe fn lzma_index_prealloc(i: *mut lzma_index, mut records: lzma_vli) { @@ -481,11 +496,7 @@ pub unsafe fn lzma_index_append( (*g).last += 1; } else { debug_assert!((*i).prealloc > 0); - g = lzma_alloc( - core::mem::size_of::() - + (*i).prealloc * core::mem::size_of::(), - allocator, - ) as *mut index_group; + g = index_group_alloc((*i).prealloc, allocator); if g.is_null() { return LZMA_MEM_ERROR; } @@ -576,11 +587,7 @@ pub unsafe fn lzma_index_cat( let s: *mut index_stream = (*dest).streams.rightmost as *mut index_stream; let g: *mut index_group = (*s).groups.rightmost as *mut index_group; if !g.is_null() && (*g).last + 1 < (*g).allocated { - let newg: *mut index_group = lzma_alloc( - core::mem::size_of::() - + ((*g).last + 1) * core::mem::size_of::(), - allocator, - ) as *mut index_group; + let newg: *mut index_group = index_group_alloc((*g).last + 1, allocator); if newg.is_null() { return LZMA_MEM_ERROR; } @@ -601,7 +608,7 @@ pub unsafe fn lzma_index_cat( (*s).groups.root = ::core::ptr::addr_of_mut!((*newg).node); } (*s).groups.rightmost = ::core::ptr::addr_of_mut!((*newg).node); - lzma_free(g as *mut c_void, allocator); + index_group_free(g, allocator); } (*dest).checks = lzma_index_checks(dest); let info: index_cat_info = index_cat_info { @@ -620,7 +627,7 @@ pub unsafe fn lzma_index_cat( (*dest).record_count += (*src).record_count; (*dest).index_list_size += (*src).index_list_size; (*dest).checks |= (*src).checks; - lzma_free(src as *mut c_void, allocator); + crate::alloc::internal_free(src, allocator); LZMA_OK } unsafe fn index_dup_stream( @@ -647,12 +654,7 @@ unsafe fn index_dup_stream( if (*src).groups.leftmost.is_null() { return dest; } - let destg: *mut index_group = lzma_alloc( - (core::mem::size_of::() as lzma_vli - + (*src).record_count * core::mem::size_of::() as lzma_vli) - as size_t, - allocator, - ) as *mut index_group; + let destg: *mut index_group = index_group_alloc((*src).record_count as size_t, allocator); if destg.is_null() { index_stream_end(dest as *mut c_void, allocator); return core::ptr::null_mut(); diff --git a/xz-core/src/common/outqueue.rs b/xz-core/src/common/outqueue.rs index 50f0f71e..f93a247d 100644 --- a/xz-core/src/common/outqueue.rs +++ b/xz-core/src/common/outqueue.rs @@ -25,7 +25,11 @@ unsafe fn free_one_cached_buffer(outq: *mut lzma_outq, allocator: *const lzma_al (*outq).cache = (*buf).next; (*outq).bufs_allocated -= 1; (*outq).mem_allocated -= lzma_outq_outbuf_memusage((*buf).allocated); - crate::alloc::internal_free_bytes(buf as *mut c_void, allocator); + crate::alloc::internal_free_array( + buf as *mut u8, + lzma_outq_outbuf_memusage((*buf).allocated) as size_t, + allocator, + ); } pub unsafe fn lzma_outq_clear_cache(outq: *mut lzma_outq, allocator: *const lzma_allocator) { while !(*outq).cache.is_null() { @@ -85,7 +89,8 @@ pub unsafe fn lzma_outq_prealloc_buf( } let alloc_size: size_t = lzma_outq_outbuf_memusage(size) as size_t; lzma_outq_clear_cache(outq, allocator); - (*outq).cache = crate::alloc::internal_alloc_bytes(alloc_size, allocator) as *mut lzma_outbuf; + (*outq).cache = + crate::alloc::internal_alloc_array::(alloc_size, allocator) as *mut lzma_outbuf; if (*outq).cache.is_null() { return LZMA_MEM_ERROR; } diff --git a/xz-core/src/common/stream_decoder_mt.rs b/xz-core/src/common/stream_decoder_mt.rs index 8af725c2..615cb0a1 100644 --- a/xz-core/src/common/stream_decoder_mt.rs +++ b/xz-core/src/common/stream_decoder_mt.rs @@ -153,8 +153,9 @@ unsafe extern "C" fn worker_decoder(thr_ptr: *mut c_void) -> *mut c_void { } else { if (*thr).state == THR_EXIT { mythread_mutex_unlock(::core::ptr::addr_of_mut!((*thr).mutex)); - crate::alloc::internal_free_bytes( - (*thr).in_0 as *mut c_void, + crate::alloc::internal_free_array( + (*thr).in_0, + (*thr).in_size, worker_allocator(thr), ); lzma_next_end( @@ -244,8 +245,9 @@ unsafe extern "C" fn worker_decoder(thr_ptr: *mut c_void) -> *mut c_void { mythread_i_434 = 1; } if ret == LZMA_STREAM_END { - crate::alloc::internal_free_bytes( - (*thr).in_0 as *mut c_void, + crate::alloc::internal_free_array( + (*thr).in_0, + (*thr).in_size, worker_allocator(thr), ); (*thr).in_0 = core::ptr::null_mut(); @@ -817,7 +819,7 @@ unsafe fn stream_decode_mt_thread_init( } (*(*coder).thr).in_size = (*coder).mem_next_in as size_t; (*(*coder).thr).in_0 = - crate::alloc::internal_alloc_bytes((*(*coder).thr).in_size, allocator) as *mut u8; + crate::alloc::internal_alloc_array::((*(*coder).thr).in_size, allocator); if (*(*coder).thr).in_0.is_null() { threads_stop(coder); return Some(LZMA_MEM_ERROR); diff --git a/xz-core/src/common/stream_encoder_mt.rs b/xz-core/src/common/stream_encoder_mt.rs index db027ac9..0ac7552c 100644 --- a/xz-core/src/common/stream_encoder_mt.rs +++ b/xz-core/src/common/stream_encoder_mt.rs @@ -8,6 +8,7 @@ pub type worker_thread = worker_thread_s; pub struct worker_thread_s { pub state: worker_state, pub in_0: *mut u8, + pub in_alloc_size: size_t, pub in_size: size_t, pub outbuf: *mut lzma_outbuf, pub coder: *mut lzma_stream_coder, @@ -380,7 +381,7 @@ unsafe extern "C" fn worker_start(thr_ptr: *mut c_void) -> *mut c_void { ::core::ptr::addr_of_mut!((*thr).block_encoder), worker_allocator(thr), ); - crate::alloc::internal_free_bytes((*thr).in_0 as *mut c_void, worker_allocator(thr)); + crate::alloc::internal_free_array((*thr).in_0, (*thr).in_alloc_size, worker_allocator(thr)); MYTHREAD_RET_VALUE } unsafe fn threads_stop(coder: *mut lzma_stream_coder, wait_for_threads: bool) { @@ -487,10 +488,11 @@ unsafe fn initialize_new_thread( .threads .offset((*coder).threads_initialized as isize) as *mut worker_thread; - (*thr).in_0 = crate::alloc::internal_alloc_bytes((*coder).block_size, allocator) as *mut u8; + (*thr).in_0 = crate::alloc::internal_alloc_array::((*coder).block_size, allocator); if (*thr).in_0.is_null() { return LZMA_MEM_ERROR; } + (*thr).in_alloc_size = (*coder).block_size; if mythread_mutex_init(::core::ptr::addr_of_mut!((*thr).mutex)) == 0 { if mythread_cond_init(::core::ptr::addr_of_mut!((*thr).cond)) == 0 { (*thr).state = THR_IDLE; @@ -526,7 +528,7 @@ unsafe fn initialize_new_thread( } mythread_mutex_destroy(::core::ptr::addr_of_mut!((*thr).mutex)); } - crate::alloc::internal_free_bytes((*thr).in_0 as *mut c_void, allocator); + crate::alloc::internal_free_array((*thr).in_0, (*thr).in_alloc_size, allocator); LZMA_MEM_ERROR } unsafe fn get_thread(coder: *mut lzma_stream_coder, allocator: *const lzma_allocator) -> lzma_ret { diff --git a/xz-core/src/lz/lz_decoder.rs b/xz-core/src/lz/lz_decoder.rs index 86dbaf42..029c1e09 100644 --- a/xz-core/src/lz/lz_decoder.rs +++ b/xz-core/src/lz/lz_decoder.rs @@ -166,7 +166,11 @@ unsafe fn lz_decode( unsafe fn lz_decoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { let coder: *mut lzma_coder = coder_ptr as *mut lzma_coder; lzma_next_end(::core::ptr::addr_of_mut!((*coder).next), allocator); - crate::alloc::internal_free_bytes((*coder).dict.buf as *mut c_void, allocator); + crate::alloc::internal_free_array( + (*coder).dict.buf, + (*coder).dict.size.wrapping_add(LZ_DICT_EXTRA as size_t), + allocator, + ); if let Some(end) = (*coder).lz.end { end((*coder).lz.coder, allocator); } else { @@ -258,11 +262,15 @@ pub unsafe fn lzma_lz_decoder_init( .dict_size .wrapping_add((2 * LZ_DICT_REPEAT_MAX) as size_t); if (*coder).dict.size != alloc_size { - crate::alloc::internal_free_bytes((*coder).dict.buf as *mut c_void, allocator); - (*coder).dict.buf = crate::alloc::internal_alloc_bytes( + crate::alloc::internal_free_array( + (*coder).dict.buf, + (*coder).dict.size.wrapping_add(LZ_DICT_EXTRA as size_t), + allocator, + ); + (*coder).dict.buf = crate::alloc::internal_alloc_array::( alloc_size.wrapping_add(LZ_DICT_EXTRA as size_t), allocator, - ) as *mut u8; + ); if (*coder).dict.buf.is_null() { return LZMA_MEM_ERROR; } diff --git a/xz-core/src/lzma/lzma2_decoder.rs b/xz-core/src/lzma/lzma2_decoder.rs index 83a1ab8b..20f0716e 100644 --- a/xz-core/src/lzma/lzma2_decoder.rs +++ b/xz-core/src/lzma/lzma2_decoder.rs @@ -1,5 +1,5 @@ use crate::lz::lz_decoder::{lzma_lz_decoder_init, lzma_lz_options}; -use crate::lzma::lzma_decoder::lzma_lzma_decoder_create; +use crate::lzma::lzma_decoder::{lzma_lzma_decoder_create, lzma_lzma1_decoder}; use crate::types::*; #[derive(Copy, Clone)] #[repr(C)] @@ -195,7 +195,7 @@ unsafe fn lzma2_decode( } unsafe fn lzma2_decoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { let coder: *mut lzma_lzma2_coder = coder_ptr as *mut lzma_lzma2_coder; - crate::alloc::internal_free_bytes((*coder).lzma.coder, allocator); + crate::alloc::internal_free((*coder).lzma.coder as *mut lzma_lzma1_decoder, allocator); crate::alloc::internal_free(coder, allocator); } unsafe fn lzma2_decoder_init( diff --git a/xz-core/src/lzma/lzma2_encoder.rs b/xz-core/src/lzma/lzma2_encoder.rs index 6eb03e24..383b33f1 100644 --- a/xz-core/src/lzma/lzma2_encoder.rs +++ b/xz-core/src/lzma/lzma2_encoder.rs @@ -222,7 +222,7 @@ unsafe fn lzma2_encode( } unsafe fn lzma2_encoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { let coder: *mut lzma_lzma2_coder = coder_ptr as *mut lzma_lzma2_coder; - crate::alloc::internal_free_bytes((*coder).lzma, allocator); + crate::alloc::internal_free((*coder).lzma as *mut lzma_lzma1_encoder, allocator); crate::alloc::internal_free(coder, allocator); } unsafe fn lzma2_encoder_options_update( diff --git a/xz-core/src/lzma/lzma_decoder.rs b/xz-core/src/lzma/lzma_decoder.rs index 3f193fb9..dec2ca91 100644 --- a/xz-core/src/lzma/lzma_decoder.rs +++ b/xz-core/src/lzma/lzma_decoder.rs @@ -2368,10 +2368,7 @@ pub unsafe fn lzma_lzma_decoder_create( lz_options: *mut lzma_lz_options, ) -> lzma_ret { if (*lz).coder.is_null() { - (*lz).coder = crate::alloc::internal_alloc_bytes( - core::mem::size_of::() as size_t, - allocator, - ); + (*lz).coder = crate::alloc::internal_alloc_object::(allocator).cast(); if (*lz).coder.is_null() { return LZMA_MEM_ERROR; } @@ -2385,6 +2382,9 @@ pub unsafe fn lzma_lzma_decoder_create( (*lz_options).preset_dict_size = (*options).preset_dict_size as size_t; LZMA_OK } +unsafe fn lzma_decoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { + crate::alloc::internal_free(coder_ptr as *mut lzma_lzma1_decoder, allocator); +} unsafe fn lzma_decoder_init( lz: *mut lzma_lz_decoder, allocator: *const lzma_allocator, @@ -2416,6 +2416,7 @@ unsafe fn lzma_decoder_init( if ret != LZMA_OK { return ret; } + (*lz).end = Some(lzma_decoder_end as unsafe fn(*mut c_void, *const lzma_allocator) -> ()); lzma_decoder_reset((*lz).coder, options); lzma_decoder_uncompressed((*lz).coder, uncomp_size, allow_eopm); LZMA_OK diff --git a/xz-core/src/lzma/lzma_encoder.rs b/xz-core/src/lzma/lzma_encoder.rs index e49c1c7e..1cd37011 100644 --- a/xz-core/src/lzma/lzma_encoder.rs +++ b/xz-core/src/lzma/lzma_encoder.rs @@ -1038,10 +1038,7 @@ pub unsafe fn lzma_lzma_encoder_create( lz_options: *mut lzma_lz_options, ) -> lzma_ret { if (*coder_ptr).is_null() { - *coder_ptr = crate::alloc::internal_alloc_bytes( - core::mem::size_of::() as size_t, - allocator, - ); + *coder_ptr = crate::alloc::internal_alloc_object::(allocator).cast(); if (*coder_ptr).is_null() { return LZMA_MEM_ERROR; } @@ -1086,6 +1083,9 @@ pub unsafe fn lzma_lzma_encoder_create( set_lz_options(lz_options, options); lzma_lzma_encoder_reset(coder, options) } +unsafe fn lzma_encoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { + crate::alloc::internal_free(coder_ptr as *mut lzma_lzma1_encoder, allocator); +} unsafe fn lzma_encoder_init( lz: *mut lzma_lz_encoder, allocator: *const lzma_allocator, @@ -1097,6 +1097,7 @@ unsafe fn lzma_encoder_init( return LZMA_PROG_ERROR; } (*lz).code = lzma_encode as lzma_lz_encoder_code_function; + (*lz).end = Some(lzma_encoder_end as unsafe fn(*mut c_void, *const lzma_allocator) -> ()); (*lz).set_out_limit = Some(lzma_lzma_set_out_limit as unsafe fn(*mut c_void, *mut u64, u64) -> lzma_ret); lzma_lzma_encoder_create( diff --git a/xz-core/src/simple/simple_coder.rs b/xz-core/src/simple/simple_coder.rs index 9d41d96a..f96d5750 100644 --- a/xz-core/src/simple/simple_coder.rs +++ b/xz-core/src/simple/simple_coder.rs @@ -175,8 +175,12 @@ unsafe fn simple_code( unsafe fn simple_coder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { let coder: *mut lzma_simple_coder = coder_ptr as *mut lzma_simple_coder; lzma_next_end(::core::ptr::addr_of_mut!((*coder).next), allocator); - crate::alloc::internal_free_bytes((*coder).simple, allocator); - crate::alloc::internal_free_bytes(coder as *mut c_void, allocator); + crate::alloc::internal_free_array((*coder).simple as *mut u8, (*coder).simple_size, allocator); + crate::alloc::internal_free_array( + coder as *mut u8, + core::mem::size_of::() + (*coder).allocated, + allocator, + ); } unsafe fn simple_coder_update( coder_ptr: *mut c_void, @@ -203,7 +207,7 @@ pub(crate) unsafe fn lzma_simple_coder_init( ) -> lzma_ret { let mut coder: *mut lzma_simple_coder = (*next).coder as *mut lzma_simple_coder; if coder.is_null() { - coder = crate::alloc::internal_alloc_bytes( + coder = crate::alloc::internal_alloc_array::( core::mem::size_of::() + 2 * unfiltered_max, allocator, ) as *mut lzma_simple_coder; @@ -249,8 +253,10 @@ pub(crate) unsafe fn lzma_simple_coder_init( }; (*coder).filter = filter; (*coder).allocated = 2 * unfiltered_max; + (*coder).simple_size = simple_size; if simple_size > 0 { - (*coder).simple = crate::alloc::internal_alloc_bytes(simple_size, allocator); + (*coder).simple = + crate::alloc::internal_alloc_array::(simple_size, allocator) as *mut c_void; if (*coder).simple.is_null() { return LZMA_MEM_ERROR; } diff --git a/xz-core/src/types.rs b/xz-core/src/types.rs index 5b23bf38..e40620ab 100644 --- a/xz-core/src/types.rs +++ b/xz-core/src/types.rs @@ -829,6 +829,7 @@ pub(crate) struct lzma_simple_coder { pub(crate) is_encoder: bool, pub(crate) filter: lzma_simple_filter_function, pub(crate) simple: *mut c_void, + pub(crate) simple_size: size_t, pub(crate) now_pos: u32, pub(crate) allocated: size_t, pub(crate) pos: size_t, From 3da4fc3887463fda72b64581f4d166393b13b007 Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Sat, 2 May 2026 21:40:07 +0900 Subject: [PATCH 3/7] Fix supported_action_slot index type for MSVC lzma_action is c_int on MSVC and c_uint elsewhere, so the u32 parameter type rejected lzma_action constants on MSVC. Take lzma_action directly. --- xz-core/src/common/filter_encoder.rs | 2 +- xz-core/src/common/stream_encoder.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xz-core/src/common/filter_encoder.rs b/xz-core/src/common/filter_encoder.rs index 5d81b454..cb7c5bc9 100644 --- a/xz-core/src/common/filter_encoder.rs +++ b/xz-core/src/common/filter_encoder.rs @@ -261,7 +261,7 @@ unsafe fn reversed_filter_slot(filters: *mut [lzma_filter; 5], index: usize) -> (filters as *mut lzma_filter).add(index) } #[inline(always)] -unsafe fn supported_action_slot(actions: *mut bool, index: u32) -> *mut bool { +unsafe fn supported_action_slot(actions: *mut bool, index: lzma_action) -> *mut bool { debug_assert!((index as usize) < 5); actions.add(index as usize) } diff --git a/xz-core/src/common/stream_encoder.rs b/xz-core/src/common/stream_encoder.rs index 68b0fcfd..55c6e205 100644 --- a/xz-core/src/common/stream_encoder.rs +++ b/xz-core/src/common/stream_encoder.rs @@ -15,7 +15,7 @@ pub struct lzma_stream_coder { pub buffer: [u8; LZMA_BLOCK_HEADER_SIZE_MAX as usize], } #[inline(always)] -unsafe fn supported_action_slot(actions: *mut bool, index: u32) -> *mut bool { +unsafe fn supported_action_slot(actions: *mut bool, index: lzma_action) -> *mut bool { debug_assert!((index as usize) < 5); actions.add(index as usize) } From 95fb95e66cffa10121e1adad9585a60bffa56e0d Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Sat, 2 May 2026 23:49:54 +0900 Subject: [PATCH 4/7] Remove non-upstream simple_size field --- xz-core/src/alloc.rs | 7 ++- xz-core/src/alloc/custom.rs | 44 ++++++++++++++- xz-core/src/common/common.rs | 7 ++- xz-core/src/common/filter_common.rs | 40 +++++++++++++- xz-core/src/common/index_hash.rs | 5 +- xz-core/src/common/stream_decoder.rs | 2 +- xz-core/src/common/stream_encoder.rs | 2 +- xz-core/src/common/string_conversion.rs | 26 ++++++--- xz-core/src/delta/delta_decoder.rs | 3 +- xz-core/src/lz/lz_decoder.rs | 5 +- xz-core/src/lz/lz_encoder.rs | 5 +- xz-core/src/lzma/lzma2_decoder.rs | 2 +- xz-core/src/lzma/lzma_decoder.rs | 4 +- xz-core/src/raw_alloc.rs | 73 ++++++++++++++++++++++++- xz-core/src/simple/simple_coder.rs | 6 +- xz-core/src/simple/simple_decoder.rs | 4 +- xz-core/src/types.rs | 7 ++- 17 files changed, 199 insertions(+), 43 deletions(-) diff --git a/xz-core/src/alloc.rs b/xz-core/src/alloc.rs index 59f4b7b6..a7095199 100644 --- a/xz-core/src/alloc.rs +++ b/xz-core/src/alloc.rs @@ -17,9 +17,12 @@ pub use custom::allocator_or_c; #[cfg(feature = "custom_allocator")] pub use rust::rust_allocator; +#[cfg(feature = "custom_allocator")] pub use policy::{lzma_alloc, lzma_alloc_zero, lzma_free}; pub(crate) use policy::{ - internal_alloc_array, internal_alloc_object, internal_alloc_zeroed_array, internal_free, - internal_free_array, internal_free_bytes, + internal_alloc_array, internal_alloc_bytes, internal_alloc_object, + internal_alloc_untyped_bytes, internal_alloc_zeroed_array, internal_alloc_zeroed_bytes, + internal_free, internal_free_array, internal_free_bytes, internal_free_untyped, + internal_free_untyped_bytes, }; diff --git a/xz-core/src/alloc/custom.rs b/xz-core/src/alloc/custom.rs index 5afabd7f..519b7a89 100644 --- a/xz-core/src/alloc/custom.rs +++ b/xz-core/src/alloc/custom.rs @@ -70,6 +70,29 @@ pub(crate) unsafe fn internal_alloc_bytes( alloc_impl(size as usize, RUST_ALLOC_ALIGN, false) } +pub(crate) unsafe fn internal_alloc_untyped_bytes( + size: size_t, + allocator: *const lzma_allocator, +) -> *mut c_void { + unsafe { internal_alloc_bytes(size, allocator) } +} + +pub(crate) unsafe fn internal_alloc_zeroed_bytes( + size: size_t, + allocator: *const lzma_allocator, +) -> *mut c_void { + let size = c_size(size); + let allocator = allocator_or_rust(allocator); + if let Some(alloc) = unsafe { (*allocator).alloc } { + let ptr = unsafe { alloc((*allocator).opaque, 1, size) }; + if !ptr.is_null() { + unsafe { core::ptr::write_bytes(ptr.cast::(), 0, size) }; + } + return ptr; + } + alloc_impl(size as usize, RUST_ALLOC_ALIGN, true) +} + pub(crate) unsafe fn internal_alloc_object(allocator: *const lzma_allocator) -> *mut T { if !allocator.is_null() && let Some(alloc) = unsafe { (*allocator).alloc } @@ -115,7 +138,11 @@ pub(crate) unsafe fn internal_alloc_zeroed_array( alloc_impl(size, core::mem::align_of::(), true) as *mut T } -pub(crate) unsafe fn internal_free_bytes(ptr: *mut c_void, allocator: *const lzma_allocator) { +pub(crate) unsafe fn internal_free_bytes( + ptr: *mut c_void, + _size: size_t, + allocator: *const lzma_allocator, +) { if !allocator.is_null() && let Some(free) = unsafe { (*allocator).free } { @@ -125,8 +152,19 @@ pub(crate) unsafe fn internal_free_bytes(ptr: *mut c_void, allocator: *const lzm unsafe { free_ptr(ptr) }; } +pub(crate) unsafe fn internal_free_untyped(ptr: *mut c_void, allocator: *const lzma_allocator) { + unsafe { lzma_free(ptr, allocator) }; +} + +pub(crate) unsafe fn internal_free_untyped_bytes( + ptr: *mut c_void, + allocator: *const lzma_allocator, +) { + unsafe { lzma_free(ptr, allocator) }; +} + pub(crate) unsafe fn internal_free(ptr: *mut T, allocator: *const lzma_allocator) { - unsafe { internal_free_bytes(ptr.cast(), allocator) }; + unsafe { internal_free_bytes(ptr.cast(), 0, allocator) }; } pub(crate) unsafe fn internal_free_array( @@ -134,5 +172,5 @@ pub(crate) unsafe fn internal_free_array( _count: size_t, allocator: *const lzma_allocator, ) { - unsafe { internal_free_bytes(ptr.cast(), allocator) }; + unsafe { internal_free_bytes(ptr.cast(), 0, allocator) }; } diff --git a/xz-core/src/common/common.rs b/xz-core/src/common/common.rs index 86e8ff7c..e152d4d5 100644 --- a/xz-core/src/common/common.rs +++ b/xz-core/src/common/common.rs @@ -1,3 +1,4 @@ +#[cfg(feature = "custom_allocator")] pub use crate::alloc::{lzma_alloc, lzma_alloc_zero, lzma_free}; use crate::types::*; pub const LZMA_VERSION_MAJOR: u32 = 5; @@ -31,7 +32,7 @@ pub unsafe fn lzma_stream_allocator(strm: *const lzma_stream) -> *const lzma_all #[inline] pub unsafe fn lzma_alloc_object(allocator: *const lzma_allocator) -> *mut T { debug_assert!(core::mem::align_of::() <= 16); - lzma_alloc(core::mem::size_of::() as size_t, allocator) as *mut T + crate::alloc::internal_alloc_object::(allocator) } pub unsafe fn lzma_bufcpy( input: *const u8, @@ -113,7 +114,7 @@ pub unsafe fn lzma_next_end(next: *mut lzma_next_coder, allocator: *const lzma_a if let Some(end) = (*next).end { end((*next).coder, allocator); } else { - lzma_free((*next).coder, allocator); + crate::alloc::internal_free_untyped((*next).coder, allocator); } *next = lzma_next_coder_s { coder: core::ptr::null_mut(), @@ -297,7 +298,7 @@ pub unsafe fn lzma_end(strm: *mut lzma_stream) { ::core::ptr::addr_of_mut!((*(*strm).internal).next), lzma_stream_allocator(strm), ); - lzma_free((*strm).internal as *mut c_void, lzma_stream_allocator(strm)); + crate::alloc::internal_free((*strm).internal, lzma_stream_allocator(strm)); (*strm).internal = core::ptr::null_mut(); } } diff --git a/xz-core/src/common/filter_common.rs b/xz-core/src/common/filter_common.rs index e6eb6279..44dc5bb2 100644 --- a/xz-core/src/common/filter_common.rs +++ b/xz-core/src/common/filter_common.rs @@ -101,6 +101,37 @@ static FEATURES: [filter_features; 13] = [ changes_size: false, }, ]; + +fn filter_options_size(id: lzma_vli) -> Option { + let mut i: usize = 0; + while i < FEATURES.len() { + if FEATURES[i].id == id { + return Some(FEATURES[i].options_size); + } + if FEATURES[i].id == LZMA_VLI_UNKNOWN { + break; + } + i += 1; + } + None +} + +pub(crate) unsafe fn lzma_filter_options_free( + filter: lzma_filter, + allocator: *const lzma_allocator, +) { + if filter.options.is_null() { + return; + } + if let Some(size) = filter_options_size(filter.id) { + crate::alloc::internal_free_bytes(filter.options, size, allocator); + } else { + debug_assert!(false, "unknown filter options size"); + #[cfg(feature = "custom_allocator")] + lzma_free(filter.options, allocator); + } +} + pub unsafe fn lzma_filters_copy( src: *const lzma_filter, real_dest: *mut lzma_filter, @@ -138,7 +169,10 @@ pub unsafe fn lzma_filters_copy( j += 1; } } - dest[i as usize].options = lzma_alloc(FEATURES[j as usize].options_size, allocator); + dest[i as usize].options = crate::alloc::internal_alloc_bytes( + FEATURES[j as usize].options_size, + allocator, + ); if dest[i as usize].options.is_null() { ret = LZMA_MEM_ERROR; break 's_15; @@ -156,7 +190,7 @@ pub unsafe fn lzma_filters_copy( if ret != LZMA_OK { while i > 0 { i -= 1; - lzma_free(dest[i as usize].options, allocator); + lzma_filter_options_free(dest[i as usize], allocator); } return ret; } @@ -178,7 +212,7 @@ pub unsafe fn lzma_filters_free(filters: *mut lzma_filter, allocator: *const lzm if i == LZMA_FILTERS_MAX as size_t { break; } - lzma_free((*filters.offset(i as isize)).options, allocator); + lzma_filter_options_free(*filters.offset(i as isize), allocator); (*filters.offset(i as isize)).options = core::ptr::null_mut(); (*filters.offset(i as isize)).id = LZMA_VLI_UNKNOWN; i += 1; diff --git a/xz-core/src/common/index_hash.rs b/xz-core/src/common/index_hash.rs index 29965817..a08866cb 100644 --- a/xz-core/src/common/index_hash.rs +++ b/xz-core/src/common/index_hash.rs @@ -45,8 +45,7 @@ pub unsafe fn lzma_index_hash_init( allocator: *const lzma_allocator, ) -> *mut lzma_index_hash { if index_hash.is_null() { - index_hash = - lzma_alloc(core::mem::size_of::(), allocator) as *mut lzma_index_hash; + index_hash = crate::alloc::internal_alloc_object::(allocator); if index_hash.is_null() { return core::ptr::null_mut(); } @@ -78,7 +77,7 @@ pub unsafe fn lzma_index_hash_end( index_hash: *mut lzma_index_hash, allocator: *const lzma_allocator, ) { - lzma_free(index_hash as *mut c_void, allocator); + crate::alloc::internal_free(index_hash, allocator); } pub fn lzma_index_hash_size(index_hash: *const lzma_index_hash) -> lzma_vli { unsafe { diff --git a/xz-core/src/common/stream_decoder.rs b/xz-core/src/common/stream_decoder.rs index 778a5cc9..b51d6e5a 100644 --- a/xz-core/src/common/stream_decoder.rs +++ b/xz-core/src/common/stream_decoder.rs @@ -286,7 +286,7 @@ unsafe fn stream_decoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allo let coder: *mut lzma_stream_coder = coder_ptr as *mut lzma_stream_coder; lzma_next_end(::core::ptr::addr_of_mut!((*coder).block_decoder), allocator); lzma_index_hash_end((*coder).index_hash, allocator); - crate::common::common::lzma_free(coder as *mut c_void, allocator); + crate::alloc::internal_free(coder, allocator); } unsafe fn stream_decoder_get_check(coder_ptr: *const c_void) -> lzma_check { let coder: *const lzma_stream_coder = coder_ptr as *const lzma_stream_coder; diff --git a/xz-core/src/common/stream_encoder.rs b/xz-core/src/common/stream_encoder.rs index 55c6e205..0548ff90 100644 --- a/xz-core/src/common/stream_encoder.rs +++ b/xz-core/src/common/stream_encoder.rs @@ -200,7 +200,7 @@ unsafe fn stream_encoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allo ::core::ptr::addr_of_mut!((*coder).filters) as *mut lzma_filter, allocator, ); - crate::common::common::lzma_free(coder as *mut c_void, allocator); + crate::alloc::internal_free(coder, allocator); } #[inline(always)] unsafe fn stream_encoder_update_before_block( diff --git a/xz-core/src/common/string_conversion.rs b/xz-core/src/common/string_conversion.rs index df738a79..2516f5e4 100644 --- a/xz-core/src/common/string_conversion.rs +++ b/xz-core/src/common/string_conversion.rs @@ -1,4 +1,4 @@ -use crate::common::filter_common::lzma_validate_chain; +use crate::common::filter_common::{lzma_filter_options_free, lzma_validate_chain}; use crate::types::*; #[derive(Copy, Clone)] #[repr(C)] @@ -76,6 +76,7 @@ pub const LZMA_LCLP_MIN: u32 = 0; pub const LZMA_PB_MIN: u32 = 0; pub const LZMA_PRESET_DEFAULT: c_uint = 6; pub const STR_ALLOC_SIZE: u32 = 800; +#[cfg(feature = "custom_allocator")] unsafe fn str_init(str: *mut lzma_str, allocator: *const lzma_allocator) -> lzma_ret { (*str).buf = lzma_alloc(STR_ALLOC_SIZE as size_t, allocator) as *mut c_char; if (*str).buf.is_null() { @@ -84,12 +85,14 @@ unsafe fn str_init(str: *mut lzma_str, allocator: *const lzma_allocator) -> lzma (*str).pos = 0; LZMA_OK } +#[cfg(feature = "custom_allocator")] unsafe fn str_free(str: *mut lzma_str, allocator: *const lzma_allocator) { lzma_free((*str).buf as *mut c_void, allocator); } unsafe fn str_is_full(str: *const lzma_str) -> bool { (*str).pos == (STR_ALLOC_SIZE - 1) as size_t } +#[cfg(feature = "custom_allocator")] unsafe fn str_finish( dest: *mut *mut c_char, str: *mut lzma_str, @@ -674,8 +677,10 @@ unsafe fn parse_filter( return b"This filter cannot be used in the .xz format\0" as *const u8 as *const c_char; } - let options: *mut c_void = - lzma_alloc_zero(filter_name_map[i as usize].opts_size as size_t, allocator); + let options: *mut c_void = crate::alloc::internal_alloc_zeroed_bytes( + filter_name_map[i as usize].opts_size as size_t, + allocator, + ); if options.is_null() { return crate::c_str!("Memory allocation failed"); } @@ -684,7 +689,11 @@ unsafe fn parse_filter( let parse = filter_name_map[i as usize].parse.unwrap_unchecked(); let errmsg: *const c_char = parse(str, str_end, options); if !errmsg.is_null() { - lzma_free(options, allocator); + crate::alloc::internal_free_bytes( + options, + filter_name_map[i as usize].opts_size as size_t, + allocator, + ); return errmsg; } (*filter).id = filter_name_map[i as usize].id; @@ -736,13 +745,12 @@ unsafe fn str_to_filters( return errmsg; } let opts: *mut lzma_options_lzma = - lzma_alloc(core::mem::size_of::(), allocator) - as *mut lzma_options_lzma; + crate::alloc::internal_alloc_object::(allocator); if opts.is_null() { return crate::c_str!("Memory allocation failed"); } if lzma_lzma_preset(opts, preset) != 0 { - lzma_free(opts as *mut c_void, allocator); + crate::alloc::internal_free(opts, allocator); return crate::c_str!("Unsupported preset"); } (*filters).id = LZMA_FILTER_LZMA2; @@ -830,7 +838,7 @@ unsafe fn str_to_filters( } while i_0 > 0 { i_0 -= 1; - lzma_free(temp_filters[i_0 as usize].options, allocator); + lzma_filter_options_free(temp_filters[i_0 as usize], allocator); } errmsg } @@ -928,6 +936,7 @@ unsafe fn strfy_filter( i += 1; } } +#[cfg(feature = "custom_allocator")] pub unsafe fn lzma_str_from_filters( output_str: *mut *mut c_char, filters: *const lzma_filter, @@ -1028,6 +1037,7 @@ pub unsafe fn lzma_str_from_filters( } str_finish(output_str, ::core::ptr::addr_of_mut!(dest), allocator) } +#[cfg(feature = "custom_allocator")] pub unsafe fn lzma_str_list_filters( output_str: *mut *mut c_char, filter_id: lzma_vli, diff --git a/xz-core/src/delta/delta_decoder.rs b/xz-core/src/delta/delta_decoder.rs index efd7c0bb..2e81900c 100644 --- a/xz-core/src/delta/delta_decoder.rs +++ b/xz-core/src/delta/delta_decoder.rs @@ -84,8 +84,7 @@ pub(crate) unsafe fn lzma_delta_props_decode( return LZMA_OPTIONS_ERROR; } let opt: *mut lzma_options_delta = - lzma_alloc(core::mem::size_of::(), allocator) - as *mut lzma_options_delta; + crate::alloc::internal_alloc_object::(allocator); if opt.is_null() { return LZMA_MEM_ERROR; } diff --git a/xz-core/src/lz/lz_decoder.rs b/xz-core/src/lz/lz_decoder.rs index 029c1e09..abb86289 100644 --- a/xz-core/src/lz/lz_decoder.rs +++ b/xz-core/src/lz/lz_decoder.rs @@ -174,7 +174,10 @@ unsafe fn lz_decoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocato if let Some(end) = (*coder).lz.end { end((*coder).lz.coder, allocator); } else { - crate::alloc::internal_free_bytes((*coder).lz.coder, allocator); + #[cfg(feature = "custom_allocator")] + crate::alloc::internal_free_bytes((*coder).lz.coder, 0, allocator); + #[cfg(not(feature = "custom_allocator"))] + debug_assert!((*coder).lz.coder.is_null()); } crate::alloc::internal_free(coder, allocator); } diff --git a/xz-core/src/lz/lz_encoder.rs b/xz-core/src/lz/lz_encoder.rs index eceab1d5..142eeec8 100644 --- a/xz-core/src/lz/lz_encoder.rs +++ b/xz-core/src/lz/lz_encoder.rs @@ -359,7 +359,10 @@ unsafe fn lz_encoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocato if let Some(end) = (*coder).lz.end { end((*coder).lz.coder, allocator); } else { - crate::alloc::internal_free_bytes((*coder).lz.coder, allocator); + #[cfg(feature = "custom_allocator")] + crate::alloc::internal_free_bytes((*coder).lz.coder, 0, allocator); + #[cfg(not(feature = "custom_allocator"))] + debug_assert!((*coder).lz.coder.is_null()); } crate::alloc::internal_free(coder, allocator); } diff --git a/xz-core/src/lzma/lzma2_decoder.rs b/xz-core/src/lzma/lzma2_decoder.rs index 20f0716e..937d6350 100644 --- a/xz-core/src/lzma/lzma2_decoder.rs +++ b/xz-core/src/lzma/lzma2_decoder.rs @@ -267,7 +267,7 @@ pub(crate) unsafe fn lzma_lzma2_props_decode( return LZMA_OPTIONS_ERROR; } let opt: *mut lzma_options_lzma = - lzma_alloc(core::mem::size_of::(), allocator) as *mut lzma_options_lzma; + crate::alloc::internal_alloc_object::(allocator); if opt.is_null() { return LZMA_MEM_ERROR; } diff --git a/xz-core/src/lzma/lzma_decoder.rs b/xz-core/src/lzma/lzma_decoder.rs index dec2ca91..d0e404c1 100644 --- a/xz-core/src/lzma/lzma_decoder.rs +++ b/xz-core/src/lzma/lzma_decoder.rs @@ -2471,12 +2471,12 @@ pub(crate) unsafe fn lzma_lzma_props_decode( return LZMA_OPTIONS_ERROR; } let opt: *mut lzma_options_lzma = - lzma_alloc(core::mem::size_of::(), allocator) as *mut lzma_options_lzma; + crate::alloc::internal_alloc_object::(allocator); if opt.is_null() { return LZMA_MEM_ERROR; } if lzma_lzma_lclppb_decode(opt, *props) { - lzma_free(opt as *mut c_void, allocator); + crate::alloc::internal_free(opt, allocator); return LZMA_OPTIONS_ERROR; } else { (*opt).dict_size = read32le(&*props.add(1).cast::<[u8; 4]>()); diff --git a/xz-core/src/raw_alloc.rs b/xz-core/src/raw_alloc.rs index 24300d76..b45da1fc 100644 --- a/xz-core/src/raw_alloc.rs +++ b/xz-core/src/raw_alloc.rs @@ -73,26 +73,32 @@ pub(crate) unsafe fn free_impl(ptr: *mut c_void) { unsafe { dealloc(base, layout) }; } +#[cfg(feature = "custom_allocator")] pub(crate) unsafe fn alloc_bytes(size: size_t) -> *mut c_void { alloc_impl(size as usize, RUST_ALLOC_ALIGN, false) } +#[cfg(feature = "custom_allocator")] pub(crate) unsafe fn alloc_zeroed_bytes(size: size_t) -> *mut c_void { alloc_impl(size as usize, RUST_ALLOC_ALIGN, true) } +#[cfg(feature = "custom_allocator")] pub(crate) unsafe fn free_ptr(ptr: *mut c_void) { unsafe { free_impl(ptr) }; } +#[cfg(feature = "custom_allocator")] pub unsafe fn lzma_alloc(size: size_t, _allocator: *const lzma_allocator) -> *mut c_void { unsafe { alloc_bytes(size) } } +#[cfg(feature = "custom_allocator")] pub unsafe fn lzma_alloc_zero(size: size_t, _allocator: *const lzma_allocator) -> *mut c_void { unsafe { alloc_zeroed_bytes(size) } } +#[cfg(feature = "custom_allocator")] pub unsafe fn lzma_free(ptr: *mut c_void, _allocator: *const lzma_allocator) { unsafe { free_ptr(ptr) }; } @@ -101,7 +107,33 @@ pub(crate) unsafe fn internal_alloc_bytes( size: size_t, _allocator: *const lzma_allocator, ) -> *mut c_void { - unsafe { alloc_bytes(size) } + let Some(layout) = raw_layout(size as usize, RUST_ALLOC_ALIGN) else { + return core::ptr::null_mut(); + }; + if layout.size() == 0 { + return core::ptr::NonNull::::dangling().as_ptr().cast(); + } + unsafe { alloc(layout).cast() } +} + +pub(crate) unsafe fn internal_alloc_untyped_bytes( + size: size_t, + _allocator: *const lzma_allocator, +) -> *mut c_void { + alloc_impl(size as usize, RUST_ALLOC_ALIGN, false) +} + +pub(crate) unsafe fn internal_alloc_zeroed_bytes( + size: size_t, + _allocator: *const lzma_allocator, +) -> *mut c_void { + let Some(layout) = raw_layout(size as usize, RUST_ALLOC_ALIGN) else { + return core::ptr::null_mut(); + }; + if layout.size() == 0 { + return core::ptr::NonNull::::dangling().as_ptr().cast(); + } + unsafe { alloc_zeroed(layout).cast() } } pub(crate) unsafe fn internal_alloc_object(_allocator: *const lzma_allocator) -> *mut T { @@ -146,8 +178,32 @@ pub(crate) unsafe fn internal_alloc_zeroed_array( unsafe { alloc_zeroed(layout).cast::() } } -pub(crate) unsafe fn internal_free_bytes(ptr: *mut c_void, _allocator: *const lzma_allocator) { - unsafe { free_ptr(ptr) }; +pub(crate) unsafe fn internal_free_bytes( + ptr: *mut c_void, + size: size_t, + _allocator: *const lzma_allocator, +) { + let Some(layout) = raw_layout(size as usize, RUST_ALLOC_ALIGN) else { + return; + }; + if ptr.is_null() || layout.size() == 0 { + return; + } + unsafe { dealloc(ptr.cast::(), layout) }; +} + +pub(crate) unsafe fn internal_free_untyped(ptr: *mut c_void, _allocator: *const lzma_allocator) { + assert!( + ptr.is_null(), + "allocated xz-core coders must install a typed end function" + ); +} + +pub(crate) unsafe fn internal_free_untyped_bytes( + ptr: *mut c_void, + _allocator: *const lzma_allocator, +) { + unsafe { free_impl(ptr) }; } pub(crate) unsafe fn internal_free(ptr: *mut T, _allocator: *const lzma_allocator) { @@ -182,6 +238,7 @@ mod tests { use super::*; #[test] + #[cfg(feature = "custom_allocator")] fn raw_allocator_round_trip() { unsafe { let ptr = alloc_bytes(32); @@ -191,6 +248,7 @@ mod tests { } #[test] + #[cfg(feature = "custom_allocator")] fn raw_allocation_respects_alignment() { #[repr(align(32))] struct Align32([u8; 32]); @@ -206,4 +264,13 @@ mod tests { free_impl(ptr); } } + + #[test] + fn internal_allocator_round_trip() { + unsafe { + let ptr = internal_alloc_bytes(32, core::ptr::null()); + assert!(!ptr.is_null()); + internal_free_bytes(ptr, 32, core::ptr::null()); + } + } } diff --git a/xz-core/src/simple/simple_coder.rs b/xz-core/src/simple/simple_coder.rs index f96d5750..81fe2f6d 100644 --- a/xz-core/src/simple/simple_coder.rs +++ b/xz-core/src/simple/simple_coder.rs @@ -175,7 +175,7 @@ unsafe fn simple_code( unsafe fn simple_coder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { let coder: *mut lzma_simple_coder = coder_ptr as *mut lzma_simple_coder; lzma_next_end(::core::ptr::addr_of_mut!((*coder).next), allocator); - crate::alloc::internal_free_array((*coder).simple as *mut u8, (*coder).simple_size, allocator); + crate::alloc::internal_free_untyped_bytes((*coder).simple, allocator); crate::alloc::internal_free_array( coder as *mut u8, core::mem::size_of::() + (*coder).allocated, @@ -253,10 +253,8 @@ pub(crate) unsafe fn lzma_simple_coder_init( }; (*coder).filter = filter; (*coder).allocated = 2 * unfiltered_max; - (*coder).simple_size = simple_size; if simple_size > 0 { - (*coder).simple = - crate::alloc::internal_alloc_array::(simple_size, allocator) as *mut c_void; + (*coder).simple = crate::alloc::internal_alloc_untyped_bytes(simple_size, allocator); if (*coder).simple.is_null() { return LZMA_MEM_ERROR; } diff --git a/xz-core/src/simple/simple_decoder.rs b/xz-core/src/simple/simple_decoder.rs index 72cf3b96..8a07149e 100644 --- a/xz-core/src/simple/simple_decoder.rs +++ b/xz-core/src/simple/simple_decoder.rs @@ -12,13 +12,13 @@ pub(crate) unsafe fn lzma_simple_props_decode( return LZMA_OPTIONS_ERROR; } let opt: *mut lzma_options_bcj = - lzma_alloc(core::mem::size_of::(), allocator) as *mut lzma_options_bcj; + crate::alloc::internal_alloc_object::(allocator); if opt.is_null() { return LZMA_MEM_ERROR; } (*opt).start_offset = read32le(&*props.cast::<[u8; 4]>()); if (*opt).start_offset == 0 { - lzma_free(opt as *mut c_void, allocator); + crate::alloc::internal_free(opt, allocator); } else { *options = opt as *mut c_void; } diff --git a/xz-core/src/types.rs b/xz-core/src/types.rs index e40620ab..3fa29403 100644 --- a/xz-core/src/types.rs +++ b/xz-core/src/types.rs @@ -829,7 +829,6 @@ pub(crate) struct lzma_simple_coder { pub(crate) is_encoder: bool, pub(crate) filter: lzma_simple_filter_function, pub(crate) simple: *mut c_void, - pub(crate) simple_size: size_t, pub(crate) now_pos: u32, pub(crate) allocated: size_t, pub(crate) pos: size_t, @@ -846,9 +845,11 @@ pub(crate) use crate::common::block_encoder::lzma_block_encoder_init; pub use crate::common::block_header_decoder::lzma_block_header_decode; pub use crate::common::block_header_encoder::{lzma_block_header_encode, lzma_block_header_size}; pub use crate::common::block_util::lzma_block_unpadded_size; +#[cfg(feature = "custom_allocator")] +pub use crate::common::common::{lzma_alloc, lzma_alloc_zero, lzma_free}; pub use crate::common::common::{ - lzma_alloc, lzma_alloc_zero, lzma_bufcpy, lzma_end, lzma_free, lzma_next_end, - lzma_next_filter_init, lzma_next_filter_update, lzma_strm_init, + lzma_bufcpy, lzma_end, lzma_next_end, lzma_next_filter_init, lzma_next_filter_update, + lzma_strm_init, }; pub use crate::common::easy_preset::lzma_easy_preset; pub use crate::common::filter_common::{ From 5be4b34b6e5333bb0ba9de81d4e6ded4e452a950 Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Mon, 4 May 2026 14:25:01 +0900 Subject: [PATCH 5/7] Fix README not to refer 0.1.7 --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1457cc82..8a824e3c 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Pure Rust xz2/liblzma-compatible crates for reading and writing xz streams. -**This crate is forked from [xz2](https://crates.io/crates/xz2) and `xz = "0.1.x"` is fully compatible with `xz2 = "0.1.7"`,** +**This crate is forked from [liblzma](https://crates.io/crates/liblzma) and `xz = "0.4.x"` is fully compatible with `liblzma = "0.4.6"`,** so you can migrate simply. ## Migrate from xz2 @@ -18,13 +18,13 @@ so you can migrate simply. ```diff # Cargo.toml [dependencies] --xz2 = "0.1.7" -+xz = "0.1.7" +-liblzma = "0.4.6" ++xz = "0.4.6" ``` ```diff // *.rs --use xz2; +-use liblzma; +use xz; ``` From edb2d1530f6d77f1a16f12d7ba55cf38496b9d38 Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Mon, 4 May 2026 14:25:36 +0900 Subject: [PATCH 6/7] Run xz test on CI --- .github/workflows/main.yml | 15 ++++++ scripts/run_xz_c_tests_with_xz_sys.sh | 66 +++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100755 scripts/run_xz_c_tests_with_xz_sys.sh diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b1899284..a630ab05 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -103,3 +103,18 @@ jobs: - name: Install Rust run: rustup update stable && rustup default stable && rustup component add rustfmt - run: cargo fmt -- --check + + upstream-c-tests: + name: Upstream C xz tests with xz-sys + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + with: + submodules: true + - name: Install Rust + run: rustup update stable --no-self-update && rustup default stable + - uses: Swatinem/rust-cache@v2 + with: + cache-targets: "false" + - name: Run upstream C xz test harness against xz-sys + run: scripts/run_xz_c_tests_with_xz_sys.sh diff --git a/scripts/run_xz_c_tests_with_xz_sys.sh b/scripts/run_xz_c_tests_with_xz_sys.sh new file mode 100755 index 00000000..c1edc8aa --- /dev/null +++ b/scripts/run_xz_c_tests_with_xz_sys.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +XZ_SRC_DIR="$ROOT_DIR/liblzma-sys/xz" +BUILD_DIR="${XZ_SYS_C_TEST_BUILD_DIR:-$ROOT_DIR/target/xz-sys-c-tests}" +CARGO_BUILD_DIR="$BUILD_DIR/cargo" +CMAKE_BUILD_DIR="$BUILD_DIR/cmake" +JOBS="${JOBS:-$(getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)}" + +if command -v ninja >/dev/null 2>&1; then + CMAKE_GENERATOR=( -G Ninja ) +else + CMAKE_GENERATOR=() +fi + +case "$(uname -s)" in + Linux) + # Rust staticlibs require these native libraries when linked by CMake. + CMAKE_EXE_LINKER_FLAGS="${CMAKE_EXE_LINKER_FLAGS:-} -pthread -ldl -lm -lrt" + ;; + *) + CMAKE_EXE_LINKER_FLAGS="${CMAKE_EXE_LINKER_FLAGS:-}" + ;; +esac + +echo "Building xz-sys staticlib..." +CARGO_TARGET_DIR="$CARGO_BUILD_DIR" cargo build -p xz-sys --release --features parallel + +RUST_LIB="$CARGO_BUILD_DIR/release/libxz_sys.a" +CMAKE_LIB="$CMAKE_BUILD_DIR/liblzma.a" + +replace_liblzma_with_xz_sys() { + cp "$RUST_LIB" "$CMAKE_LIB" + + ar t "$CMAKE_LIB" > "$BUILD_DIR/liblzma-archive-members.txt" + if ! grep -q 'xz_sys' "$BUILD_DIR/liblzma-archive-members.txt"; then + echo "replacement liblzma archive does not look like xz-sys" >&2 + exit 1 + fi +} + +echo "Configuring upstream xz C test harness..." +cmake -S "$XZ_SRC_DIR" -B "$CMAKE_BUILD_DIR" "${CMAKE_GENERATOR[@]}" \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_TESTING=ON \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_EXE_LINKER_FLAGS="$CMAKE_EXE_LINKER_FLAGS" \ + -DXZ_NLS=OFF \ + -DXZ_DOXYGEN=OFF + +echo "Building C liblzma target once to materialize CMake outputs..." +cmake --build "$CMAKE_BUILD_DIR" --target liblzma --parallel "$JOBS" + +echo "Replacing C liblzma with xz-sys and building all C tests/tools..." +replace_liblzma_with_xz_sys +cmake --build "$CMAKE_BUILD_DIR" --parallel "$JOBS" + +# Replace once more and rebuild dependents. This guarantees that CMake test +# executables and tools are linked against xz-sys even if the previous build +# regenerated liblzma.a as part of the all target. +replace_liblzma_with_xz_sys +cmake --build "$CMAKE_BUILD_DIR" --parallel "$JOBS" + +echo "Running upstream xz C tests against xz-sys..." +ctest --test-dir "$CMAKE_BUILD_DIR" --output-on-failure "$@" From 38aa00bd3510c84d32d53e98741abe0512ddea61 Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Mon, 4 May 2026 14:49:27 +0900 Subject: [PATCH 7/7] Fix PR CI failures --- Cargo.lock.msrv | 2 +- README.md | 2 +- xz-core/src/alloc/custom.rs | 129 +++++++++++++++++------- xz-core/src/common/index_hash.rs | 15 ++- xz-core/src/common/stream_decoder_mt.rs | 4 +- xz-core/src/common/stream_encoder_mt.rs | 8 +- xz-core/src/lzma/lzma_decoder.rs | 1 + 7 files changed, 115 insertions(+), 46 deletions(-) diff --git a/Cargo.lock.msrv b/Cargo.lock.msrv index c555fff4..942751fa 100644 --- a/Cargo.lock.msrv +++ b/Cargo.lock.msrv @@ -972,7 +972,7 @@ dependencies = [ [[package]] name = "xz-core" -version = "0.1.0" +version = "0.0.1" dependencies = [ "libc", "memchr", diff --git a/README.md b/README.md index 8a824e3c..444bf74f 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Pure Rust xz2/liblzma-compatible crates for reading and writing xz streams. **This crate is forked from [liblzma](https://crates.io/crates/liblzma) and `xz = "0.4.x"` is fully compatible with `liblzma = "0.4.6"`,** so you can migrate simply. -## Migrate from xz2 +## Migrate from liblzma ```diff # Cargo.toml diff --git a/xz-core/src/alloc/custom.rs b/xz-core/src/alloc/custom.rs index 519b7a89..122ad4f0 100644 --- a/xz-core/src/alloc/custom.rs +++ b/xz-core/src/alloc/custom.rs @@ -1,21 +1,12 @@ use crate::types::*; use super::c::{c_alloc_bytes, c_alloc_zeroed_bytes, c_allocator_ptr, c_free_ptr}; -use super::rust::rust_allocator_ptr; use crate::raw_alloc::{RUST_ALLOC_ALIGN, alloc_impl, free_ptr}; fn c_size(size: size_t) -> size_t { if size == 0 { 1 } else { size } } -pub(crate) fn allocator_or_rust(allocator: *const lzma_allocator) -> *const lzma_allocator { - if allocator.is_null() { - rust_allocator_ptr() - } else { - allocator - } -} - pub fn allocator_or_c(allocator: *const lzma_allocator) -> *const lzma_allocator { if allocator.is_null() { c_allocator_ptr() @@ -63,9 +54,11 @@ pub(crate) unsafe fn internal_alloc_bytes( allocator: *const lzma_allocator, ) -> *mut c_void { let size = c_size(size); - let allocator = allocator_or_rust(allocator); - if let Some(alloc) = unsafe { (*allocator).alloc } { - return unsafe { alloc((*allocator).opaque, 1, size) }; + if !allocator.is_null() { + if let Some(alloc) = unsafe { (*allocator).alloc } { + return unsafe { alloc((*allocator).opaque, 1, size) }; + } + return unsafe { c_alloc_bytes(size) }; } alloc_impl(size as usize, RUST_ALLOC_ALIGN, false) } @@ -82,24 +75,26 @@ pub(crate) unsafe fn internal_alloc_zeroed_bytes( allocator: *const lzma_allocator, ) -> *mut c_void { let size = c_size(size); - let allocator = allocator_or_rust(allocator); - if let Some(alloc) = unsafe { (*allocator).alloc } { - let ptr = unsafe { alloc((*allocator).opaque, 1, size) }; - if !ptr.is_null() { - unsafe { core::ptr::write_bytes(ptr.cast::(), 0, size) }; + if !allocator.is_null() { + if let Some(alloc) = unsafe { (*allocator).alloc } { + let ptr = unsafe { alloc((*allocator).opaque, 1, size) }; + if !ptr.is_null() { + unsafe { core::ptr::write_bytes(ptr.cast::(), 0, size) }; + } + return ptr; } - return ptr; + return unsafe { c_alloc_zeroed_bytes(size) }; } alloc_impl(size as usize, RUST_ALLOC_ALIGN, true) } pub(crate) unsafe fn internal_alloc_object(allocator: *const lzma_allocator) -> *mut T { - if !allocator.is_null() - && let Some(alloc) = unsafe { (*allocator).alloc } - { - return unsafe { - alloc((*allocator).opaque, 1, core::mem::size_of::() as size_t) as *mut T - }; + if !allocator.is_null() { + let size = c_size(core::mem::size_of::() as size_t); + if let Some(alloc) = unsafe { (*allocator).alloc } { + return unsafe { alloc((*allocator).opaque, 1, size) as *mut T }; + } + return unsafe { c_alloc_bytes(size) as *mut T }; } alloc_impl(core::mem::size_of::(), core::mem::align_of::(), false) as *mut T } @@ -111,10 +106,12 @@ pub(crate) unsafe fn internal_alloc_array( let Some(size) = (count as usize).checked_mul(core::mem::size_of::()) else { return core::ptr::null_mut(); }; - if !allocator.is_null() - && let Some(alloc) = unsafe { (*allocator).alloc } - { - return unsafe { alloc((*allocator).opaque, 1, size as size_t) as *mut T }; + if !allocator.is_null() { + let size = c_size(size as size_t); + if let Some(alloc) = unsafe { (*allocator).alloc } { + return unsafe { alloc((*allocator).opaque, 1, size) as *mut T }; + } + return unsafe { c_alloc_bytes(size) as *mut T }; } alloc_impl(size, core::mem::align_of::(), false) as *mut T } @@ -126,14 +123,16 @@ pub(crate) unsafe fn internal_alloc_zeroed_array( let Some(size) = (count as usize).checked_mul(core::mem::size_of::()) else { return core::ptr::null_mut(); }; - if !allocator.is_null() - && let Some(alloc) = unsafe { (*allocator).alloc } - { - let ptr = unsafe { alloc((*allocator).opaque, 1, size as size_t) as *mut T }; - if !ptr.is_null() { - unsafe { core::ptr::write_bytes(ptr as *mut u8, 0, size) }; + if !allocator.is_null() { + let alloc_size = c_size(size as size_t); + if let Some(alloc) = unsafe { (*allocator).alloc } { + let ptr = unsafe { alloc((*allocator).opaque, 1, alloc_size) as *mut T }; + if !ptr.is_null() { + unsafe { core::ptr::write_bytes(ptr as *mut u8, 0, alloc_size as usize) }; + } + return ptr; } - return ptr; + return unsafe { c_alloc_zeroed_bytes(alloc_size) as *mut T }; } alloc_impl(size, core::mem::align_of::(), true) as *mut T } @@ -149,18 +148,22 @@ pub(crate) unsafe fn internal_free_bytes( unsafe { free((*allocator).opaque, ptr) }; return; } + if !allocator.is_null() { + unsafe { c_free_ptr(ptr) }; + return; + } unsafe { free_ptr(ptr) }; } pub(crate) unsafe fn internal_free_untyped(ptr: *mut c_void, allocator: *const lzma_allocator) { - unsafe { lzma_free(ptr, allocator) }; + unsafe { internal_free_bytes(ptr, 0, allocator) }; } pub(crate) unsafe fn internal_free_untyped_bytes( ptr: *mut c_void, allocator: *const lzma_allocator, ) { - unsafe { lzma_free(ptr, allocator) }; + unsafe { internal_free_bytes(ptr, 0, allocator) }; } pub(crate) unsafe fn internal_free(ptr: *mut T, allocator: *const lzma_allocator) { @@ -174,3 +177,55 @@ pub(crate) unsafe fn internal_free_array( ) { unsafe { internal_free_bytes(ptr.cast(), 0, allocator) }; } + +#[cfg(test)] +mod tests { + use super::*; + use core::sync::atomic::{AtomicUsize, Ordering}; + + static FREE_COUNT: AtomicUsize = AtomicUsize::new(0); + + unsafe fn c_alloc(_opaque: *mut c_void, nmemb: size_t, size: size_t) -> *mut c_void { + let Some(bytes) = (nmemb as usize).checked_mul(size as usize) else { + return core::ptr::null_mut(); + }; + unsafe { c_alloc_bytes(bytes as size_t) } + } + + unsafe fn counted_c_free(_opaque: *mut c_void, ptr: *mut c_void) { + FREE_COUNT.fetch_add(1, Ordering::Relaxed); + unsafe { c_free_ptr(ptr) }; + } + + #[test] + fn internal_free_falls_back_to_c_free_for_partial_c_allocator() { + unsafe { + let allocator = lzma_allocator { + alloc: Some(c_alloc), + free: None, + opaque: core::ptr::null_mut(), + }; + + let ptr = internal_alloc_object::(&allocator); + assert!(!ptr.is_null()); + internal_free(ptr, &allocator); + } + } + + #[test] + fn internal_alloc_falls_back_to_c_alloc_for_partial_c_allocator() { + unsafe { + FREE_COUNT.store(0, Ordering::Relaxed); + let allocator = lzma_allocator { + alloc: None, + free: Some(counted_c_free), + opaque: core::ptr::null_mut(), + }; + + let ptr = internal_alloc_bytes(16, &allocator); + assert!(!ptr.is_null()); + internal_free_bytes(ptr, 16, &allocator); + assert_eq!(FREE_COUNT.load(Ordering::Relaxed), 1); + } + } +} diff --git a/xz-core/src/common/index_hash.rs b/xz-core/src/common/index_hash.rs index a08866cb..6051d001 100644 --- a/xz-core/src/common/index_hash.rs +++ b/xz-core/src/common/index_hash.rs @@ -242,7 +242,20 @@ pub unsafe fn lzma_index_hash_decode( continue; } 5 => {} - 6 => break, + 6 => loop { + if *in_pos == in_size { + return LZMA_OK; + } + let val = *input.offset(*in_pos as isize); + *in_pos += 1; + if (*index_hash).crc32 >> ((*index_hash).pos * 8) & 0xff != val as u32 { + return LZMA_DATA_ERROR; + } + (*index_hash).pos += 1; + if (*index_hash).pos >= 4 { + return LZMA_STREAM_END; + } + }, _ => return LZMA_PROG_ERROR, } if (*index_hash).pos > 0 { diff --git a/xz-core/src/common/stream_decoder_mt.rs b/xz-core/src/common/stream_decoder_mt.rs index 615cb0a1..4dfb7c78 100644 --- a/xz-core/src/common/stream_decoder_mt.rs +++ b/xz-core/src/common/stream_decoder_mt.rs @@ -4,7 +4,7 @@ use crate::common::outqueue::{ use crate::types::*; #[derive(Copy, Clone)] #[repr(C)] -pub struct lzma_stream_coder { +struct lzma_stream_coder { pub sequence: stream_decoder_mt_seq, pub block_decoder: lzma_next_coder, pub block_options: lzma_block, @@ -45,7 +45,7 @@ pub struct lzma_stream_coder { } #[derive(Copy, Clone)] #[repr(C)] -pub struct worker_thread { +struct worker_thread { pub state: worker_state, pub in_0: *mut u8, pub in_size: size_t, diff --git a/xz-core/src/common/stream_encoder_mt.rs b/xz-core/src/common/stream_encoder_mt.rs index 0ac7552c..2688dde4 100644 --- a/xz-core/src/common/stream_encoder_mt.rs +++ b/xz-core/src/common/stream_encoder_mt.rs @@ -2,10 +2,10 @@ use crate::common::block_buffer_encoder::{lzma_block_buffer_bound64, lzma_block_ use crate::common::filter_encoder::lzma_mt_block_size; use crate::common::outqueue::lzma_outq_memusage; use crate::types::*; -pub type worker_thread = worker_thread_s; +type worker_thread = worker_thread_s; #[derive(Copy, Clone)] #[repr(C)] -pub struct worker_thread_s { +struct worker_thread_s { pub state: worker_state, pub in_0: *mut u8, pub in_alloc_size: size_t, @@ -49,10 +49,10 @@ unsafe fn set_worker_allocator(thr: *mut worker_thread, allocator: *const lzma_a let _ = (thr, allocator); } } -pub type lzma_stream_coder = lzma_stream_coder_s; +type lzma_stream_coder = lzma_stream_coder_s; #[derive(Copy, Clone)] #[repr(C)] -pub struct lzma_stream_coder_s { +struct lzma_stream_coder_s { pub sequence: stream_encoder_mt_seq, pub block_size: size_t, pub filters: [lzma_filter; 5], diff --git a/xz-core/src/lzma/lzma_decoder.rs b/xz-core/src/lzma/lzma_decoder.rs index d0e404c1..84b08b16 100644 --- a/xz-core/src/lzma/lzma_decoder.rs +++ b/xz-core/src/lzma/lzma_decoder.rs @@ -2373,6 +2373,7 @@ pub unsafe fn lzma_lzma_decoder_create( return LZMA_MEM_ERROR; } (*lz).code = lzma_decode as lzma_lz_decoder_code_function; + (*lz).end = Some(lzma_decoder_end as unsafe fn(*mut c_void, *const lzma_allocator) -> ()); (*lz).reset = Some(lzma_decoder_reset as unsafe fn(*mut c_void, *const c_void) -> ()); (*lz).set_uncompressed = Some(lzma_decoder_uncompressed as unsafe fn(*mut c_void, lzma_vli, bool) -> ());