diff --git a/src/rust/src/decoder/mod.rs b/src/rust/src/decoder/mod.rs index fb65c91d3..325a72fc3 100644 --- a/src/rust/src/decoder/mod.rs +++ b/src/rust/src/decoder/mod.rs @@ -44,35 +44,24 @@ pub struct Dtvcc<'a> { impl<'a> Dtvcc<'a> { /// Create a new dtvcc context pub fn new(ctx: &'a mut dtvcc_ctx) -> Self { - let report = if !ctx.report.is_null() { - unsafe { Box::new(*(ctx.report)) } - } else { - Box::new(ccx_decoder_dtvcc_report::default()) - }; - let encoder = if !ctx.encoder.is_null() { - unsafe { Box::new(*(ctx.encoder as *mut encoder_ctx)) } - } else { - Box::new(encoder_ctx::default()) - }; - let timing = if !ctx.timing.is_null() { - unsafe { Box::new(*(ctx.timing)) } - } else { - Box::new(ccx_common_timing_ctx::default()) - }; + let report = unsafe { &mut *ctx.report }; + let encoder = unsafe { &mut *(ctx.encoder as *mut encoder_ctx) }; + let timing = unsafe { &mut *ctx.timing }; + Self { is_active: is_true(ctx.is_active), active_services_count: ctx.active_services_count as u8, services_active: ctx.services_active.to_vec(), report_enabled: is_true(ctx.report_enabled), - report: Box::leak(report), + report, decoders: ctx.decoders.iter_mut().collect(), packet: ctx.current_packet.to_vec(), packet_length: ctx.current_packet_length as u8, is_header_parsed: is_true(ctx.is_current_packet_header_parsed), last_sequence: ctx.last_sequence, - encoder: Box::leak(encoder), + encoder, no_rollup: is_true(ctx.no_rollup), - timing: Box::leak(timing), + timing, } } /// Process cc data and add it to the dtvcc packet @@ -247,13 +236,27 @@ impl PartialEq for dtvcc_symbol { } #[cfg(test)] -mod test { +pub mod test { use lib_ccxr::util::log::{set_logger, CCExtractorLogger, DebugMessageMask, OutputTarget}; use crate::utils::get_zero_allocated_obj; use super::*; + pub fn initialize_dtvcc_ctx() -> Box { + let mut ctx = get_zero_allocated_obj::(); + + // Initialize the required pointers to avoid null pointer dereference + let report = Box::new(ccx_decoder_dtvcc_report::default()); + ctx.report = Box::into_raw(report); + + let encoder = Box::new(encoder_ctx::default()); + ctx.encoder = Box::into_raw(encoder) as *mut _ as *mut std::os::raw::c_void; + + let timing = Box::new(ccx_common_timing_ctx::default()); + ctx.timing = Box::into_raw(timing); + ctx + } #[test] fn test_process_cc_data() { set_logger(CCExtractorLogger::new( @@ -262,7 +265,9 @@ mod test { false, )) .ok(); - let mut dtvcc_ctx = get_zero_allocated_obj::(); + + let mut dtvcc_ctx = initialize_dtvcc_ctx(); + let mut decoder = Dtvcc::new(&mut dtvcc_ctx); // Case 1: cc_type = 2 @@ -311,7 +316,9 @@ mod test { false, )) .ok(); - let mut dtvcc_ctx = get_zero_allocated_obj::(); + + let mut dtvcc_ctx = initialize_dtvcc_ctx(); + let mut decoder = Dtvcc::new(&mut dtvcc_ctx); // Case 1: Without providing last_sequence diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs index 74101c95a..f69b52d3c 100644 --- a/src/rust/src/lib.rs +++ b/src/rust/src/lib.rs @@ -27,7 +27,7 @@ use std::os::windows::io::{FromRawHandle, RawHandle}; use args::Args; use bindings::*; -use cfg_if::cfg_if; +use cfg_if::cfg_if; use clap::{error::ErrorKind, Parser}; use common::{copy_from_rust, CType, CType2}; use decoder::Dtvcc; @@ -43,62 +43,62 @@ use std::{ os::raw::{c_char, c_double, c_int, c_long, c_uint}, }; -// Mock data for rust unit tests -cfg_if! { - if #[cfg(test)] { - static mut cb_708: c_int = 0; - static mut cb_field1: c_int = 0; - static mut cb_field2: c_int = 0; - static mut current_fps: c_double = 30.0; - static mut usercolor_rgb: [c_int; 8] = [0; 8]; - static mut FILEBUFFERSIZE: c_int = 0; - static mut MPEG_CLOCK_FREQ: c_int = 90000; - - static mut frames_since_ref_time: c_int = 0; - static mut total_frames_count: c_uint = 0; - static mut fts_at_gop_start: c_long = 0; - static mut gop_rollover: c_int = 0; - static mut pts_big_change: c_uint = 0; - - static mut tlt_config: ccx_s_teletext_config = unsafe { std::mem::zeroed() }; - static mut ccx_options: ccx_s_options = unsafe { std::mem::zeroed() }; - static mut gop_time: gop_time_code = unsafe { std::mem::zeroed() }; - static mut first_gop_time: gop_time_code = unsafe { std::mem::zeroed() }; - static mut ccx_common_timing_settings: ccx_common_timing_settings_t = unsafe { std::mem::zeroed() }; - static mut capitalization_list: word_list = unsafe { std::mem::zeroed() }; - static mut profane: word_list = unsafe { std::mem::zeroed() }; - - unsafe extern "C" fn version(_location: *const c_char) {} - unsafe extern "C" fn set_binary_mode() {} - } -} - -// External C symbols (only when not testing) -#[cfg(not(test))] -extern "C" { - static mut cb_708: c_int; - static mut cb_field1: c_int; - static mut cb_field2: c_int; - static mut current_fps: c_double; - static mut usercolor_rgb: [c_int; 8]; - static mut FILEBUFFERSIZE: c_int; - static mut MPEG_CLOCK_FREQ: c_int; - static mut tlt_config: ccx_s_teletext_config; - static mut ccx_options: ccx_s_options; - static mut frames_since_ref_time: c_int; - static mut total_frames_count: c_uint; - static mut gop_time: gop_time_code; - static mut first_gop_time: gop_time_code; - static mut fts_at_gop_start: c_long; - static mut gop_rollover: c_int; - static mut ccx_common_timing_settings: ccx_common_timing_settings_t; - static mut capitalization_list: word_list; - static mut profane: word_list; - static mut pts_big_change: c_uint; - - fn version(location: *const c_char); - fn set_binary_mode(); -} +// Mock data for rust unit tests +cfg_if! { + if #[cfg(test)] { + static mut cb_708: c_int = 0; + static mut cb_field1: c_int = 0; + static mut cb_field2: c_int = 0; + static mut current_fps: c_double = 30.0; + static mut usercolor_rgb: [c_int; 8] = [0; 8]; + static mut FILEBUFFERSIZE: c_int = 0; + static mut MPEG_CLOCK_FREQ: c_int = 90000; + + static mut frames_since_ref_time: c_int = 0; + static mut total_frames_count: c_uint = 0; + static mut fts_at_gop_start: c_long = 0; + static mut gop_rollover: c_int = 0; + static mut pts_big_change: c_uint = 0; + + static mut tlt_config: ccx_s_teletext_config = unsafe { std::mem::zeroed() }; + static mut ccx_options: ccx_s_options = unsafe { std::mem::zeroed() }; + static mut gop_time: gop_time_code = unsafe { std::mem::zeroed() }; + static mut first_gop_time: gop_time_code = unsafe { std::mem::zeroed() }; + static mut ccx_common_timing_settings: ccx_common_timing_settings_t = unsafe { std::mem::zeroed() }; + static mut capitalization_list: word_list = unsafe { std::mem::zeroed() }; + static mut profane: word_list = unsafe { std::mem::zeroed() }; + + unsafe extern "C" fn version(_location: *const c_char) {} + unsafe extern "C" fn set_binary_mode() {} + } +} + +// External C symbols (only when not testing) +#[cfg(not(test))] +extern "C" { + static mut cb_708: c_int; + static mut cb_field1: c_int; + static mut cb_field2: c_int; + static mut current_fps: c_double; + static mut usercolor_rgb: [c_int; 8]; + static mut FILEBUFFERSIZE: c_int; + static mut MPEG_CLOCK_FREQ: c_int; + static mut tlt_config: ccx_s_teletext_config; + static mut ccx_options: ccx_s_options; + static mut frames_since_ref_time: c_int; + static mut total_frames_count: c_uint; + static mut gop_time: gop_time_code; + static mut first_gop_time: gop_time_code; + static mut fts_at_gop_start: c_long; + static mut gop_rollover: c_int; + static mut ccx_common_timing_settings: ccx_common_timing_settings_t; + static mut capitalization_list: word_list; + static mut profane: word_list; + static mut pts_big_change: c_uint; + + fn version(location: *const c_char); + fn set_binary_mode(); +} /// Initialize env logger with custom format, using stdout as target #[no_mangle] @@ -352,7 +352,8 @@ mod test { #[test] fn test_do_cb() { - let mut dtvcc_ctx = utils::get_zero_allocated_obj::(); + let mut dtvcc_ctx = crate::decoder::test::initialize_dtvcc_ctx(); + let mut dtvcc = Dtvcc::new(&mut dtvcc_ctx); let mut decoder_ctx = lib_cc_decode::default();