@@ -9,7 +9,7 @@ use std::os::unix::ffi::{OsStrExt, OsStringExt};
99#[ cfg( windows) ]
1010use std:: os:: windows:: ffi:: { OsStrExt , OsStringExt } ;
1111
12- use rustc_target:: abi:: LayoutOf ;
12+ use rustc_target:: abi:: { LayoutOf , Size } ;
1313
1414use crate :: * ;
1515
@@ -50,19 +50,19 @@ impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mi
5050pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriEvalContextExt < ' mir , ' tcx > {
5151 /// Helper function to read an OsString from a null-terminated sequence of bytes, which is what
5252 /// the Unix APIs usually handle.
53- fn read_os_str_from_c_str < ' a > ( & ' a self , scalar : Scalar < Tag > ) -> InterpResult < ' tcx , & ' a OsStr >
53+ fn read_os_str_from_c_str < ' a > ( & ' a self , sptr : Scalar < Tag > ) -> InterpResult < ' tcx , & ' a OsStr >
5454 where
5555 ' tcx : ' a ,
5656 ' mir : ' a ,
5757 {
5858 let this = self . eval_context_ref ( ) ;
59- let bytes = this. memory . read_c_str ( scalar ) ?;
59+ let bytes = this. read_c_str ( sptr ) ?;
6060 bytes_to_os_str ( bytes)
6161 }
6262
6363 /// Helper function to read an OsString from a 0x0000-terminated sequence of u16,
6464 /// which is what the Windows APIs usually handle.
65- fn read_os_str_from_wide_str < ' a > ( & ' a self , scalar : Scalar < Tag > ) -> InterpResult < ' tcx , OsString >
65+ fn read_os_str_from_wide_str < ' a > ( & ' a self , sptr : Scalar < Tag > ) -> InterpResult < ' tcx , OsString >
6666 where
6767 ' tcx : ' a ,
6868 ' mir : ' a ,
@@ -78,7 +78,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
7878 Ok ( s. into ( ) )
7979 }
8080
81- let u16_vec = self . eval_context_ref ( ) . memory . read_wide_str ( scalar ) ?;
81+ let u16_vec = self . eval_context_ref ( ) . read_wide_str ( sptr ) ?;
8282 u16vec_to_osstring ( u16_vec)
8383 }
8484
@@ -90,7 +90,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
9090 fn write_os_str_to_c_str (
9191 & mut self ,
9292 os_str : & OsStr ,
93- scalar : Scalar < Tag > ,
93+ sptr : Scalar < Tag > ,
9494 size : u64 ,
9595 ) -> InterpResult < ' tcx , ( bool , u64 ) > {
9696 let bytes = os_str_to_bytes ( os_str) ?;
@@ -102,7 +102,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
102102 }
103103 self . eval_context_mut ( )
104104 . memory
105- . write_bytes ( scalar , bytes. iter ( ) . copied ( ) . chain ( iter:: once ( 0u8 ) ) ) ?;
105+ . write_bytes ( sptr , bytes. iter ( ) . copied ( ) . chain ( iter:: once ( 0u8 ) ) ) ?;
106106 Ok ( ( true , string_length) )
107107 }
108108
@@ -114,7 +114,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
114114 fn write_os_str_to_wide_str (
115115 & mut self ,
116116 os_str : & OsStr ,
117- scalar : Scalar < Tag > ,
117+ sptr : Scalar < Tag > ,
118118 size : u64 ,
119119 ) -> InterpResult < ' tcx , ( bool , u64 ) > {
120120 #[ cfg( windows) ]
@@ -136,15 +136,27 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
136136 // If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required
137137 // 0x0000 terminator to memory would cause an out-of-bounds access.
138138 let string_length = u64:: try_from ( u16_vec. len ( ) ) . unwrap ( ) ;
139- if size <= string_length {
139+ let string_length = string_length. checked_add ( 1 ) . unwrap ( ) ;
140+ if size < string_length {
140141 return Ok ( ( false , string_length) ) ;
141142 }
142143
143144 // Store the UTF-16 string.
144- self . eval_context_mut ( )
145- . memory
146- . write_u16s ( scalar, u16_vec. into_iter ( ) . chain ( iter:: once ( 0x0000 ) ) ) ?;
147- Ok ( ( true , string_length) )
145+ let size2 = Size :: from_bytes ( 2 ) ;
146+ let this = self . eval_context_mut ( ) ;
147+ let tcx = & * this. tcx ;
148+ let ptr = this. force_ptr ( sptr) ?; // we need to write at least the 0 terminator
149+ let alloc = this. memory . get_raw_mut ( ptr. alloc_id ) ?;
150+ for ( offset, wchar) in u16_vec. into_iter ( ) . chain ( iter:: once ( 0x0000 ) ) . enumerate ( ) {
151+ let offset = u64:: try_from ( offset) . unwrap ( ) ;
152+ alloc. write_scalar (
153+ tcx,
154+ ptr. offset ( size2 * offset, tcx) ?,
155+ Scalar :: from_u16 ( wchar) . into ( ) ,
156+ size2,
157+ ) ?;
158+ }
159+ Ok ( ( true , string_length - 1 ) )
148160 }
149161
150162 /// Allocate enough memory to store the given `OsStr` as a null-terminated sequence of bytes.
@@ -178,13 +190,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
178190 }
179191
180192 /// Read a null-terminated sequence of bytes, and perform path separator conversion if needed.
181- fn read_path_from_c_str < ' a > ( & ' a self , scalar : Scalar < Tag > ) -> InterpResult < ' tcx , Cow < ' a , Path > >
193+ fn read_path_from_c_str < ' a > ( & ' a self , sptr : Scalar < Tag > ) -> InterpResult < ' tcx , Cow < ' a , Path > >
182194 where
183195 ' tcx : ' a ,
184196 ' mir : ' a ,
185197 {
186198 let this = self . eval_context_ref ( ) ;
187- let os_str = this. read_os_str_from_c_str ( scalar ) ?;
199+ let os_str = this. read_os_str_from_c_str ( sptr ) ?;
188200
189201 Ok ( match this. convert_path_separator ( Cow :: Borrowed ( os_str) , PathConversion :: TargetToHost ) {
190202 Cow :: Borrowed ( x) => Cow :: Borrowed ( Path :: new ( x) ) ,
@@ -193,9 +205,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
193205 }
194206
195207 /// Read a null-terminated sequence of `u16`s, and perform path separator conversion if needed.
196- fn read_path_from_wide_str ( & self , scalar : Scalar < Tag > ) -> InterpResult < ' tcx , PathBuf > {
208+ fn read_path_from_wide_str ( & self , sptr : Scalar < Tag > ) -> InterpResult < ' tcx , PathBuf > {
197209 let this = self . eval_context_ref ( ) ;
198- let os_str = this. read_os_str_from_wide_str ( scalar ) ?;
210+ let os_str = this. read_os_str_from_wide_str ( sptr ) ?;
199211
200212 Ok ( this
201213 . convert_path_separator ( Cow :: Owned ( os_str) , PathConversion :: TargetToHost )
@@ -208,27 +220,27 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
208220 fn write_path_to_c_str (
209221 & mut self ,
210222 path : & Path ,
211- scalar : Scalar < Tag > ,
223+ sptr : Scalar < Tag > ,
212224 size : u64 ,
213225 ) -> InterpResult < ' tcx , ( bool , u64 ) > {
214226 let this = self . eval_context_mut ( ) ;
215227 let os_str = this
216228 . convert_path_separator ( Cow :: Borrowed ( path. as_os_str ( ) ) , PathConversion :: HostToTarget ) ;
217- this. write_os_str_to_c_str ( & os_str, scalar , size)
229+ this. write_os_str_to_c_str ( & os_str, sptr , size)
218230 }
219231
220232 /// Write a Path to the machine memory (as a null-terminated sequence of `u16`s),
221233 /// adjusting path separators if needed.
222234 fn write_path_to_wide_str (
223235 & mut self ,
224236 path : & Path ,
225- scalar : Scalar < Tag > ,
237+ sptr : Scalar < Tag > ,
226238 size : u64 ,
227239 ) -> InterpResult < ' tcx , ( bool , u64 ) > {
228240 let this = self . eval_context_mut ( ) ;
229241 let os_str = this
230242 . convert_path_separator ( Cow :: Borrowed ( path. as_os_str ( ) ) , PathConversion :: HostToTarget ) ;
231- this. write_os_str_to_wide_str ( & os_str, scalar , size)
243+ this. write_os_str_to_wide_str ( & os_str, sptr , size)
232244 }
233245
234246 fn convert_path_separator < ' a > (
0 commit comments