@@ -264,11 +264,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
264
264
return this. set_last_error_and_return ( LibcError ( "EBADF" ) , dest) ;
265
265
} ;
266
266
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
+ }
267
275
// 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 ).
269
277
let count =
270
278
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
272
280
} else {
273
281
count
274
282
} ;
@@ -338,8 +346,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
338
346
return this. set_last_error_and_return ( LibcError ( "EBADF" ) , dest) ;
339
347
} ;
340
348
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).
343
363
let count =
344
364
if fd. nondet_short_accesses ( ) && count >= 2 && this. machine . rng . get_mut ( ) . random ( ) {
345
365
count / 2
0 commit comments