@@ -212,18 +212,35 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> {
212212 struct Align8 < T > ( T ) ;
213213 let mut data = Align8 ( [ 0u8 ; MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize ] ) ;
214214 let db = data. 0 . as_mut_ptr ( ) as * mut REPARSE_MOUNTPOINT_DATA_BUFFER ;
215- let buf = core:: ptr:: addr_of_mut!( ( * db) . ReparseTarget ) as * mut u16 ;
216- let mut i = 0 ;
215+ let end = db. cast :: < u8 > ( ) . add ( MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize ) ;
216+ let reparse_target_slice = {
217+ let buf_start = core:: ptr:: addr_of_mut!( ( * db) . ReparseTarget ) . cast :: < u16 > ( ) ;
218+ // Compute offset in bytes and then divide so that we round down
219+ // rather than hit any UB (admittedly this arithmetic should work
220+ // out so that this isn't necessary)
221+ let buf_len_bytes =
222+ usize:: try_from ( end. offset_from ( buf_start. cast :: < u8 > ( ) ) ) . unwrap ( ) ;
223+ let buf_len_wchars = buf_len_bytes / core:: mem:: size_of :: < u16 > ( ) ;
224+ core:: slice:: from_raw_parts_mut ( buf_start, buf_len_wchars)
225+ } ;
226+
217227 // FIXME: this conversion is very hacky
218- let v = br"\??\" ;
219- let v = v. iter ( ) . map ( |x| * x as u16 ) ;
220- for c in v. chain ( target. as_os_str ( ) . encode_wide ( ) . skip ( 4 ) ) {
221- * buf. offset ( i) = c;
228+ let iter = br"\??\"
229+ . iter ( )
230+ . map ( |x| * x as u16 )
231+ . chain ( path. iter ( ) . copied ( ) )
232+ . chain ( core:: iter:: once ( 0 ) ) ;
233+ let mut i = 0 ;
234+ for c in iter {
235+ if i >= reparse_target_slice. len ( ) {
236+ return Err ( io:: Error :: new (
237+ io:: ErrorKind :: Other ,
238+ format ! ( "path too long for reparse target: {target:?}" ) ,
239+ ) ) ;
240+ }
241+ reparse_target_slice[ i] = c;
222242 i += 1 ;
223243 }
224- * buf. offset ( i) = 0 ;
225- i += 1 ;
226-
227244 ( * db) . ReparseTag = IO_REPARSE_TAG_MOUNT_POINT ;
228245 ( * db) . ReparseTargetMaximumLength = ( i * 2 ) as u16 ;
229246 ( * db) . ReparseTargetLength = ( ( i - 1 ) * 2 ) as u16 ;
0 commit comments