@@ -127,17 +127,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
127127 let tcx = & { this. tcx . tcx } ;
128128
129129 let buf = this. force_ptr ( this. read_scalar ( buf_op) ?. not_undef ( ) ?) ?;
130- let size = this. read_scalar ( size_op) ?. to_usize ( & * this . tcx ) ?;
130+ let size = this. read_scalar ( size_op) ?. to_usize ( & * tcx) ?;
131131 // If we cannot get the current directory, we return null
132132 match env:: current_dir ( ) {
133133 Ok ( cwd) => {
134134 // It is not clear what happens with non-utf8 paths here
135135 let mut bytes = cwd. display ( ) . to_string ( ) . into_bytes ( ) ;
136- // If the buffer is smaller or equal than the path, we return null.
136+ // If `size` is smaller or equal than the `bytes.len()`, writing `bytes` plus the
137+ // required null terminator to memory using the `buf` pointer would cause an
138+ // overflow. The desired behavior in this case is to return null.
137139 if ( bytes. len ( ) as u64 ) < size {
138140 // We add a `/0` terminator
139141 bytes. push ( 0 ) ;
140- // This is ok because the buffer is larger than the path with the null terminator.
142+ // This is ok because the buffer was strictly larger than `bytes`, so after
143+ // adding the null terminator, the buffer size is larger or equal to
144+ // `bytes.len()`, meaning that `bytes` actually fit inside tbe buffer.
141145 this. memory_mut ( )
142146 . get_mut ( buf. alloc_id ) ?
143147 . write_bytes ( tcx, buf, & bytes) ?;
@@ -148,7 +152,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
148152 }
149153 Err ( e) => this. consume_io_error ( e) ?,
150154 }
151- Ok ( Scalar :: ptr_null ( & * this . tcx ) )
155+ Ok ( Scalar :: ptr_null ( & * tcx) )
152156 }
153157
154158 fn chdir ( & mut self , path_op : OpTy < ' tcx , Tag > ) -> InterpResult < ' tcx , i32 > {
0 commit comments