Merge from rustc

This commit is contained in:
Ralf Jung 2023-02-15 10:44:40 +01:00
commit 1a2908bfaa
1116 changed files with 27941 additions and 19637 deletions

View file

@ -16,7 +16,7 @@ panic_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" }
core = { path = "../core" }
libc = { version = "0.2.138", default-features = false, features = ['rustc-dep-of-std'] }
compiler_builtins = { version = "0.1.85" }
compiler_builtins = { version = "0.1.87" }
profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" }
hashbrown = { version = "0.12", default-features = false, features = ['rustc-dep-of-std'] }

View file

@ -72,11 +72,6 @@ pub fn unsupported_err() -> crate::io::Error {
)
}
#[no_mangle]
pub extern "C" fn floor(x: f64) -> f64 {
unsafe { intrinsics::floorf64(x) }
}
pub fn abort_internal() -> ! {
unsafe {
abi::abort();

View file

@ -141,12 +141,28 @@ mod imp {
// list.
let argv = ARGV.load(Ordering::Relaxed);
let argc = if argv.is_null() { 0 } else { ARGC.load(Ordering::Relaxed) };
(0..argc)
.map(|i| {
let cstr = CStr::from_ptr(*argv.offset(i) as *const libc::c_char);
OsStringExt::from_vec(cstr.to_bytes().to_vec())
})
.collect()
let mut args = Vec::with_capacity(argc as usize);
for i in 0..argc {
let ptr = *argv.offset(i) as *const libc::c_char;
// Some C commandline parsers (e.g. GLib and Qt) are replacing already
// handled arguments in `argv` with `NULL` and move them to the end. That
// means that `argc` might be bigger than the actual number of non-`NULL`
// pointers in `argv` at this point.
//
// To handle this we simply stop iterating at the first `NULL` argument.
//
// `argv` is also guaranteed to be `NULL`-terminated so any non-`NULL` arguments
// after the first `NULL` can safely be ignored.
if ptr.is_null() {
break;
}
let cstr = CStr::from_ptr(ptr);
args.push(OsStringExt::from_vec(cstr.to_bytes().to_vec()));
}
args
}
}
}

View file

@ -21,6 +21,7 @@ mod libc {
extern "C" {
pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char;
pub fn chdir(dir: *const c_char) -> c_int;
pub fn __wasilibc_get_environ() -> *mut *mut c_char;
}
}
@ -161,7 +162,12 @@ impl Iterator for Env {
pub fn env() -> Env {
unsafe {
let _guard = env_read_lock();
let mut environ = libc::environ;
// Use `__wasilibc_get_environ` instead of `environ` here so that we
// don't require wasi-libc to eagerly initialize the environment
// variables.
let mut environ = libc::__wasilibc_get_environ();
let mut result = Vec::new();
if !environ.is_null() {
while !(*environ).is_null() {

View file

@ -295,8 +295,6 @@ pub fn nt_success(status: NTSTATUS) -> bool {
status >= 0
}
// "RNG\0"
pub const BCRYPT_RNG_ALGORITHM: &[u16] = &[b'R' as u16, b'N' as u16, b'G' as u16, 0];
pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002;
#[repr(C)]
@ -834,6 +832,10 @@ if #[cfg(not(target_vendor = "uwp"))] {
#[link(name = "advapi32")]
extern "system" {
// Forbidden when targeting UWP
#[link_name = "SystemFunction036"]
pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN;
// Allowed but unused by UWP
pub fn OpenProcessToken(
ProcessHandle: HANDLE,
@ -1258,13 +1260,6 @@ extern "system" {
cbBuffer: ULONG,
dwFlags: ULONG,
) -> NTSTATUS;
pub fn BCryptOpenAlgorithmProvider(
phalgorithm: *mut BCRYPT_ALG_HANDLE,
pszAlgId: LPCWSTR,
pszimplementation: LPCWSTR,
dwflags: ULONG,
) -> NTSTATUS;
pub fn BCryptCloseAlgorithmProvider(hAlgorithm: BCRYPT_ALG_HANDLE, dwFlags: ULONG) -> NTSTATUS;
}
// Functions that aren't available on every version of Windows that we support,

View file

@ -1266,7 +1266,12 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> {
// If the fallback fails for any reason we return the original error.
match File::open(path, &opts) {
Ok(file) => file.file_attr(),
Err(e) if e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as _) => {
Err(e)
if [Some(c::ERROR_SHARING_VIOLATION as _), Some(c::ERROR_ACCESS_DENIED as _)]
.contains(&e.raw_os_error()) =>
{
// `ERROR_ACCESS_DENIED` is returned when the user doesn't have permission for the resource.
// One such example is `System Volume Information` as default but can be created as well
// `ERROR_SHARING_VIOLATION` will almost never be returned.
// Usually if a file is locked you can still read some metadata.
// However, there are special system files, such as
@ -1393,6 +1398,8 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> {
let mut data = Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
let data_ptr = data.0.as_mut_ptr();
let db = data_ptr.cast::<c::REPARSE_MOUNTPOINT_DATA_BUFFER>();
// Zero the header to ensure it's fully initialized, including reserved parameters.
*db = mem::zeroed();
let buf = ptr::addr_of_mut!((*db).ReparseTarget).cast::<c::WCHAR>();
let mut i = 0;
// FIXME: this conversion is very hacky

View file

@ -1,106 +1,39 @@
//! # Random key generation
//!
//! This module wraps the RNG provided by the OS. There are a few different
//! ways to interface with the OS RNG so it's worth exploring each of the options.
//! Note that at the time of writing these all go through the (undocumented)
//! `bcryptPrimitives.dll` but they use different route to get there.
//!
//! Originally we were using [`RtlGenRandom`], however that function is
//! deprecated and warns it "may be altered or unavailable in subsequent versions".
//!
//! So we switched to [`BCryptGenRandom`] with the `BCRYPT_USE_SYSTEM_PREFERRED_RNG`
//! flag to query and find the system configured RNG. However, this change caused a small
//! but significant number of users to experience panics caused by a failure of
//! this function. See [#94098].
//!
//! The current version falls back to using `BCryptOpenAlgorithmProvider` if
//! `BCRYPT_USE_SYSTEM_PREFERRED_RNG` fails for any reason.
//!
//! [#94098]: https://github.com/rust-lang/rust/issues/94098
//! [`RtlGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom
//! [`BCryptGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
use crate::io;
use crate::mem;
use crate::ptr;
use crate::sys::c;
/// Generates high quality secure random keys for use by [`HashMap`].
///
/// This is used to seed the default [`RandomState`].
///
/// [`HashMap`]: crate::collections::HashMap
/// [`RandomState`]: crate::collections::hash_map::RandomState
pub fn hashmap_random_keys() -> (u64, u64) {
Rng::SYSTEM.gen_random_keys().unwrap_or_else(fallback_rng)
let mut v = (0, 0);
let ret = unsafe {
c::BCryptGenRandom(
ptr::null_mut(),
&mut v as *mut _ as *mut u8,
mem::size_of_val(&v) as c::ULONG,
c::BCRYPT_USE_SYSTEM_PREFERRED_RNG,
)
};
if c::nt_success(ret) { v } else { fallback_rng() }
}
struct Rng {
algorithm: c::BCRYPT_ALG_HANDLE,
flags: u32,
}
impl Rng {
const SYSTEM: Self = unsafe { Self::new(ptr::null_mut(), c::BCRYPT_USE_SYSTEM_PREFERRED_RNG) };
/// Create the RNG from an existing algorithm handle.
///
/// # Safety
///
/// The handle must either be null or a valid algorithm handle.
const unsafe fn new(algorithm: c::BCRYPT_ALG_HANDLE, flags: u32) -> Self {
Self { algorithm, flags }
}
/// Open a handle to the RNG algorithm.
fn open() -> Result<Self, c::NTSTATUS> {
use crate::sync::atomic::AtomicPtr;
use crate::sync::atomic::Ordering::{Acquire, Release};
// An atomic is used so we don't need to reopen the handle every time.
static HANDLE: AtomicPtr<crate::ffi::c_void> = AtomicPtr::new(ptr::null_mut());
let mut handle = HANDLE.load(Acquire);
if handle.is_null() {
let status = unsafe {
c::BCryptOpenAlgorithmProvider(
&mut handle,
c::BCRYPT_RNG_ALGORITHM.as_ptr(),
ptr::null(),
0,
)
};
if c::nt_success(status) {
// If another thread opens a handle first then use that handle instead.
let result = HANDLE.compare_exchange(ptr::null_mut(), handle, Release, Acquire);
if let Err(previous_handle) = result {
// Close our handle and return the previous one.
unsafe { c::BCryptCloseAlgorithmProvider(handle, 0) };
handle = previous_handle;
}
Ok(unsafe { Self::new(handle, 0) })
} else {
Err(status)
}
} else {
Ok(unsafe { Self::new(handle, 0) })
}
}
fn gen_random_keys(self) -> Result<(u64, u64), c::NTSTATUS> {
let mut v = (0, 0);
let status = unsafe {
let size = mem::size_of_val(&v).try_into().unwrap();
c::BCryptGenRandom(self.algorithm, ptr::addr_of_mut!(v).cast(), size, self.flags)
};
if c::nt_success(status) { Ok(v) } else { Err(status) }
}
}
/// Generate random numbers using the fallback RNG function
/// Generate random numbers using the fallback RNG function (RtlGenRandom)
///
/// This is necessary because of a failure to load the SysWOW64 variant of the
/// bcryptprimitives.dll library from code that lives in bcrypt.dll
/// See <https://bugzilla.mozilla.org/show_bug.cgi?id=1788004#c9>
#[cfg(not(target_vendor = "uwp"))]
#[inline(never)]
fn fallback_rng(rng_status: c::NTSTATUS) -> (u64, u64) {
match Rng::open().and_then(|rng| rng.gen_random_keys()) {
Ok(keys) => keys,
Err(status) => {
panic!("RNG broken: {rng_status:#x}, fallback RNG broken: {status:#x}")
}
}
fn fallback_rng() -> (u64, u64) {
let mut v = (0, 0);
let ret =
unsafe { c::RtlGenRandom(&mut v as *mut _ as *mut u8, mem::size_of_val(&v) as c::ULONG) };
if ret != 0 { v } else { panic!("fallback RNG broken: {}", io::Error::last_os_error()) }
}
/// We can't use RtlGenRandom with UWP, so there is no fallback
#[cfg(target_vendor = "uwp")]
#[inline(never)]
fn fallback_rng() -> (u64, u64) {
panic!("fallback RNG broken: RtlGenRandom() not supported on UWP");
}

View file

@ -1,6 +1,5 @@
#![unstable(issue = "none", feature = "windows_stdio")]
use crate::char::decode_utf16;
use crate::cmp;
use crate::io;
use crate::mem::MaybeUninit;
@ -369,7 +368,7 @@ fn read_u16s(handle: c::HANDLE, buf: &mut [MaybeUninit<u16>]) -> io::Result<usiz
#[allow(unused)]
fn utf16_to_utf8(utf16: &[u16], utf8: &mut [u8]) -> io::Result<usize> {
let mut written = 0;
for chr in decode_utf16(utf16.iter().cloned()) {
for chr in char::decode_utf16(utf16.iter().cloned()) {
match chr {
Ok(chr) => {
chr.encode_utf8(&mut utf8[written..]);

View file

@ -18,10 +18,10 @@
#[cfg(test)]
mod tests;
use core::char::{encode_utf16_raw, encode_utf8_raw};
use core::str::next_code_point;
use crate::borrow::Cow;
use crate::char;
use crate::collections::TryReserveError;
use crate::fmt;
use crate::hash::{Hash, Hasher};
@ -235,7 +235,7 @@ impl Wtf8Buf {
/// This does **not** include the WTF-8 concatenation check or `is_known_utf8` check.
fn push_code_point_unchecked(&mut self, code_point: CodePoint) {
let mut bytes = [0; 4];
let bytes = char::encode_utf8_raw(code_point.value, &mut bytes);
let bytes = encode_utf8_raw(code_point.value, &mut bytes);
self.bytes.extend_from_slice(bytes)
}
@ -939,7 +939,7 @@ impl<'a> Iterator for EncodeWide<'a> {
let mut buf = [0; 2];
self.code_points.next().map(|code_point| {
let n = char::encode_utf16_raw(code_point.value, &mut buf).len();
let n = encode_utf16_raw(code_point.value, &mut buf).len();
if n == 2 {
self.extra = buf[1];
}