@@ -118,13 +118,29 @@ fn mutex_get_id<'tcx>(
118
118
ecx : & mut MiriInterpCx < ' tcx > ,
119
119
mutex_op : & OpTy < ' tcx > ,
120
120
) -> InterpResult < ' tcx , MutexId > {
121
+ let address = ecx. deref_pointer_as ( mutex_op, ecx. libc_ty_layout ( "pthread_mutex_t" ) ) ?. ptr ( ) ;
122
+ let kind = MutexKind :: new ( mutex_get_kind ( ecx, mutex_op) ?) ;
121
123
ecx. mutex_get_or_create_id (
122
124
mutex_op,
123
125
ecx. libc_ty_layout ( "pthread_mutex_t" ) ,
124
126
mutex_id_offset ( ecx) ?,
127
+ || Ok ( Some ( AdditionalMutexData { kind, address } ) ) ,
125
128
)
126
129
}
127
130
131
+ fn mutex_check_moved < ' tcx > (
132
+ ecx : & mut MiriInterpCx < ' tcx > ,
133
+ mutex_op : & OpTy < ' tcx > ,
134
+ id : MutexId ,
135
+ ) -> InterpResult < ' tcx , ( ) > {
136
+ let addr = ecx. deref_pointer_as ( mutex_op, ecx. libc_ty_layout ( "pthread_mutex_t" ) ) ?. ptr ( ) . addr ( ) ;
137
+ let data = ecx. mutex_get_data ( id) . expect ( "data should be always exist for pthreads" ) ;
138
+ if data. address . addr ( ) != addr {
139
+ throw_ub_format ! ( "pthread_mutex_t can't be moved after first use" )
140
+ }
141
+ Ok ( ( ) )
142
+ }
143
+
128
144
fn mutex_reset_id < ' tcx > (
129
145
ecx : & mut MiriInterpCx < ' tcx > ,
130
146
mutex_op : & OpTy < ' tcx > ,
@@ -457,6 +473,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
457
473
458
474
mutex_set_kind ( this, mutex_op, kind) ?;
459
475
476
+ // Fetch (and ignore) the mutex's id to go through the initialization
477
+ // code, and thus register the mutex's address.
478
+ mutex_get_id ( this, mutex_op) ?;
479
+
460
480
Ok ( ( ) )
461
481
}
462
482
@@ -467,8 +487,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
467
487
) -> InterpResult < ' tcx > {
468
488
let this = self . eval_context_mut ( ) ;
469
489
470
- let kind = mutex_get_kind ( this, mutex_op) ?;
471
490
let id = mutex_get_id ( this, mutex_op) ?;
491
+ let kind = this
492
+ . mutex_get_data ( id)
493
+ . expect ( "data should always exist for pthread mutexes" )
494
+ . kind
495
+ . to_i32 ( ) ;
496
+
497
+ mutex_check_moved ( this, mutex_op, id) ?;
472
498
473
499
let ret = if this. mutex_is_locked ( id) {
474
500
let owner_thread = this. mutex_get_owner ( id) ;
@@ -504,8 +530,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
504
530
fn pthread_mutex_trylock ( & mut self , mutex_op : & OpTy < ' tcx > ) -> InterpResult < ' tcx , Scalar > {
505
531
let this = self . eval_context_mut ( ) ;
506
532
507
- let kind = mutex_get_kind ( this, mutex_op) ?;
508
533
let id = mutex_get_id ( this, mutex_op) ?;
534
+ let kind = this
535
+ . mutex_get_data ( id)
536
+ . expect ( "data should always exist for pthread mutexes" )
537
+ . kind
538
+ . to_i32 ( ) ;
539
+
540
+ mutex_check_moved ( this, mutex_op, id) ?;
509
541
510
542
Ok ( Scalar :: from_i32 ( if this. mutex_is_locked ( id) {
511
543
let owner_thread = this. mutex_get_owner ( id) ;
@@ -536,8 +568,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
536
568
fn pthread_mutex_unlock ( & mut self , mutex_op : & OpTy < ' tcx > ) -> InterpResult < ' tcx , Scalar > {
537
569
let this = self . eval_context_mut ( ) ;
538
570
539
- let kind = mutex_get_kind ( this, mutex_op) ?;
540
571
let id = mutex_get_id ( this, mutex_op) ?;
572
+ let kind = this
573
+ . mutex_get_data ( id)
574
+ . expect ( "data should always exist for pthread mutexes" )
575
+ . kind
576
+ . to_i32 ( ) ;
577
+
578
+ mutex_check_moved ( this, mutex_op, id) ?;
541
579
542
580
if let Some ( _old_locked_count) = this. mutex_unlock ( id) ? {
543
581
// The mutex was locked by the current thread.
0 commit comments