Skip to content

Commit aface90

Browse files
committed
Auto merge of #121199 - RalfJung:ref-to-vtable-fn, r=<try>
const-eval: error when encountering references to functions / vtables Such references sound like an exceedingly bad idea... just use raw pointers if you must do things like this. But we should crater this, to be on the safe side.
2 parents d2e8ecd + 6563788 commit aface90

File tree

6 files changed

+68
-18
lines changed

6 files changed

+68
-18
lines changed

compiler/rustc_const_eval/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,8 +464,10 @@ const_eval_validation_out_of_range = {$front_matter}: encountered {$value}, but
464464
const_eval_validation_partial_pointer = {$front_matter}: encountered a partial pointer or a mix of pointers
465465
const_eval_validation_pointer_as_int = {$front_matter}: encountered a pointer, but {$expected}
466466
const_eval_validation_ptr_out_of_range = {$front_matter}: encountered a pointer, but expected something that cannot possibly fail to be {$in_range}
467+
const_eval_validation_ref_to_function = {$front_matter}: encountered a reference pointing to a function
467468
const_eval_validation_ref_to_static = {$front_matter}: encountered a reference pointing to a static variable in a constant
468469
const_eval_validation_ref_to_uninhabited = {$front_matter}: encountered a reference pointing to uninhabited type {$ty}
470+
const_eval_validation_ref_to_vtable = {$front_matter}: encountered a reference pointing to a vtable
469471
const_eval_validation_unaligned_box = {$front_matter}: encountered an unaligned box (required {$required_bytes} byte alignment but found {$found_bytes})
470472
const_eval_validation_unaligned_ref = {$front_matter}: encountered an unaligned reference (required {$required_bytes} byte alignment but found {$found_bytes})
471473
const_eval_validation_uninhabited_enum_variant = {$front_matter}: encountered an uninhabited enum variant

compiler/rustc_const_eval/src/errors.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,8 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
614614
PartialPointer => const_eval_validation_partial_pointer,
615615
ConstRefToMutable => const_eval_validation_const_ref_to_mutable,
616616
ConstRefToExtern => const_eval_validation_const_ref_to_extern,
617+
RefToFunction => const_eval_validation_ref_to_function,
618+
RefToVtable => const_eval_validation_ref_to_vtable,
617619
MutableRefInConstOrStatic => const_eval_validation_mutable_ref_in_const_or_static,
618620
MutableRefToImmutable => const_eval_validation_mutable_ref_to_immutable,
619621
NullFnPtr => const_eval_validation_null_fn_ptr,
@@ -771,6 +773,8 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
771773
| MutableRefInConstOrStatic
772774
| ConstRefToMutable
773775
| ConstRefToExtern
776+
| RefToFunction
777+
| RefToVtable
774778
| MutableRefToImmutable
775779
| NullFnPtr
776780
| NeverVal

compiler/rustc_const_eval/src/interpret/validity.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -502,9 +502,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
502502
if is_mut { Mutability::Mut } else { Mutability::Not }
503503
}
504504
GlobalAlloc::Memory(alloc) => alloc.inner().mutability,
505-
GlobalAlloc::Function(..) | GlobalAlloc::VTable(..) => {
506-
// These are immutable, we better don't allow mutable pointers here.
507-
Mutability::Not
505+
GlobalAlloc::Function(..) => {
506+
throw_validation_failure!(self.path, RefToFunction);
507+
}
508+
GlobalAlloc::VTable(..) => {
509+
throw_validation_failure!(self.path, RefToVtable);
508510
}
509511
};
510512
// Mutability check.

compiler/rustc_middle/src/mir/interpret/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,8 @@ pub enum ValidationErrorKind<'tcx> {
425425
ConstRefToExtern,
426426
MutableRefToImmutable,
427427
UnsafeCellInImmutable,
428+
RefToFunction,
429+
RefToVtable,
428430
NullFnPtr,
429431
NeverVal,
430432
NullablePtrOutOfRange { range: WrappingRange, max_value: u128 },

tests/ui/consts/const-eval/ub-ref-ptr.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@ const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
2222

2323
const NULL: &u16 = unsafe { mem::transmute(0usize) };
2424
//~^ ERROR it is undefined behavior to use this value
25+
//~| null reference
2526

2627
const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
2728
//~^ ERROR it is undefined behavior to use this value
29+
//~| null box
2830

2931

3032
// It is very important that we reject this: We do promote `&(4 * REF_AS_USIZE)`,
@@ -41,23 +43,28 @@ const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize],
4143

4244
const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
4345
//~^ ERROR it is undefined behavior to use this value
46+
//~| dangling reference
4447

4548
const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
4649
//~^ ERROR it is undefined behavior to use this value
50+
//~| dangling box
4751

4852
const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init };
4953
//~^ ERROR evaluation of constant value failed
5054
//~| uninitialized
5155

5256
const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
5357
//~^ ERROR it is undefined behavior to use this value
58+
//~| encountered null pointer, but expected a function pointer
5459
const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init };
5560
//~^ ERROR evaluation of constant value failed
5661
//~| uninitialized
5762
const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
5863
//~^ ERROR it is undefined behavior to use this value
64+
//~| expected a function pointer
5965
const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
6066
//~^ ERROR it is undefined behavior to use this value
67+
//~| expected a function pointer
6168

6269

6370
const UNALIGNED_READ: () = unsafe {
@@ -66,5 +73,16 @@ const UNALIGNED_READ: () = unsafe {
6673
ptr.read(); //~ inside `UNALIGNED_READ`
6774
};
6875

76+
const POINTS_TO_FUNCTION: &() = unsafe {
77+
//~^ ERROR it is undefined behavior to use this value
78+
//~| function
79+
mem::transmute(main as fn())
80+
};
81+
const POINTS_TO_VTABLE: (&(), &()) = unsafe {
82+
//~^ ERROR it is undefined behavior to use this value
83+
//~| vtable
84+
mem::transmute(&() as &dyn Send)
85+
};
86+
6987

7088
fn main() {}

tests/ui/consts/const-eval/ub-ref-ptr.stderr

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
3232
}
3333

3434
error[E0080]: it is undefined behavior to use this value
35-
--> $DIR/ub-ref-ptr.rs:26:1
35+
--> $DIR/ub-ref-ptr.rs:27:1
3636
|
3737
LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
3838
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box
@@ -43,7 +43,7 @@ LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
4343
}
4444

4545
error[E0080]: evaluation of constant value failed
46-
--> $DIR/ub-ref-ptr.rs:33:1
46+
--> $DIR/ub-ref-ptr.rs:35:1
4747
|
4848
LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
4949
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
@@ -52,7 +52,7 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
5252
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
5353

5454
error[E0080]: evaluation of constant value failed
55-
--> $DIR/ub-ref-ptr.rs:36:39
55+
--> $DIR/ub-ref-ptr.rs:38:39
5656
|
5757
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
5858
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
@@ -61,13 +61,13 @@ LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
6161
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
6262

6363
note: erroneous constant encountered
64-
--> $DIR/ub-ref-ptr.rs:36:38
64+
--> $DIR/ub-ref-ptr.rs:38:38
6565
|
6666
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
6767
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6868

6969
error[E0080]: evaluation of constant value failed
70-
--> $DIR/ub-ref-ptr.rs:39:86
70+
--> $DIR/ub-ref-ptr.rs:41:86
7171
|
7272
LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
7373
| ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
@@ -76,13 +76,13 @@ LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[us
7676
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
7777

7878
note: erroneous constant encountered
79-
--> $DIR/ub-ref-ptr.rs:39:85
79+
--> $DIR/ub-ref-ptr.rs:41:85
8080
|
8181
LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
8282
| ^^^^^^^^^^^^^^^^^^^^^
8383

8484
error[E0080]: it is undefined behavior to use this value
85-
--> $DIR/ub-ref-ptr.rs:42:1
85+
--> $DIR/ub-ref-ptr.rs:44:1
8686
|
8787
LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
8888
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (0x539[noalloc] has no provenance)
@@ -93,7 +93,7 @@ LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
9393
}
9494

9595
error[E0080]: it is undefined behavior to use this value
96-
--> $DIR/ub-ref-ptr.rs:45:1
96+
--> $DIR/ub-ref-ptr.rs:48:1
9797
|
9898
LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
9999
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (0x539[noalloc] has no provenance)
@@ -104,13 +104,13 @@ LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
104104
}
105105

106106
error[E0080]: evaluation of constant value failed
107-
--> $DIR/ub-ref-ptr.rs:48:41
107+
--> $DIR/ub-ref-ptr.rs:52:41
108108
|
109109
LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init };
110110
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
111111

112112
error[E0080]: it is undefined behavior to use this value
113-
--> $DIR/ub-ref-ptr.rs:52:1
113+
--> $DIR/ub-ref-ptr.rs:56:1
114114
|
115115
LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
116116
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer
@@ -121,13 +121,13 @@ LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
121121
}
122122

123123
error[E0080]: evaluation of constant value failed
124-
--> $DIR/ub-ref-ptr.rs:54:38
124+
--> $DIR/ub-ref-ptr.rs:59:38
125125
|
126126
LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init };
127127
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
128128

129129
error[E0080]: it is undefined behavior to use this value
130-
--> $DIR/ub-ref-ptr.rs:57:1
130+
--> $DIR/ub-ref-ptr.rs:62:1
131131
|
132132
LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
133133
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
@@ -138,7 +138,7 @@ LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
138138
}
139139

140140
error[E0080]: it is undefined behavior to use this value
141-
--> $DIR/ub-ref-ptr.rs:59:1
141+
--> $DIR/ub-ref-ptr.rs:65:1
142142
|
143143
LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
144144
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC2<imm>, but expected a function pointer
@@ -158,11 +158,33 @@ note: inside `std::ptr::read::<u32>`
158158
note: inside `std::ptr::const_ptr::<impl *const u32>::read`
159159
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
160160
note: inside `UNALIGNED_READ`
161-
--> $DIR/ub-ref-ptr.rs:66:5
161+
--> $DIR/ub-ref-ptr.rs:73:5
162162
|
163163
LL | ptr.read();
164164
| ^^^^^^^^^^
165165

166-
error: aborting due to 15 previous errors
166+
error[E0080]: it is undefined behavior to use this value
167+
--> $DIR/ub-ref-ptr.rs:76:1
168+
|
169+
LL | const POINTS_TO_FUNCTION: &() = unsafe {
170+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a function
171+
|
172+
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
173+
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
174+
HEX_DUMP
175+
}
176+
177+
error[E0080]: it is undefined behavior to use this value
178+
--> $DIR/ub-ref-ptr.rs:81:1
179+
|
180+
LL | const POINTS_TO_VTABLE: (&(), &()) = unsafe {
181+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .1: encountered a reference pointing to a vtable
182+
|
183+
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
184+
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
185+
HEX_DUMP
186+
}
187+
188+
error: aborting due to 17 previous errors
167189

168190
For more information about this error, try `rustc --explain E0080`.

0 commit comments

Comments
 (0)