@@ -224,9 +224,7 @@ impl Log for AndroidLogger {
224
224
. unwrap_or_else ( || module_path. as_bytes ( ) ) ;
225
225
226
226
// truncate the tag here to fit into LOGGING_TAG_MAX_LEN
227
- self . fill_tag_bytes ( & mut tag_bytes, tag) ;
228
- // use stack array as C string
229
- let tag: & CStr = unsafe { CStr :: from_ptr ( mem:: transmute ( tag_bytes. as_ptr ( ) ) ) } ;
227
+ let tag = fill_tag_bytes ( & mut tag_bytes, tag) ;
230
228
231
229
// message must not exceed LOGGING_MSG_MAX_LEN
232
230
// therefore split log message into multiple log calls
@@ -250,23 +248,32 @@ impl Log for AndroidLogger {
250
248
fn flush ( & self ) { }
251
249
}
252
250
253
- impl AndroidLogger {
254
- fn fill_tag_bytes ( & self , array : & mut [ MaybeUninit < u8 > ] , tag : & [ u8 ] ) {
255
- if tag. len ( ) > LOGGING_TAG_MAX_LEN {
256
- for ( input, output) in tag
257
- . iter ( )
258
- . take ( LOGGING_TAG_MAX_LEN - 2 )
259
- . chain ( b"..\0 " . iter ( ) )
260
- . zip ( array. iter_mut ( ) )
261
- {
262
- output. write ( * input) ;
263
- }
264
- } else {
265
- for ( input, output) in tag. iter ( ) . chain ( b"\0 " . iter ( ) ) . zip ( array. iter_mut ( ) ) {
266
- output. write ( * input) ;
267
- }
251
+ fn fill_tag_bytes < ' a > (
252
+ array : & ' a mut [ MaybeUninit < u8 > ; LOGGING_TAG_MAX_LEN + 1 ] ,
253
+ tag : & [ u8 ] ,
254
+ ) -> & ' a CStr {
255
+ // FIXME: Simplify when maybe_uninit_fill with MaybeUninit::fill_from() is stabilized
256
+ let initialized;
257
+ if tag. len ( ) > LOGGING_TAG_MAX_LEN {
258
+ for ( input, output) in tag
259
+ . iter ( )
260
+ . take ( LOGGING_TAG_MAX_LEN - 2 )
261
+ . chain ( b"..\0 " )
262
+ . zip ( array. iter_mut ( ) )
263
+ {
264
+ output. write ( * input) ;
265
+ }
266
+ initialized = array. as_slice ( ) ;
267
+ } else {
268
+ for ( input, output) in tag. iter ( ) . chain ( b"\0 " . iter ( ) ) . zip ( array. iter_mut ( ) ) {
269
+ output. write ( * input) ;
268
270
}
271
+ initialized = & array[ ..tag. len ( ) + 1 ] ;
269
272
}
273
+
274
+ // SAFETY: The above code initialized the length of the tag plus a nul terminator, or the whole length of the slice
275
+ let initialized = unsafe { slice_assume_init_ref ( initialized) } ;
276
+ CStr :: from_bytes_with_nul ( initialized) . expect ( "Unreachable: we wrote a nul terminator" )
270
277
}
271
278
272
279
/// Filter for android logger.
@@ -449,7 +456,11 @@ impl<'a> PlatformLogWriter<'a> {
449
456
self . buffer . get_unchecked_mut ( len)
450
457
} ) ;
451
458
452
- let msg: & CStr = unsafe { CStr :: from_ptr ( self . buffer . as_ptr ( ) . cast ( ) ) } ;
459
+ // TODO: This function must be `unsafe` - or receive an initialized slice or CStr directly -
460
+ // as we can't otherwise guarantee safety here.
461
+ let initialized = unsafe { slice_assume_init_ref ( & self . buffer [ ..len + 1 ] ) } ;
462
+ let msg = CStr :: from_bytes_with_nul ( initialized)
463
+ . expect ( "Unreachable: nul terminator was placed at `len`" ) ;
453
464
android_log ( self . buf_id , self . priority , self . tag , msg) ;
454
465
455
466
unsafe { * self . buffer . get_unchecked_mut ( len) = last_byte } ;
@@ -544,6 +555,11 @@ fn uninit_array<const N: usize, T>() -> [MaybeUninit<T>; N] {
544
555
unsafe { MaybeUninit :: uninit ( ) . assume_init ( ) }
545
556
}
546
557
558
+ // FIXME: Remove when maybe_uninit_slice is stabilized to provide MaybeUninit::slice_assume_init_ref()
559
+ unsafe fn slice_assume_init_ref < T > ( slice : & [ MaybeUninit < T > ] ) -> & [ T ] {
560
+ & * ( slice as * const [ MaybeUninit < T > ] as * const [ T ] )
561
+ }
562
+
547
563
#[ cfg( test) ]
548
564
mod tests {
549
565
use super :: * ;
@@ -604,28 +620,26 @@ mod tests {
604
620
605
621
#[ test]
606
622
fn fill_tag_bytes_truncates_long_tag ( ) {
607
- let logger = AndroidLogger :: new ( Config :: default ( ) ) ;
608
- let too_long_tag: [ u8 ; LOGGING_TAG_MAX_LEN + 20 ] = [ b'a' ; LOGGING_TAG_MAX_LEN + 20 ] ;
623
+ let too_long_tag = [ b'a' ; LOGGING_TAG_MAX_LEN + 20 ] ;
609
624
610
- let mut result: [ MaybeUninit < u8 > ; LOGGING_TAG_MAX_LEN + 1 ] = uninit_array ( ) ;
611
- logger . fill_tag_bytes ( & mut result, & too_long_tag) ;
625
+ let mut result = uninit_array ( ) ;
626
+ let tag = fill_tag_bytes ( & mut result, & too_long_tag) ;
612
627
613
- let mut expected_result = [ b'a' ; LOGGING_TAG_MAX_LEN - 2 ] . to_vec ( ) ;
628
+ let mut expected_result = vec ! [ b'a' ; LOGGING_TAG_MAX_LEN - 2 ] ;
614
629
expected_result. extend ( "..\0 " . as_bytes ( ) ) ;
615
- assert_eq ! ( unsafe { assume_init_slice ( & result ) } , expected_result) ;
630
+ assert_eq ! ( tag . to_bytes_with_nul ( ) , expected_result) ;
616
631
}
617
632
618
633
#[ test]
619
634
fn fill_tag_bytes_keeps_short_tag ( ) {
620
- let logger = AndroidLogger :: new ( Config :: default ( ) ) ;
621
- let short_tag: [ u8 ; 3 ] = [ b'a' ; 3 ] ;
635
+ let short_tag = [ b'a' ; 3 ] ;
622
636
623
- let mut result: [ MaybeUninit < u8 > ; LOGGING_TAG_MAX_LEN + 1 ] = uninit_array ( ) ;
624
- logger . fill_tag_bytes ( & mut result, & short_tag) ;
637
+ let mut result = uninit_array ( ) ;
638
+ let tag = fill_tag_bytes ( & mut result, & short_tag) ;
625
639
626
640
let mut expected_result = short_tag. to_vec ( ) ;
627
641
expected_result. push ( 0 ) ;
628
- assert_eq ! ( unsafe { assume_init_slice ( & result [ .. 4 ] ) } , expected_result) ;
642
+ assert_eq ! ( tag . to_bytes_with_nul ( ) , expected_result) ;
629
643
}
630
644
631
645
#[ test]
@@ -654,7 +668,7 @@ mod tests {
654
668
assert_eq ! ( writer. len, 3 ) ;
655
669
assert_eq ! ( writer. last_newline_index, 0 ) ;
656
670
assert_eq ! (
657
- unsafe { assume_init_slice ( & writer. buffer[ ..writer. len] ) } ,
671
+ unsafe { slice_assume_init_ref ( & writer. buffer[ ..writer. len] ) } ,
658
672
"\n 90" . as_bytes( )
659
673
) ;
660
674
@@ -699,7 +713,7 @@ mod tests {
699
713
writer. output_specified_len ( 5 ) ;
700
714
701
715
assert_eq ! (
702
- unsafe { assume_init_slice ( & writer. buffer[ ..log_string. len( ) ] ) } ,
716
+ unsafe { slice_assume_init_ref ( & writer. buffer[ ..log_string. len( ) ] ) } ,
703
717
log_string. as_bytes( )
704
718
) ;
705
719
}
@@ -714,7 +728,7 @@ mod tests {
714
728
writer. copy_bytes_to_start ( 3 , 2 ) ;
715
729
716
730
assert_eq ! (
717
- unsafe { assume_init_slice ( & writer. buffer[ ..10 ] ) } ,
731
+ unsafe { slice_assume_init_ref ( & writer. buffer[ ..10 ] ) } ,
718
732
"3423456789" . as_bytes( )
719
733
) ;
720
734
}
@@ -731,7 +745,7 @@ mod tests {
731
745
writer. copy_bytes_to_start ( 10 , 0 ) ;
732
746
733
747
assert_eq ! (
734
- unsafe { assume_init_slice ( & writer. buffer[ ..test_string. len( ) ] ) } ,
748
+ unsafe { slice_assume_init_ref ( & writer. buffer[ ..test_string. len( ) ] ) } ,
735
749
test_string. as_bytes( )
736
750
) ;
737
751
}
@@ -743,8 +757,4 @@ mod tests {
743
757
CStr :: from_bytes_with_nul ( b"tag\0 " ) . unwrap ( ) ,
744
758
)
745
759
}
746
-
747
- unsafe fn assume_init_slice < T > ( slice : & [ MaybeUninit < T > ] ) -> & [ T ] {
748
- & * ( slice as * const [ MaybeUninit < T > ] as * const [ T ] )
749
- }
750
760
}
0 commit comments