Auto merge of #100793 - matthiaskrgr:rollup-dy7rfdh, r=matthiaskrgr

Rollup of 10 pull requests

Successful merges:

 - #100186 (Mention `as_mut` alongside `as_ref` in borrowck error message)
 - #100383 (Mitigate stale data reads on SGX platform)
 - #100507 (suggest `once_cell::Lazy` for non-const statics)
 - #100617 (Suggest the right help message for as_ref)
 - #100667 (Migrate "invalid variable declaration" errors to SessionDiagnostic)
 - #100709 (Migrate typeck's `used` expected symbol diagnostic to `SessionDiagnostic`)
 - #100723 (Add the diagnostic translation lints to crates that don't emit them)
 - #100729 (Avoid zeroing a 1kb stack buffer on every call to `std::sys::windows::fill_utf16_buf`)
 - #100750 (improved diagnostic for function defined with `def`, `fun`, `func`, or `function` instead of `fn`)
 - #100763 (triagebot: Autolabel `A-rustdoc-json`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-08-20 07:59:48 +00:00
commit 36e530cb08
63 changed files with 476 additions and 138 deletions

View File

@ -33,6 +33,8 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![no_std]
#![forbid(unsafe_code)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate alloc;

View File

@ -19,6 +19,8 @@
#![feature(rustc_attrs)]
#![cfg_attr(test, feature(test))]
#![feature(strict_provenance)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
use smallvec::SmallVec;

View File

@ -19,6 +19,8 @@
#![feature(slice_internals)]
#![feature(stmt_expr_attributes)]
#![recursion_limit = "256"]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate rustc_macros;

View File

@ -1,3 +1,5 @@
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#![feature(associated_type_bounds)]
#![feature(box_patterns)]
#![feature(with_negative_coherence)]

View File

@ -1086,14 +1086,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
),
);
}
if is_option_or_result && maybe_reinitialized_locations_is_empty {
err.span_suggestion_verbose(
fn_call_span.shrink_to_lo(),
"consider calling `.as_ref()` to borrow the type's contents",
"as_ref().",
Applicability::MachineApplicable,
);
}
// Avoid pointing to the same function in multiple different
// error messages.
if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
@ -1102,6 +1094,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&format!("this function takes ownership of the receiver `self`, which moves {}", place_name)
);
}
if is_option_or_result && maybe_reinitialized_locations_is_empty {
err.span_label(
var_span,
"help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents",
);
}
}
// Other desugarings takes &self, which cannot cause a move
_ => {}

View File

@ -1,6 +1,7 @@
//! Concrete error types for all operations which may be invalid in a certain const context.
use hir::def_id::LocalDefId;
use hir::ConstContext;
use rustc_errors::{
error_code, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed,
};
@ -331,6 +332,10 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
ccx.const_kind(),
));
if let ConstContext::Static(_) = ccx.const_kind() {
err.note("consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell");
}
err
}
}

View File

@ -28,6 +28,8 @@
#![feature(vec_into_raw_parts)]
#![allow(rustc::default_hash_types)]
#![allow(rustc::potential_query_instability)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate tracing;

View File

@ -1,4 +1,6 @@
#![deny(rustdoc::invalid_codeblock_attributes)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
//! This library is used to gather all error codes into one place,
//! the goal being to make their maintenance easier.

View File

@ -32,3 +32,12 @@ parser_incorrect_use_of_await =
parser_in_in_typo =
expected iterable, found keyword `in`
.suggestion = remove the duplicated `in`
parser_invalid_variable_declaration =
invalid variable declaration
parser_switch_mut_let_order =
switch the order of `mut` and `let`
parser_missing_let_before_mut = missing keyword
parser_use_let_not_auto = write `let` instead of `auto` to introduce a new variable
parser_use_let_not_var = write `let` instead of `var` to introduce a new variable

View File

@ -131,3 +131,5 @@ typeck_unused_extern_crate =
typeck_extern_crate_not_idiomatic =
`extern crate` is not idiomatic in the new edition
.suggestion = convert it to a `{$msg_code}`
typeck_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`

View File

@ -1,6 +1,8 @@
#![feature(once_cell)]
#![feature(rustc_attrs)]
#![feature(type_alias_impl_trait)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
use fluent_bundle::FluentResource;
use fluent_syntax::parser::ParserError;

View File

@ -12,6 +12,8 @@
//! symbol to the `accepted` or `removed` modules respectively.
#![feature(once_cell)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
mod accepted;
mod active;

View File

@ -1,3 +1,6 @@
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
use std::ffi::CString;
use std::fs;
use std::io;

View File

@ -273,6 +273,8 @@
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
test(attr(allow(unused_variables), deny(warnings)))
)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
use LabelText::*;

View File

@ -11,6 +11,8 @@
#![feature(never_type)]
#![feature(rustc_attrs)]
#![recursion_limit = "256"]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate rustc_macros;

View File

@ -1,4 +1,6 @@
#![recursion_limit = "256"]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
use rustc_ast as ast;
use rustc_ast::util::parser::{self, AssocOp, Fixity};

View File

@ -1,3 +1,5 @@
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#![feature(allow_internal_unstable)]
#![feature(bench_black_box)]
#![feature(extend_one)]

View File

@ -2079,7 +2079,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
diag.span_suggestion(
span,
*msg,
format!("{}.as_ref()", snippet),
// HACK: fix issue# 100605, suggesting convert from &Option<T> to Option<&T>, remove the extra `&`
format!("{}.as_ref()", snippet.trim_start_matches('&')),
Applicability::MachineApplicable,
);
}

View File

@ -18,6 +18,8 @@
//! lexeme types.
//!
//! [`rustc_parse::lexer`]: ../rustc_parse/lexer/index.html
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
// We want to be able to build this crate with a stable compiler, so no
// `#![feature]` attributes should be added.

View File

@ -1,4 +1,6 @@
#![feature(min_specialization)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate rustc_macros;

View File

@ -1,3 +1,5 @@
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
// NOTE: This crate only exists to allow linking on mingw targets.

View File

@ -38,6 +38,9 @@
//! debugging, you can make changes inside those crates and quickly run main.rs
//! to read the debug logs.
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
use std::env::{self, VarError};
use std::fmt::{self, Display};
use std::io;

View File

@ -4,6 +4,8 @@
#![feature(proc_macro_diagnostic)]
#![feature(proc_macro_span)]
#![allow(rustc::default_hash_types)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#![recursion_limit = "128"]
use synstructure::decl_derive;

View File

@ -334,6 +334,35 @@ struct InInTypo {
sugg_span: Span,
}
#[derive(SessionDiagnostic)]
#[error(parser::invalid_variable_declaration)]
pub struct InvalidVariableDeclaration {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub sub: InvalidVariableDeclarationSub,
}
#[derive(SessionSubdiagnostic)]
pub enum InvalidVariableDeclarationSub {
#[suggestion(
parser::switch_mut_let_order,
applicability = "maybe-incorrect",
code = "let mut"
)]
SwitchMutLetOrder(#[primary_span] Span),
#[suggestion(
parser::missing_let_before_mut,
applicability = "machine-applicable",
code = "let mut"
)]
MissingLet(#[primary_span] Span),
#[suggestion(parser::use_let_not_auto, applicability = "machine-applicable", code = "let")]
UseLetNotAuto(#[primary_span] Span),
#[suggestion(parser::use_let_not_var, applicability = "machine-applicable", code = "let")]
UseLetNotVar(#[primary_span] Span),
}
// SnapshotParser is used to create a snapshot of the parser
// without causing duplicate errors being emitted when the `Parser`
// is dropped.
@ -611,6 +640,15 @@ impl<'a> Parser<'a> {
appl,
);
}
if ["def", "fun", "func", "function"].contains(&symbol.as_str()) {
err.span_suggestion_short(
self.prev_token.span,
&format!("write `fn` instead of `{symbol}` to declare a function"),
"fn",
appl,
);
}
}
// Add suggestion for a missing closing angle bracket if '>' is included in expected_tokens

View File

@ -1,5 +1,7 @@
use super::attr::DEFAULT_INNER_ATTR_FORBIDDEN;
use super::diagnostics::{AttemptLocalParseRecovery, Error};
use super::diagnostics::{
AttemptLocalParseRecovery, Error, InvalidVariableDeclaration, InvalidVariableDeclarationSub,
};
use super::expr::LhsExpr;
use super::pat::RecoverComma;
use super::path::PathStyle;
@ -58,28 +60,22 @@ impl<'a> Parser<'a> {
if self.token.is_keyword(kw::Mut) && self.is_keyword_ahead(1, &[kw::Let]) {
self.bump();
let mut_let_span = lo.to(self.token.span);
self.struct_span_err(mut_let_span, "invalid variable declaration")
.span_suggestion(
mut_let_span,
"switch the order of `mut` and `let`",
"let mut",
Applicability::MaybeIncorrect,
)
.emit();
self.sess.emit_err(InvalidVariableDeclaration {
span: mut_let_span,
sub: InvalidVariableDeclarationSub::SwitchMutLetOrder(mut_let_span),
});
}
Ok(Some(if self.token.is_keyword(kw::Let) {
self.parse_local_mk(lo, attrs, capture_semi, force_collect)?
} else if self.is_kw_followed_by_ident(kw::Mut) {
self.recover_stmt_local(lo, attrs, "missing keyword", "let mut")?
self.recover_stmt_local(lo, attrs, InvalidVariableDeclarationSub::MissingLet)?
} else if self.is_kw_followed_by_ident(kw::Auto) {
self.bump(); // `auto`
let msg = "write `let` instead of `auto` to introduce a new variable";
self.recover_stmt_local(lo, attrs, msg, "let")?
self.recover_stmt_local(lo, attrs, InvalidVariableDeclarationSub::UseLetNotAuto)?
} else if self.is_kw_followed_by_ident(sym::var) {
self.bump(); // `var`
let msg = "write `let` instead of `var` to introduce a new variable";
self.recover_stmt_local(lo, attrs, msg, "let")?
self.recover_stmt_local(lo, attrs, InvalidVariableDeclarationSub::UseLetNotVar)?
} else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() {
// We have avoided contextual keywords like `union`, items with `crate` visibility,
// or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something
@ -217,13 +213,10 @@ impl<'a> Parser<'a> {
&mut self,
lo: Span,
attrs: AttrWrapper,
msg: &str,
sugg: &str,
subdiagnostic: fn(Span) -> InvalidVariableDeclarationSub,
) -> PResult<'a, Stmt> {
let stmt = self.recover_local_after_let(lo, attrs)?;
self.struct_span_err(lo, "invalid variable declaration")
.span_suggestion(lo, msg, sugg, Applicability::MachineApplicable)
.emit();
self.sess.emit_err(InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) });
Ok(stmt)
}

View File

@ -9,6 +9,8 @@
html_playground_url = "https://play.rust-lang.org/",
test(attr(deny(warnings)))
)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
// We want to be able to build this crate with a stable compiler, so no
// `#![feature]` attributes should be added.

View File

@ -7,6 +7,8 @@
#![feature(rustc_attrs)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate rustc_macros;

View File

@ -18,6 +18,8 @@ Core encoding and decoding interfaces.
#![feature(new_uninit)]
#![cfg_attr(test, feature(test))]
#![allow(rustc::internal)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
pub use self::serialize::{Decodable, Decoder, Encodable, Encoder};

View File

@ -11,6 +11,8 @@
test(attr(allow(unused_variables), deny(warnings)))
)]
#![cfg_attr(not(feature = "default"), feature(rustc_private))]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
pub mod mir;

View File

@ -20,6 +20,8 @@
#![feature(negative_impls)]
#![feature(min_specialization)]
#![feature(rustc_attrs)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate rustc_macros;

View File

@ -16,6 +16,8 @@
#![feature(never_type)]
#![feature(rustc_attrs)]
#![feature(step_trait)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
use std::iter::FromIterator;
use std::path::{Path, PathBuf};

View File

@ -1,6 +1,8 @@
//! New recursive solver modeled on Chalk's recursive solver. Most of
//! the guts are broken up into modules; see the comments in those modules.
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#![feature(let_else)]
#![recursion_limit = "256"]

View File

@ -2836,12 +2836,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
}
Some(_) => {
tcx.sess
.struct_span_err(
attr.span,
"expected `used`, `used(compiler)` or `used(linker)`",
)
.emit();
tcx.sess.emit_err(errors::ExpectedUsedSymbol { span: attr.span });
}
None => {
// Unfortunately, unconditionally using `llvm.used` causes

View File

@ -340,3 +340,10 @@ pub struct ExternCrateNotIdiomatic {
pub msg_code: String,
pub suggestion_code: String,
}
#[derive(SessionDiagnostic)]
#[error(typeck::expected_used_symbol)]
pub struct ExpectedUsedSymbol {
#[primary_span]
pub span: Span,
}

View File

@ -305,6 +305,34 @@ where
}
}
// Split a memory region ptr..ptr + len into three parts:
// +--------+
// | small0 | Chunk smaller than 8 bytes
// +--------+
// | big | Chunk 8-byte aligned, and size a multiple of 8 bytes
// +--------+
// | small1 | Chunk smaller than 8 bytes
// +--------+
fn region_as_aligned_chunks(ptr: *const u8, len: usize) -> (usize, usize, usize) {
let small0_size = if ptr as usize % 8 == 0 { 0 } else { 8 - ptr as usize % 8 };
let small1_size = (len - small0_size as usize) % 8;
let big_size = len - small0_size as usize - small1_size as usize;
(small0_size, big_size, small1_size)
}
unsafe fn copy_quadwords(src: *const u8, dst: *mut u8, len: usize) {
unsafe {
asm!(
"rep movsq (%rsi), (%rdi)",
inout("rcx") len / 8 => _,
inout("rdi") dst => _,
inout("rsi") src => _,
options(att_syntax, nostack, preserves_flags)
);
}
}
/// Copies `len` bytes of data from enclave pointer `src` to userspace `dst`
///
/// This function mitigates stale data vulnerabilities by ensuring all writes to untrusted memory are either:
@ -343,17 +371,6 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
}
}
unsafe fn copy_aligned_quadwords_to_userspace(src: *const u8, dst: *mut u8, len: usize) {
unsafe {
asm!(
"rep movsq (%rsi), (%rdi)",
inout("rcx") len / 8 => _,
inout("rdi") dst => _,
inout("rsi") src => _,
options(att_syntax, nostack, preserves_flags)
);
}
}
assert!(!src.is_null());
assert!(!dst.is_null());
assert!(is_enclave_range(src, len));
@ -370,7 +387,7 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
} else if len % 8 == 0 && dst as usize % 8 == 0 {
// Copying 8-byte aligned quadwords: copy quad word per quad word
unsafe {
copy_aligned_quadwords_to_userspace(src, dst, len);
copy_quadwords(src, dst, len);
}
} else {
// Split copies into three parts:
@ -381,20 +398,16 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
// +--------+
// | small1 | Chunk smaller than 8 bytes
// +--------+
let (small0_size, big_size, small1_size) = region_as_aligned_chunks(dst, len);
unsafe {
// Copy small0
let small0_size = (8 - dst as usize % 8) as u8;
let small0_src = src;
let small0_dst = dst;
copy_bytewise_to_userspace(small0_src as _, small0_dst, small0_size as _);
copy_bytewise_to_userspace(src, dst, small0_size as _);
// Copy big
let small1_size = ((len - small0_size as usize) % 8) as u8;
let big_size = len - small0_size as usize - small1_size as usize;
let big_src = src.offset(small0_size as _);
let big_dst = dst.offset(small0_size as _);
copy_aligned_quadwords_to_userspace(big_src as _, big_dst, big_size);
copy_quadwords(big_src as _, big_dst, big_size);
// Copy small1
let small1_src = src.offset(big_size as isize + small0_size as isize);
@ -404,6 +417,106 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
}
}
/// Copies `len` bytes of data from userspace pointer `src` to enclave pointer `dst`
///
/// This function mitigates AEPIC leak vulnerabilities by ensuring all reads from untrusted memory are 8-byte aligned
///
/// # Panics
/// This function panics if:
///
/// * The `src` pointer is null
/// * The `dst` pointer is null
/// * The `src` memory range is not in user memory
/// * The `dst` memory range is not in enclave memory
///
/// # References
/// - https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00657.html
/// - https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/stale-data-read-from-xapic.html
pub(crate) unsafe fn copy_from_userspace(src: *const u8, dst: *mut u8, len: usize) {
// Copies memory region `src..src + len` to the enclave at `dst`. The source memory region
// is:
// - strictly less than 8 bytes in size and may be
// - located at a misaligned memory location
fn copy_misaligned_chunk_to_enclave(src: *const u8, dst: *mut u8, len: usize) {
let mut tmp_buff = [0u8; 16];
unsafe {
// Compute an aligned memory region to read from
// +--------+ <-- aligned_src + aligned_len (8B-aligned)
// | pad1 |
// +--------+ <-- src + len (misaligned)
// | |
// | |
// | |
// +--------+ <-- src (misaligned)
// | pad0 |
// +--------+ <-- aligned_src (8B-aligned)
let pad0_size = src as usize % 8;
let aligned_src = src.sub(pad0_size);
let pad1_size = 8 - (src.add(len) as usize % 8);
let aligned_len = pad0_size + len + pad1_size;
debug_assert!(len < 8);
debug_assert_eq!(aligned_src as usize % 8, 0);
debug_assert_eq!(aligned_len % 8, 0);
debug_assert!(aligned_len <= 16);
// Copy the aligned buffer to a temporary buffer
// Note: copying from a slightly different memory location is a bit odd. In this case it
// can't lead to page faults or inadvertent copying from the enclave as we only ensured
// that the `src` pointer is aligned at an 8 byte boundary. As pages are 4096 bytes
// aligned, `aligned_src` must be on the same page as `src`. A similar argument can be made
// for `src + len`
copy_quadwords(aligned_src as _, tmp_buff.as_mut_ptr(), aligned_len);
// Copy the correct parts of the temporary buffer to the destination
ptr::copy(tmp_buff.as_ptr().add(pad0_size), dst, len);
}
}
assert!(!src.is_null());
assert!(!dst.is_null());
assert!(is_user_range(src, len));
assert!(is_enclave_range(dst, len));
assert!(!(src as usize).overflowing_add(len + 8).1);
assert!(!(dst as usize).overflowing_add(len + 8).1);
if len < 8 {
copy_misaligned_chunk_to_enclave(src, dst, len);
} else if len % 8 == 0 && src as usize % 8 == 0 {
// Copying 8-byte aligned quadwords: copy quad word per quad word
unsafe {
copy_quadwords(src, dst, len);
}
} else {
// Split copies into three parts:
// +--------+
// | small0 | Chunk smaller than 8 bytes
// +--------+
// | big | Chunk 8-byte aligned, and size a multiple of 8 bytes
// +--------+
// | small1 | Chunk smaller than 8 bytes
// +--------+
let (small0_size, big_size, small1_size) = region_as_aligned_chunks(dst, len);
unsafe {
// Copy small0
copy_misaligned_chunk_to_enclave(src, dst, small0_size);
// Copy big
let big_src = src.add(small0_size);
let big_dst = dst.add(small0_size);
copy_quadwords(big_src, big_dst, big_size);
// Copy small1
let small1_src = src.add(big_size + small0_size);
let small1_dst = dst.add(big_size + small0_size);
copy_misaligned_chunk_to_enclave(small1_src, small1_dst, small1_size);
}
}
}
#[unstable(feature = "sgx_platform", issue = "56975")]
impl<T: ?Sized> UserRef<T>
where
@ -468,7 +581,7 @@ where
pub fn copy_to_enclave(&self, dest: &mut T) {
unsafe {
assert_eq!(mem::size_of_val(dest), mem::size_of_val(&*self.0.get()));
ptr::copy(
copy_from_userspace(
self.0.get() as *const T as *const u8,
dest as *mut T as *mut u8,
mem::size_of_val(dest),
@ -494,7 +607,11 @@ where
{
/// Copies the value from user memory into enclave memory.
pub fn to_enclave(&self) -> T {
unsafe { ptr::read(self.0.get()) }
unsafe {
let mut data: T = mem::MaybeUninit::uninit().assume_init();
copy_from_userspace(self.0.get() as _, &mut data as *mut T as _, mem::size_of::<T>());
data
}
}
}

View File

@ -1,8 +1,8 @@
use super::alloc::copy_to_userspace;
use super::alloc::User;
use super::alloc::{copy_from_userspace, copy_to_userspace};
#[test]
fn test_copy_function() {
fn test_copy_to_userspace_function() {
let mut src = [0u8; 100];
let mut dst = User::<[u8]>::uninitialized(100);
@ -28,3 +28,29 @@ fn test_copy_function() {
}
}
}
#[test]
fn test_copy_from_userspace_function() {
let mut dst = [0u8; 100];
let mut src = User::<[u8]>::uninitialized(100);
src.copy_from_enclave(&[0u8; 100]);
for size in 0..48 {
// For all possible alignment
for offset in 0..8 {
// overwrite complete dst
dst = [0u8; 100];
// Copy src[0..size] to dst + offset
unsafe { copy_from_userspace(src.as_ptr().offset(offset), dst.as_mut_ptr(), size) };
// Verify copy
for byte in 0..size {
unsafe {
assert_eq!(dst[byte as usize], *src.as_ptr().offset(offset + byte as isize));
}
}
}
}
}

View File

@ -2,6 +2,7 @@
use crate::ffi::{CStr, OsStr, OsString};
use crate::io::ErrorKind;
use crate::mem::MaybeUninit;
use crate::os::windows::ffi::{OsStrExt, OsStringExt};
use crate::path::PathBuf;
use crate::time::Duration;
@ -204,8 +205,8 @@ where
// This initial size also works around `GetFullPathNameW` returning
// incorrect size hints for some short paths:
// https://github.com/dylni/normpath/issues/5
let mut stack_buf = [0u16; 512];
let mut heap_buf = Vec::new();
let mut stack_buf: [MaybeUninit<u16>; 512] = MaybeUninit::uninit_array();
let mut heap_buf: Vec<MaybeUninit<u16>> = Vec::new();
unsafe {
let mut n = stack_buf.len();
loop {
@ -214,6 +215,11 @@ where
} else {
let extra = n - heap_buf.len();
heap_buf.reserve(extra);
// We used `reserve` and not `reserve_exact`, so in theory we
// may have gotten more than requested. If so, we'd like to use
// it... so long as we won't cause overflow.
n = heap_buf.capacity().min(c::DWORD::MAX as usize);
// Safety: MaybeUninit<u16> does not need initialization
heap_buf.set_len(n);
&mut heap_buf[..]
};
@ -228,13 +234,13 @@ where
// error" is still 0 then we interpret it as a 0 length buffer and
// not an actual error.
c::SetLastError(0);
let k = match f1(buf.as_mut_ptr(), n as c::DWORD) {
let k = match f1(buf.as_mut_ptr().cast::<u16>(), n as c::DWORD) {
0 if c::GetLastError() == 0 => 0,
0 => return Err(crate::io::Error::last_os_error()),
n => n,
} as usize;
if k == n && c::GetLastError() == c::ERROR_INSUFFICIENT_BUFFER {
n *= 2;
n = n.saturating_mul(2).min(c::DWORD::MAX as usize);
} else if k > n {
n = k;
} else if k == n {
@ -244,7 +250,9 @@ where
// Therefore k never equals n.
unreachable!();
} else {
return Ok(f2(&buf[..k]));
// Safety: First `k` values are initialized.
let slice: &[u16] = MaybeUninit::slice_assume_init_ref(&buf[..k]);
return Ok(f2(slice));
}
}
}

View File

@ -14,6 +14,7 @@ LL | static settings_dir: String = format!("");
| ^^^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0507]: cannot move out of static item `settings_dir`

View File

@ -5,6 +5,7 @@ LL | cb.map(|cb| cb());
| ^^^--------------
| | |
| | `*cb` moved due to this method call
| help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
| move occurs because `*cb` has type `Option<&mut dyn FnMut()>`, which does not implement the `Copy` trait
|
note: this function takes ownership of the receiver `self`, which moves `*cb`
@ -12,10 +13,6 @@ note: this function takes ownership of the receiver `self`, which moves `*cb`
|
LL | pub const fn map<U, F>(self, f: F) -> Option<U>
| ^^^^
help: consider calling `.as_ref()` to borrow the type's contents
|
LL | cb.as_ref().map(|cb| cb());
| +++++++++
error[E0596]: cannot borrow `*cb` as mutable, as it is behind a `&` reference
--> $DIR/suggest-as-ref-on-mut-closure.rs:12:26

View File

@ -22,6 +22,7 @@ LL | field2: SafeEnum::Variant4("str".to_string())
| ^^^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
error[E0010]: allocations are not allowed in statics
--> $DIR/check-static-values-constraints.rs:94:5

View File

@ -13,6 +13,7 @@ LL | invalid();
| ^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
error[E0015]: cannot call non-const fn `invalid` in statics
--> $DIR/issue-32829-2.rs:54:9
@ -21,6 +22,7 @@ LL | invalid();
| ^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
error: aborting due to 3 previous errors

View File

@ -5,6 +5,7 @@ LL | static foo: Foo = bar();
| ^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
error: aborting due to previous error

View File

@ -0,0 +1,9 @@
fn takes_option(_arg: Option<&String>) {}
fn main() {
takes_option(&None); //~ ERROR 4:18: 4:23: mismatched types [E0308]
let x = String::from("x");
let res = Some(x);
takes_option(&res); //~ ERROR 8:18: 8:22: mismatched types [E0308]
}

View File

@ -0,0 +1,46 @@
error[E0308]: mismatched types
--> $DIR/issue-100605.rs:4:18
|
LL | takes_option(&None);
| ------------ ^^^^^ expected enum `Option`, found `&Option<_>`
| |
| arguments to this function are incorrect
|
= note: expected enum `Option<&String>`
found reference `&Option<_>`
note: function defined here
--> $DIR/issue-100605.rs:1:4
|
LL | fn takes_option(_arg: Option<&String>) {}
| ^^^^^^^^^^^^ ---------------------
help: you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`
|
LL | takes_option(None.as_ref());
| ~~~~~~~~~~~~~
help: consider removing the borrow
|
LL - takes_option(&None);
LL + takes_option(None);
|
error[E0308]: mismatched types
--> $DIR/issue-100605.rs:8:18
|
LL | takes_option(&res);
| ------------ ^^^^
| | |
| | expected enum `Option`, found `&Option<String>`
| | help: you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`: `res.as_ref()`
| arguments to this function are incorrect
|
= note: expected enum `Option<&String>`
found reference `&Option<String>`
note: function defined here
--> $DIR/issue-100605.rs:1:4
|
LL | fn takes_option(_arg: Option<&String>) {}
| ^^^^^^^^^^^^ ---------------------
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -5,6 +5,7 @@ LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
error[E0133]: use of extern static is unsafe and requires unsafe function or block
--> $DIR/issue-16538.rs:14:30

View File

@ -21,6 +21,7 @@ LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
error: aborting due to 3 previous errors

View File

@ -16,6 +16,7 @@ note: impl defined here, but it is not `const`
LL | impl Deref for A {
| ^^^^^^^^^^^^^^^^
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
error: aborting due to previous error

View File

@ -0,0 +1,10 @@
// Check what happens when `def` is used to define a function, instead of `fn`
// edition:2021
#![allow(dead_code)]
def foo() {}
//~^ ERROR expected one of `!` or `::`, found `foo`
//~^^ HELP write `fn` instead of `def` to declare a function
fn main() {}

View File

@ -0,0 +1,10 @@
error: expected one of `!` or `::`, found `foo`
--> $DIR/fn-defined-using-def.rs:6:5
|
LL | def foo() {}
| --- ^^^ expected one of `!` or `::`
| |
| help: write `fn` instead of `def` to declare a function
error: aborting due to previous error

View File

@ -0,0 +1,10 @@
// Check what happens when `fun` is used to define a function, instead of `fn`
// edition:2021
#![allow(dead_code)]
fun foo() {}
//~^ ERROR expected one of `!` or `::`, found `foo`
//~^^ HELP write `fn` instead of `fun` to declare a function
fn main() {}

View File

@ -0,0 +1,10 @@
error: expected one of `!` or `::`, found `foo`
--> $DIR/fn-defined-using-fun.rs:6:5
|
LL | fun foo() {}
| --- ^^^ expected one of `!` or `::`
| |
| help: write `fn` instead of `fun` to declare a function
error: aborting due to previous error

View File

@ -0,0 +1,10 @@
// Check what happens when `func` is used to define a function, instead of `fn`
// edition:2021
#![allow(dead_code)]
func foo() {}
//~^ ERROR expected one of `!` or `::`, found `foo`
//~^^ HELP write `fn` instead of `func` to declare a function
fn main() {}

View File

@ -0,0 +1,10 @@
error: expected one of `!` or `::`, found `foo`
--> $DIR/fn-defined-using-func.rs:6:6
|
LL | func foo() {}
| ---- ^^^ expected one of `!` or `::`
| |
| help: write `fn` instead of `func` to declare a function
error: aborting due to previous error

View File

@ -0,0 +1,10 @@
// Check what happens when `function` is used to define a function, instead of `fn`
// edition:2021
#![allow(dead_code)]
function foo() {}
//~^ ERROR expected one of `!` or `::`, found `foo`
//~^^ HELP write `fn` instead of `function` to declare a function
fn main() {}

View File

@ -0,0 +1,10 @@
error: expected one of `!` or `::`, found `foo`
--> $DIR/fn-defined-using-function.rs:6:10
|
LL | function foo() {}
| -------- ^^^ expected one of `!` or `::`
| |
| help: write `fn` instead of `function` to declare a function
error: aborting due to previous error

View File

@ -5,6 +5,7 @@ LL | static a: [isize; 2] = [foo(); 2];
| ^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
error: aborting due to previous error

View File

@ -1,13 +0,0 @@
// run-rustfix
struct Struct;
fn bar(_: &Struct) -> Struct {
Struct
}
fn main() {
let foo = Some(Struct);
let _x: Option<Struct> = foo.as_ref().map(|s| bar(&s));
let _y = foo; //~ERROR use of moved value: `foo`
}

View File

@ -1,5 +1,3 @@
// run-rustfix
struct Struct;
fn bar(_: &Struct) -> Struct {

View File

@ -1,10 +1,12 @@
error[E0382]: use of moved value: `foo`
--> $DIR/as-ref-2.rs:12:14
--> $DIR/as-ref-2.rs:10:14
|
LL | let foo = Some(Struct);
| --- move occurs because `foo` has type `Option<Struct>`, which does not implement the `Copy` trait
LL | let _x: Option<Struct> = foo.map(|s| bar(&s));
| ---------------- `foo` moved due to this method call
| --- ---------------- `foo` moved due to this method call
| |
| help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
LL | let _y = foo;
| ^^^ value used here after move
|
@ -13,10 +15,6 @@ note: this function takes ownership of the receiver `self`, which moves `foo`
|
LL | pub const fn map<U, F>(self, f: F) -> Option<U>
| ^^^^
help: consider calling `.as_ref()` to borrow the type's contents
|
LL | let _x: Option<Struct> = foo.as_ref().map(|s| bar(&s));
| +++++++++
error: aborting due to previous error

View File

@ -1,39 +0,0 @@
//run-rustfix
pub struct LipogramCorpora {
selections: Vec<(char, Option<String>)>,
}
impl LipogramCorpora {
pub fn validate_all(&mut self) -> Result<(), char> {
for selection in &self.selections {
if selection.1.is_some() {
if selection.1.as_ref().unwrap().contains(selection.0) {
//~^ ERROR cannot move out of `selection.1`
return Err(selection.0);
}
}
}
Ok(())
}
}
pub struct LipogramCorpora2 {
selections: Vec<(char, Result<String, String>)>,
}
impl LipogramCorpora2 {
pub fn validate_all(&mut self) -> Result<(), char> {
for selection in &self.selections {
if selection.1.is_ok() {
if selection.1.as_ref().unwrap().contains(selection.0) {
//~^ ERROR cannot move out of `selection.1`
return Err(selection.0);
}
}
}
Ok(())
}
}
fn main() {}

View File

@ -1,5 +1,3 @@
//run-rustfix
pub struct LipogramCorpora {
selections: Vec<(char, Option<String>)>,
}

View File

@ -1,9 +1,10 @@
error[E0507]: cannot move out of `selection.1` which is behind a shared reference
--> $DIR/option-content-move.rs:11:20
--> $DIR/option-content-move.rs:9:20
|
LL | if selection.1.unwrap().contains(selection.0) {
| ^^^^^^^^^^^ -------- `selection.1` moved due to this method call
| |
| help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
| move occurs because `selection.1` has type `Option<String>`, which does not implement the `Copy` trait
|
note: this function takes ownership of the receiver `self`, which moves `selection.1`
@ -11,17 +12,14 @@ note: this function takes ownership of the receiver `self`, which moves `selecti
|
LL | pub const fn unwrap(self) -> T {
| ^^^^
help: consider calling `.as_ref()` to borrow the type's contents
|
LL | if selection.1.as_ref().unwrap().contains(selection.0) {
| +++++++++
error[E0507]: cannot move out of `selection.1` which is behind a shared reference
--> $DIR/option-content-move.rs:29:20
--> $DIR/option-content-move.rs:27:20
|
LL | if selection.1.unwrap().contains(selection.0) {
| ^^^^^^^^^^^ -------- `selection.1` moved due to this method call
| |
| help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
| move occurs because `selection.1` has type `Result<String, String>`, which does not implement the `Copy` trait
|
note: this function takes ownership of the receiver `self`, which moves `selection.1`
@ -29,10 +27,6 @@ note: this function takes ownership of the receiver `self`, which moves `selecti
|
LL | pub fn unwrap(self) -> T
| ^^^^
help: consider calling `.as_ref()` to borrow the type's contents
|
LL | if selection.1.as_ref().unwrap().contains(selection.0) {
| +++++++++
error: aborting due to 2 previous errors

View File

@ -129,6 +129,7 @@ trigger_files = [
# Internal tooling
"src/etc/htmldocck.py",
"src/etc/check_missing_items.py",
"src/tools/jsondocck",
"src/tools/rustdoc-gui",
"src/tools/rustdoc-js",
@ -138,6 +139,15 @@ exclude_labels = [
"T-*",
]
[autolabel."A-rustdoc-json"]
trigger_files = [
"src/etc/check_missing_items.py",
"src/librustdoc/json/",
"src/rustdoc-json-types",
"src/test/rustdoc-json",
"src/tools/jsondocck",
]
[autolabel."T-compiler"]
trigger_files = [
# Source code