@@ -1403,24 +1403,40 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> {
14031403 opts. custom_flags ( c:: FILE_FLAG_OPEN_REPARSE_POINT | c:: FILE_FLAG_BACKUP_SEMANTICS ) ;
14041404 let f = File :: open ( junction, & opts) ?;
14051405 let h = f. as_inner ( ) . as_raw_handle ( ) ;
1406-
14071406 unsafe {
14081407 let mut data = Align8 ( [ MaybeUninit :: < u8 > :: uninit ( ) ; c:: MAXIMUM_REPARSE_DATA_BUFFER_SIZE ] ) ;
14091408 let data_ptr = data. 0 . as_mut_ptr ( ) ;
1409+ let data_end = data_ptr. add ( c:: MAXIMUM_REPARSE_DATA_BUFFER_SIZE ) ;
14101410 let db = data_ptr. cast :: < c:: REPARSE_MOUNTPOINT_DATA_BUFFER > ( ) ;
14111411 // Zero the header to ensure it's fully initialized, including reserved parameters.
14121412 * db = mem:: zeroed ( ) ;
1413- let buf = ptr:: addr_of_mut!( ( * db) . ReparseTarget ) . cast :: < c:: WCHAR > ( ) ;
1414- let mut i = 0 ;
1413+ let reparse_target_slice = {
1414+ let buf_start = ptr:: addr_of_mut!( ( * db) . ReparseTarget ) . cast :: < c:: WCHAR > ( ) ;
1415+ // Compute offset in bytes and then divide so that we round down
1416+ // rather than hit any UB (admittedly this arithmetic should work
1417+ // out so that this isn't necessary)
1418+ let buf_len_bytes = usize:: try_from ( data_end. byte_offset_from ( buf_start) ) . unwrap ( ) ;
1419+ let buf_len_wchars = buf_len_bytes / core:: mem:: size_of :: < c:: WCHAR > ( ) ;
1420+ core:: slice:: from_raw_parts_mut ( buf_start, buf_len_wchars)
1421+ } ;
1422+
14151423 // FIXME: this conversion is very hacky
1416- let v = br"\??\" ;
1417- let v = v. iter ( ) . map ( |x| * x as u16 ) ;
1418- for c in v. chain ( original. as_os_str ( ) . encode_wide ( ) ) {
1419- * buf. add ( i) = c;
1424+ let iter = br"\??\"
1425+ . iter ( )
1426+ . map ( |x| * x as u16 )
1427+ . chain ( original. as_os_str ( ) . encode_wide ( ) )
1428+ . chain ( core:: iter:: once ( 0 ) ) ;
1429+ let mut i = 0 ;
1430+ for c in iter {
1431+ if i >= reparse_target_slice. len ( ) {
1432+ return Err ( crate :: io:: const_io_error!(
1433+ crate :: io:: ErrorKind :: InvalidFilename ,
1434+ "Input filename is too long"
1435+ ) ) ;
1436+ }
1437+ reparse_target_slice[ i] = c;
14201438 i += 1 ;
14211439 }
1422- * buf. add ( i) = 0 ;
1423- i += 1 ;
14241440 ( * db) . ReparseTag = c:: IO_REPARSE_TAG_MOUNT_POINT ;
14251441 ( * db) . ReparseTargetMaximumLength = ( i * 2 ) as c:: WORD ;
14261442 ( * db) . ReparseTargetLength = ( ( i - 1 ) * 2 ) as c:: WORD ;
0 commit comments