@@ -163,7 +163,7 @@ impl FileDescription for AnonSocket {
163163} else {
164164// Blocking socketpair with writer and empty buffer.
165165// FIXME: blocking is currently not supported
166- throw_unsup_format ! ( "socketpair read: blocking isn't supported yet" ) ;
166+ throw_unsup_format ! ( "socketpair/pipe/pipe2 read: blocking isn't supported yet" ) ;
167167}
168168}
169169}
@@ -230,7 +230,7 @@ impl FileDescription for AnonSocket {
230230return ecx. set_last_error_and_return ( ErrorKind :: WouldBlock , dest) ;
231231} else {
232232// Blocking socketpair with a full buffer.
233- throw_unsup_format ! ( "socketpair write: blocking isn't supported yet" ) ;
233+ throw_unsup_format ! ( "socketpair/pipe/pipe2 write: blocking isn't supported yet" ) ;
234234}
235235}
236236// Remember this clock so `read` can synchronize with us.
@@ -267,21 +267,24 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
267267let this = self . eval_context_mut ( ) ;
268268
269269let domain = this. read_scalar ( domain) ?. to_i32 ( ) ?;
270- let mut type_ = this. read_scalar ( type_) ?. to_i32 ( ) ?;
270+ let mut flags = this. read_scalar ( type_) ?. to_i32 ( ) ?;
271271let protocol = this. read_scalar ( protocol) ?. to_i32 ( ) ?;
272272let sv = this. deref_pointer ( sv) ?;
273273
274274let mut is_sock_nonblock = false ;
275275
276- // Parse and remove the type flags that we support.
277- // SOCK_NONBLOCK only exists on Linux .
276+ // Interpret the flag. Every flag we recognize is "subtracted" from `flags`, so
277+ // if there is anything left at the end, that's an unsupported flag .
278278if this. tcx . sess . target . os == "linux" {
279- if type_ & this. eval_libc_i32 ( "SOCK_NONBLOCK" ) == this. eval_libc_i32 ( "SOCK_NONBLOCK" ) {
279+ // SOCK_NONBLOCK only exists on Linux.
280+ let sock_nonblock = this. eval_libc_i32 ( "SOCK_NONBLOCK" ) ;
281+ let sock_cloexec = this. eval_libc_i32 ( "SOCK_CLOEXEC" ) ;
282+ if flags & sock_nonblock == sock_nonblock {
280283 is_sock_nonblock = true ;
281- type_ &= !( this . eval_libc_i32 ( "SOCK_NONBLOCK" ) ) ;
284+ flags &= !sock_nonblock ;
282285}
283- if type_ & this . eval_libc_i32 ( "SOCK_CLOEXEC" ) == this . eval_libc_i32 ( "SOCK_CLOEXEC" ) {
284- type_ &= !( this . eval_libc_i32 ( "SOCK_CLOEXEC" ) ) ;
286+ if flags & sock_cloexec == sock_cloexec {
287+ flags &= !sock_cloexec ;
285288}
286289}
287290
@@ -294,11 +297,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
294297 and AF_LOCAL are allowed",
295298 domain
296299) ;
297- } else if type_ != this. eval_libc_i32 ( "SOCK_STREAM" ) {
300+ } else if flags != this. eval_libc_i32 ( "SOCK_STREAM" ) {
298301throw_unsup_format ! (
299302"socketpair: type {:#x} is unsupported, only SOCK_STREAM, \
300303 SOCK_CLOEXEC and SOCK_NONBLOCK are allowed",
301- type_
304+ flags
302305) ;
303306} else if protocol != 0 {
304307throw_unsup_format ! (
@@ -347,14 +350,26 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
347350let this = self . eval_context_mut ( ) ;
348351
349352let pipefd = this. deref_pointer_as ( pipefd, this. machine . layouts . i32 ) ?;
350- let flags = match flags {
353+ let mut flags = match flags {
351354Some ( flags) => this. read_scalar ( flags) ?. to_i32 ( ) ?,
352355None => 0 ,
353356} ;
354357
355- // As usual we ignore CLOEXEC.
356358let cloexec = this. eval_libc_i32 ( "O_CLOEXEC" ) ;
357- if flags != 0 && flags != cloexec {
359+ let o_nonblock = this. eval_libc_i32 ( "O_NONBLOCK" ) ;
360+
361+ // Interpret the flag. Every flag we recognize is "subtracted" from `flags`, so
362+ // if there is anything left at the end, that's an unsupported flag.
363+ let mut is_nonblock = false ;
364+ if flags & o_nonblock == o_nonblock {
365+ is_nonblock = true ;
366+ flags &= !o_nonblock;
367+ }
368+ // As usual we ignore CLOEXEC.
369+ if flags & cloexec == cloexec {
370+ flags &= !cloexec;
371+ }
372+ if flags != 0 {
358373throw_unsup_format ! ( "unsupported flags in `pipe2`" ) ;
359374}
360375
@@ -365,13 +380,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
365380readbuf : Some ( RefCell :: new ( Buffer :: new ( ) ) ) ,
366381peer_fd : OnceCell :: new ( ) ,
367382peer_lost_data : Cell :: new ( false ) ,
368- is_nonblock : false ,
383+ is_nonblock,
369384} ) ;
370385let fd1 = fds. new_ref ( AnonSocket {
371386readbuf : None ,
372387peer_fd : OnceCell :: new ( ) ,
373388peer_lost_data : Cell :: new ( false ) ,
374- is_nonblock : false ,
389+ is_nonblock,
375390} ) ;
376391
377392// Make the file descriptions point to each other.
0 commit comments