@@ -26,12 +26,14 @@ pub mod bindings {
2626 include ! ( concat!( env!( "OUT_DIR" ) , "/bindings.rs" ) ) ;
2727}
2828
29+ use std:: alloc:: { self , Layout } ;
2930use std:: ffi:: CString ;
31+ use std:: mem:: { align_of, size_of} ;
3032use std:: os:: raw:: c_void;
3133use std:: ptr:: null_mut;
3234use std:: sync:: atomic:: Ordering ;
3335
34- use crate :: bindings:: { cc_subtitle, eia608_screen, realloc } ;
36+ use crate :: bindings:: { cc_subtitle, eia608_screen} ;
3537
3638use lib_ccxr:: debug;
3739use lib_ccxr:: info;
@@ -42,31 +44,8 @@ use lib_ccxr::util::log::{hex_dump, send_gui, DebugMessageFlag, GuiXdsMessage};
4244use crate :: xds:: constants:: * ;
4345use crate :: xds:: types:: * ;
4446
45- extern "C" {
46- fn malloc ( size : usize ) -> * mut c_void ;
47- fn free ( ptr : * mut c_void ) ;
48- }
49-
5047// --- helper func ---
5148
52- /// Frees a pointer and sets it to null.
53- ///
54- /// Converts the raw pointer back into a `Box` to deallocate the memory,
55- /// then sets the original pointer to null to prevent use-after-free.
56- ///
57- /// # Safety
58- /// - The pointer must have been originally allocated by Rust's `Box::into_raw`
59- /// or equivalent. Using this with C-allocated memory will cause undefined behavior.
60- /// - The pointer must not be used after this call.
61- pub fn freep < T > ( ptr : & mut * mut T ) {
62- unsafe {
63- if !ptr. is_null ( ) {
64- free ( * ptr as * mut c_void ) ;
65- * ptr = null_mut ( ) ;
66- }
67- }
68- }
69-
7049/// Helper function to copy String into i8 array
7150fn string_to_i8_array ( s : & str , arr : & mut [ i8 ] ) {
7251 let bytes = s. as_bytes ( ) ;
@@ -94,7 +73,6 @@ fn i8_array_to_string(arr: &[i8]) -> String {
9473/// Writes an XDS string to the subtitle output buffer.
9574///
9675/// # Safety
97- /// - `sub.data` must be a valid pointer previously allocated by C's malloc/realloc, or null.
9876/// - The caller must ensure `sub` and `ctx` remain valid for the duration of the call.
9977/// - The returned `xds_str` pointer in the screen data must be freed with `CString::from_raw`.
10078pub unsafe fn write_xds_string (
@@ -103,28 +81,44 @@ pub unsafe fn write_xds_string(
10381 p : String ,
10482 ts_start_of_xds : i64 ,
10583) -> Result < ( ) , ( ) > {
84+ let c_str = CString :: new ( p) . map_err ( |_| ( ) ) ?;
85+ let len = c_str. as_bytes ( ) . len ( ) ; // length w/o null terminator - matching C's vsnprintf return
86+ let alloc_len = len + 1 ; // allocate space for null terminator
87+
10688 let new_size = ( sub. nb_data + 1 ) as usize * size_of :: < eia608_screen > ( ) ;
107- let new_data =
108- unsafe { realloc ( sub. data as * mut c_void , new_size as u64 ) as * mut eia608_screen } ;
89+ let screen_align = align_of :: < eia608_screen > ( ) ;
90+ let new_data = unsafe {
91+ if sub. data . is_null ( ) {
92+ let layout = Layout :: from_size_align_unchecked ( new_size, screen_align) ;
93+ alloc:: alloc ( layout) as * mut eia608_screen
94+ } else {
95+ let old_size = sub. nb_data as usize * size_of :: < eia608_screen > ( ) ;
96+ let old_layout = Layout :: from_size_align_unchecked ( old_size, screen_align) ;
97+ alloc:: realloc ( sub. data as * mut u8 , old_layout, new_size) as * mut eia608_screen
98+ }
99+ } ;
109100 if new_data. is_null ( ) {
110- freep ( & mut sub. data ) ;
101+ if !sub. data . is_null ( ) && sub. nb_data > 0 {
102+ let old_size = sub. nb_data as usize * size_of :: < eia608_screen > ( ) ;
103+ let old_layout = Layout :: from_size_align_unchecked ( old_size, screen_align) ;
104+ alloc:: dealloc ( sub. data as * mut u8 , old_layout) ;
105+ sub. data = null_mut ( ) ;
106+ }
111107 sub. nb_data = 0 ;
112108 info ! ( "No Memory left" ) ;
113109 return Err ( ( ) ) ;
114110 }
115111 sub. data = new_data as * mut c_void ;
116112 sub. datatype = 0 ;
117113 let data_element = & mut * new_data. add ( sub. nb_data as usize ) ;
118- let c_str = CString :: new ( p) . map_err ( |_| ( ) ) ?;
119114
120- let len = c_str. as_bytes ( ) . len ( ) ; // length w/o null terminator - matching C's vsnprintf return
121- let alloc_len = len + 1 ; // allocate space for null terminator
122- let ptr = unsafe { malloc ( alloc_len) as * mut i8 } ; // fixing c/rust mem mismatch
115+ let str_layout = Layout :: from_size_align ( alloc_len, 1 ) . map_err ( |_| ( ) ) ?;
116+ let ptr = unsafe { alloc:: alloc ( str_layout) as * mut i8 } ;
123117 if ptr. is_null ( ) {
124118 return Err ( ( ) ) ;
125119 }
126120 unsafe {
127- std:: ptr:: copy_nonoverlapping ( c_str. as_ptr ( ) , ptr, alloc_len) ; // copy including null terminator
121+ std:: ptr:: copy_nonoverlapping ( c_str. as_ptr ( ) , ptr, alloc_len) ;
128122 }
129123
130124 data_element. format = 2 ;
0 commit comments