@@ -264,11 +264,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
264264 return this. set_last_error_and_return ( LibcError ( "EBADF" ) , dest) ;
265265 } ;
266266
267+ // Handle the zero-sized case. The man page says:
268+ // > If count is zero, read() may detect the errors described below. In the absence of any
269+ // > errors, or if read() does not check for errors, a read() with a count of 0 returns zero
270+ // > and has no other effects.
271+ if count == 0 {
272+ this. write_null ( dest) ?;
273+ return interp_ok ( ( ) ) ;
274+ }
267275 // Non-deterministically decide to further reduce the count, simulating a partial read (but
268- // never to 0, that has different behavior ).
276+ // never to 0, that would indicate EOF ).
269277 let count =
270278 if fd. nondet_short_accesses ( ) && count >= 2 && this. machine . rng . get_mut ( ) . random ( ) {
271- count / 2
279+ count / 2 // since `count` is at least 2, the result is still at least 1
272280 } else {
273281 count
274282 } ;
@@ -338,8 +346,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
338346 return this. set_last_error_and_return ( LibcError ( "EBADF" ) , dest) ;
339347 } ;
340348
341- // Non-deterministically decide to further reduce the count, simulating a partial write (but
342- // never to 0, that has different behavior).
349+ // Handle the zero-sized case. The man page says:
350+ // > If count is zero and fd refers to a regular file, then write() may return a failure
351+ // > status if one of the errors below is detected. If no errors are detected, or error
352+ // > detection is not performed, 0 is returned without causing any other effect. If count
353+ // > is zero and fd refers to a file other than a regular file, the results are not
354+ // > specified.
355+ if count == 0 {
356+ // For now let's not open the can of worms of what exactly "not specified" could mean...
357+ this. write_null ( dest) ?;
358+ return interp_ok ( ( ) ) ;
359+ }
360+ // Non-deterministically decide to further reduce the count, simulating a partial write.
361+ // We avoid reducing the write size to 0: the docs seem to be entirely fine with that,
362+ // but the standard library is not (https://github.com/rust-lang/rust/issues/145959).
343363 let count =
344364 if fd. nondet_short_accesses ( ) && count >= 2 && this. machine . rng . get_mut ( ) . random ( ) {
345365 count / 2
0 commit comments