@@ -543,34 +543,41 @@ pub fn copy_and_replace_cstring_placeholder(
543
543
let old_prefix = prefix_placeholder. as_bytes ( ) ;
544
544
let new_prefix = target_prefix. as_bytes ( ) ;
545
545
546
- // Compute the padding required when replacing the old prefix with the new one. If the old
547
- // prefix is longer than the new one we need to add padding to ensure that the entire part
548
- // will hold the same number of bytes. We do this by adding '\0's (e.g. nul terminators). This
549
- // ensures that the text will remain a valid nul-terminated string.
550
- let padding = vec ! [ b'\0' ; old_prefix. len( ) . saturating_sub( new_prefix. len( ) ) ] ;
551
-
552
546
loop {
553
547
if let Some ( index) = memchr:: memmem:: find ( source_bytes, old_prefix) {
548
+ // write all bytes up to the old prefix, followed by the new prefix.
549
+ destination. write_all ( & source_bytes[ ..index] ) ?;
550
+
554
551
// Find the end of the c-style string. The nul terminator basically.
555
552
let mut end = index + old_prefix. len ( ) ;
556
553
while end < source_bytes. len ( ) && source_bytes[ end] != b'\0' {
557
554
end += 1 ;
558
555
}
559
556
560
- // Determine the total length of the c-string.
561
- let len = end - index;
557
+ let mut out = Vec :: new ( ) ;
558
+ let mut old_bytes = & source_bytes[ index..end] ;
559
+ let old_len = old_bytes. len ( ) ;
562
560
563
- // Get the suffix part (this is the text after the prefix by up until the nul
564
- // terminator). E.g. in `old-prefix/some/path\0` the suffix would be `/some/path`.
565
- let suffix = & source_bytes[ index + old_prefix. len ( ) ..end] ;
561
+ // replace all occurrences of the old prefix with the new prefix
562
+ while let Some ( index) = memchr:: memmem:: find ( old_bytes, old_prefix) {
563
+ out. write_all ( & old_bytes[ ..index] ) ?;
564
+ out. write_all ( new_prefix) ?;
565
+ old_bytes = & old_bytes[ index + old_prefix. len ( ) ..] ;
566
+ }
567
+ out. write_all ( old_bytes) ?;
568
+ // write everything up to the old length
569
+ if out. len ( ) > old_len {
570
+ destination. write_all ( & out[ ..old_len] ) ?;
571
+ } else {
572
+ destination. write_all ( & out) ?;
573
+ }
566
574
567
- // Write all bytes up to the old prefix, then the new prefix followed by suffix and
568
- // padding.
569
- destination. write_all ( & source_bytes[ ..index] ) ?;
570
- destination. write_all ( & new_prefix[ ..len. min ( new_prefix. len ( ) ) ] ) ?;
571
- destination
572
- . write_all ( & suffix[ ..len. saturating_sub ( new_prefix. len ( ) ) . min ( suffix. len ( ) ) ] ) ?;
573
- destination. write_all ( & padding) ?;
575
+ // Compute the padding required when replacing the old prefix(es) with the new one. If the old
576
+ // prefix is longer than the new one we need to add padding to ensure that the entire part
577
+ // will hold the same number of bytes. We do this by adding '\0's (e.g. nul terminators). This
578
+ // ensures that the text will remain a valid nul-terminated string.
579
+ let padding = old_len. saturating_sub ( out. len ( ) ) ;
580
+ destination. write_all ( & vec ! [ 0 ; padding] ) ?;
574
581
575
582
// Continue with the rest of the bytes.
576
583
source_bytes = & source_bytes[ end..] ;
@@ -662,4 +669,16 @@ mod test {
662
669
. unwrap ( ) ;
663
670
assert_eq ! ( & output. into_inner( ) , expected_output) ;
664
671
}
672
+
673
+ #[ test]
674
+ fn replace_binary_path_var ( ) {
675
+ let input =
676
+ b"beginrandomdataPATH=/placeholder/etc/share:/placeholder/bin/:\x00 somemoretext" ;
677
+ let mut output = Cursor :: new ( Vec :: new ( ) ) ;
678
+ super :: copy_and_replace_cstring_placeholder ( input, & mut output, "/placeholder" , "/target" )
679
+ . unwrap ( ) ;
680
+ let out = & output. into_inner ( ) ;
681
+ assert_eq ! ( out, b"beginrandomdataPATH=/target/etc/share:/target/bin/:\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 somemoretext" ) ;
682
+ assert_eq ! ( out. len( ) , input. len( ) ) ;
683
+ }
665
684
}
0 commit comments