@@ -9,7 +9,7 @@ use std::os::unix::ffi::{OsStrExt, OsStringExt};
9
9
#[ cfg( windows) ]
10
10
use std:: os:: windows:: ffi:: { OsStrExt , OsStringExt } ;
11
11
12
- use rustc_target:: abi:: LayoutOf ;
12
+ use rustc_target:: abi:: { LayoutOf , Size } ;
13
13
14
14
use crate :: * ;
15
15
@@ -50,19 +50,19 @@ impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mi
50
50
pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriEvalContextExt < ' mir , ' tcx > {
51
51
/// Helper function to read an OsString from a null-terminated sequence of bytes, which is what
52
52
/// 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 >
54
54
where
55
55
' tcx : ' a ,
56
56
' mir : ' a ,
57
57
{
58
58
let this = self . eval_context_ref ( ) ;
59
- let bytes = this. memory . read_c_str ( scalar ) ?;
59
+ let bytes = this. read_c_str ( sptr ) ?;
60
60
bytes_to_os_str ( bytes)
61
61
}
62
62
63
63
/// Helper function to read an OsString from a 0x0000-terminated sequence of u16,
64
64
/// 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 >
66
66
where
67
67
' tcx : ' a ,
68
68
' mir : ' a ,
@@ -78,7 +78,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
78
78
Ok ( s. into ( ) )
79
79
}
80
80
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 ) ?;
82
82
u16vec_to_osstring ( u16_vec)
83
83
}
84
84
@@ -90,7 +90,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
90
90
fn write_os_str_to_c_str (
91
91
& mut self ,
92
92
os_str : & OsStr ,
93
- scalar : Scalar < Tag > ,
93
+ sptr : Scalar < Tag > ,
94
94
size : u64 ,
95
95
) -> InterpResult < ' tcx , ( bool , u64 ) > {
96
96
let bytes = os_str_to_bytes ( os_str) ?;
@@ -102,7 +102,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
102
102
}
103
103
self . eval_context_mut ( )
104
104
. memory
105
- . write_bytes ( scalar , bytes. iter ( ) . copied ( ) . chain ( iter:: once ( 0u8 ) ) ) ?;
105
+ . write_bytes ( sptr , bytes. iter ( ) . copied ( ) . chain ( iter:: once ( 0u8 ) ) ) ?;
106
106
Ok ( ( true , string_length) )
107
107
}
108
108
@@ -114,7 +114,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
114
114
fn write_os_str_to_wide_str (
115
115
& mut self ,
116
116
os_str : & OsStr ,
117
- scalar : Scalar < Tag > ,
117
+ sptr : Scalar < Tag > ,
118
118
size : u64 ,
119
119
) -> InterpResult < ' tcx , ( bool , u64 ) > {
120
120
#[ cfg( windows) ]
@@ -136,15 +136,27 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
136
136
// If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required
137
137
// 0x0000 terminator to memory would cause an out-of-bounds access.
138
138
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 {
140
141
return Ok ( ( false , string_length) ) ;
141
142
}
142
143
143
144
// 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 ) )
148
160
}
149
161
150
162
/// 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
178
190
}
179
191
180
192
/// 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 > >
182
194
where
183
195
' tcx : ' a ,
184
196
' mir : ' a ,
185
197
{
186
198
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 ) ?;
188
200
189
201
Ok ( match this. convert_path_separator ( Cow :: Borrowed ( os_str) , PathConversion :: TargetToHost ) {
190
202
Cow :: Borrowed ( x) => Cow :: Borrowed ( Path :: new ( x) ) ,
@@ -193,9 +205,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
193
205
}
194
206
195
207
/// 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 > {
197
209
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 ) ?;
199
211
200
212
Ok ( this
201
213
. convert_path_separator ( Cow :: Owned ( os_str) , PathConversion :: TargetToHost )
@@ -208,27 +220,27 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
208
220
fn write_path_to_c_str (
209
221
& mut self ,
210
222
path : & Path ,
211
- scalar : Scalar < Tag > ,
223
+ sptr : Scalar < Tag > ,
212
224
size : u64 ,
213
225
) -> InterpResult < ' tcx , ( bool , u64 ) > {
214
226
let this = self . eval_context_mut ( ) ;
215
227
let os_str = this
216
228
. 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)
218
230
}
219
231
220
232
/// Write a Path to the machine memory (as a null-terminated sequence of `u16`s),
221
233
/// adjusting path separators if needed.
222
234
fn write_path_to_wide_str (
223
235
& mut self ,
224
236
path : & Path ,
225
- scalar : Scalar < Tag > ,
237
+ sptr : Scalar < Tag > ,
226
238
size : u64 ,
227
239
) -> InterpResult < ' tcx , ( bool , u64 ) > {
228
240
let this = self . eval_context_mut ( ) ;
229
241
let os_str = this
230
242
. 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)
232
244
}
233
245
234
246
fn convert_path_separator < ' a > (
0 commit comments