diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2022-02-24 07:48:06 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-02-24 07:48:06 +0100 |
| commit | 3cd1dc1d6ec80efa2cff237d8494d825ab983da6 (patch) | |
| tree | a409691506547c78ce7f4924122860d931068835 /compiler/rustc_const_eval/src | |
| parent | 8a42e3da0bae5b25d42c0eea29884b31a41215e1 (diff) | |
| parent | 182d335870265a102c0f6467db65b5e59bd97e24 (diff) | |
| download | rust-3cd1dc1d6ec80efa2cff237d8494d825ab983da6.tar.gz rust-3cd1dc1d6ec80efa2cff237d8494d825ab983da6.zip | |
Rollup merge of #94270 - RalfJung:fn-ptrs, r=oli-obk
Miri: relax fn ptr check As discussed in https://github.com/rust-lang/unsafe-code-guidelines/issues/72#issuecomment-1025407536, the function pointer check done by Miri is currently overeager: contrary to our usual principle of only checking rather uncontroversial validity invariants, we actually check that the pointer points to a real function. So, this relaxes the check to what the validity invariant probably will be (and what the reference already says it is): the function pointer must be non-null, and that's it. The check that CTFE does on the final value of a constant is unchanged -- CTFE recurses through references, so it makes some sense to also recurse through function pointers. We might still want to relax this in the future, but that would be a separate change. r? `@oli-obk`
Diffstat (limited to 'compiler/rustc_const_eval/src')
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/validity.rs | 31 |
1 files changed, 18 insertions, 13 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 54e29299e6c..0bf86d52080 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -567,22 +567,27 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' } ty::FnPtr(_sig) => { let value = try_validation!( - self.ecx.read_immediate(value), + self.ecx.read_scalar(value).and_then(|v| v.check_init()), self.path, err_unsup!(ReadPointerAsBytes) => { "part of a pointer" } expected { "a proper pointer or integer value" }, + err_ub!(InvalidUninitBytes(None)) => { "uninitialized bytes" } expected { "a proper pointer or integer value" }, ); - // Make sure we print a `ScalarMaybeUninit` (and not an `ImmTy`) in the error - // message below. - let value = value.to_scalar_or_uninit(); - let _fn = try_validation!( - value.check_init().and_then(|ptr| self.ecx.memory.get_fn(self.ecx.scalar_to_ptr(ptr))), - self.path, - err_ub!(DanglingIntPointer(..)) | - err_ub!(InvalidFunctionPointer(..)) | - err_ub!(InvalidUninitBytes(None)) => - { "{:x}", value } expected { "a function pointer" }, - ); - // FIXME: Check if the signature matches + let ptr = self.ecx.scalar_to_ptr(value); + // Ensure the pointer is non-null. + if self.ecx.memory.ptr_may_be_null(ptr) { + throw_validation_failure!(self.path, { "a potentially null function pointer" }); + } + // If we check references recursively, also check that this points to a function. + if let Some(_) = self.ref_tracking { + let _fn = try_validation!( + self.ecx.memory.get_fn(ptr), + self.path, + err_ub!(DanglingIntPointer(..)) | + err_ub!(InvalidFunctionPointer(..)) => + { "{:x}", value } expected { "a function pointer" }, + ); + // FIXME: Check if the signature matches + } Ok(true) } ty::Never => throw_validation_failure!(self.path, { "a value of the never type `!`" }), |
