Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1094,7 +1094,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
// only place where we have access to the compiler `Session`.
// - LLVM work can be done on any thread.
// - Codegen can only happen on the main thread.
// - Each thread doing substantial work most be in possession of a `Token`
// - Each thread doing substantial work must be in possession of a `Token`
// from the `Jobserver`.
// - The compiler process always holds one `Token`. Any additional `Tokens`
// have to be requested from the `Jobserver`.
Expand Down Expand Up @@ -1146,7 +1146,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
// if possible. These two goals are at odds with each other: If memory
// consumption were not an issue, we could just let the main thread produce
// LLVM WorkItems at full speed, assuring maximal utilization of
// Tokens/LLVM worker threads. However, since codegen usual is faster
// Tokens/LLVM worker threads. However, since codegen is usually faster
// than LLVM processing, the queue of LLVM WorkItems would fill up and each
// WorkItem potentially holds on to a substantial amount of memory.
//
Expand Down
87 changes: 87 additions & 0 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// ignore-tidy-filelength

//! Lints in the Rust compiler.
//!
//! This contains lints which can feasibly be implemented as their own
Expand Down Expand Up @@ -2964,3 +2966,88 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
}
}
}

declare_lint! {
/// The `deref_nullptr` lint detects when an null pointer is dereferenced,
/// which causes [undefined behavior].
///
/// ### Example
///
/// ```rust,no_run
/// # #![allow(unused)]
/// use std::ptr;
/// unsafe {
/// let x = &*ptr::null::<i32>();
/// let x = ptr::addr_of!(*ptr::null::<i32>());
/// let x = *(0 as *const i32);
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Dereferencing a null pointer causes [undefined behavior] even as a place expression,
/// like `&*(0 as *const i32)` or `addr_of!(*(0 as *const i32))`.
///
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
pub DEREF_NULLPTR,
Warn,
"detects when an null pointer is dereferenced"
}

declare_lint_pass!(DerefNullPtr => [DEREF_NULLPTR]);

impl<'tcx> LateLintPass<'tcx> for DerefNullPtr {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) {
/// test if expression is a null ptr
fn is_null_ptr(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
match &expr.kind {
rustc_hir::ExprKind::Cast(ref expr, ref ty) => {
if let rustc_hir::TyKind::Ptr(_) = ty.kind {
return is_zero(expr) || is_null_ptr(cx, expr);
}
}
// check for call to `core::ptr::null` or `core::ptr::null_mut`
rustc_hir::ExprKind::Call(ref path, _) => {
if let rustc_hir::ExprKind::Path(ref qpath) = path.kind {
if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() {
return cx.tcx.is_diagnostic_item(sym::ptr_null, def_id)
|| cx.tcx.is_diagnostic_item(sym::ptr_null_mut, def_id);
}
}
}
_ => {}
}
false
}

/// test if experssion is the literal `0`
fn is_zero(expr: &hir::Expr<'_>) -> bool {
match &expr.kind {
rustc_hir::ExprKind::Lit(ref lit) => {
if let LitKind::Int(a, _) = lit.node {
return a == 0;
}
}
_ => {}
}
false
}

if let rustc_hir::ExprKind::Unary(ref un_op, ref expr_deref) = expr.kind {
if let rustc_hir::UnOp::Deref = un_op {
if is_null_ptr(cx, expr_deref) {
cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| {
let mut err = lint.build("dereferencing a null pointer");
err.span_label(
expr.span,
"this code causes undefined behavior when executed",
);
err.emit();
});
}
}
}
}
}
1 change: 1 addition & 0 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ macro_rules! late_lint_mod_passes {
UnreachablePub: UnreachablePub,
ExplicitOutlivesRequirements: ExplicitOutlivesRequirements,
InvalidValue: InvalidValue,
DerefNullPtr: DerefNullPtr,
]
);
};
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,8 @@ symbols! {
profiler_runtime,
ptr_guaranteed_eq,
ptr_guaranteed_ne,
ptr_null,
ptr_null_mut,
ptr_offset_from,
pub_macro_rules,
pub_restricted,
Expand Down
2 changes: 2 additions & 0 deletions library/core/src/ptr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_promotable]
#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
#[rustc_diagnostic_item = "ptr_null"]
pub const fn null<T>() -> *const T {
0 as *const T
}
Expand All @@ -229,6 +230,7 @@ pub const fn null<T>() -> *const T {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_promotable]
#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
#[rustc_diagnostic_item = "ptr_null_mut"]
pub const fn null_mut<T>() -> *mut T {
0 as *mut T
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![allow(dead_code)]

use crate::alloc::{GlobalAlloc, Layout, System};
use crate::cmp;
use crate::ptr;
Expand Down
13 changes: 13 additions & 0 deletions library/std/src/sys/common/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// This module contains code that is shared between all platforms, mostly utility or fallback code.
// This explicitly does not include code that is shared between only a few platforms,
// such as when reusing an implementation from `unix` or `unsupported`.
// In those cases the desired code should be included directly using the #[path] attribute,
// not moved to this module.
//
// Currently `sys_common` contains a lot of code that should live in this module,
// ideally `sys_common` would only contain platform-independent abstractions on top of `sys`.
// Progress on this is tracked in #84187.

#![allow(dead_code)]

pub mod alloc;
8 changes: 4 additions & 4 deletions library/std/src/sys/hermit/args.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::ffi::OsString;
use crate::marker::PhantomData;
use crate::vec;

/// One-time global initialization.
Expand All @@ -19,7 +18,6 @@ pub fn args() -> Args {

pub struct Args {
iter: vec::IntoIter<OsString>,
_dont_send_or_sync_me: PhantomData<*mut ()>,
}

impl Args {
Expand All @@ -28,6 +26,9 @@ impl Args {
}
}

impl !Send for Args {}
impl !Sync for Args {}

impl Iterator for Args {
type Item = OsString;
fn next(&mut self) -> Option<OsString> {
Expand All @@ -53,7 +54,6 @@ impl DoubleEndedIterator for Args {
mod imp {
use super::Args;
use crate::ffi::{CStr, OsString};
use crate::marker::PhantomData;
use crate::ptr;
use crate::sys_common::os_str_bytes::*;

Expand All @@ -76,7 +76,7 @@ mod imp {
}

pub fn args() -> Args {
Args { iter: clone().into_iter(), _dont_send_or_sync_me: PhantomData }
Args { iter: clone().into_iter() }
}

fn clone() -> Vec<OsString> {
Expand Down
7 changes: 4 additions & 3 deletions library/std/src/sys/hermit/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use crate::error::Error as StdError;
use crate::ffi::{CStr, OsStr, OsString};
use crate::fmt;
use crate::io;
use crate::marker::PhantomData;
use crate::memchr;
use crate::path::{self, PathBuf};
use crate::str;
Expand Down Expand Up @@ -110,9 +109,11 @@ pub fn init_environment(env: *const *const i8) {

pub struct Env {
iter: vec::IntoIter<(OsString, OsString)>,
_dont_send_or_sync_me: PhantomData<*mut ()>,
}

impl !Send for Env {}
impl !Sync for Env {}

impl Iterator for Env {
type Item = (OsString, OsString);
fn next(&mut self) -> Option<(OsString, OsString)> {
Expand All @@ -134,7 +135,7 @@ pub fn env() -> Env {
result.push((key.clone(), value.clone()));
}

return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData };
return Env { iter: result.into_iter() };
}
}

Expand Down
2 changes: 2 additions & 0 deletions library/std/src/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#![allow(missing_debug_implementations)]

mod common;

cfg_if::cfg_if! {
if #[cfg(target_os = "vxworks")] {
mod vxworks;
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/unix/alloc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::alloc::{GlobalAlloc, Layout, System};
use crate::ptr;
use crate::sys_common::alloc::{realloc_fallback, MIN_ALIGN};
use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN};

#[stable(feature = "alloc_system_type", since = "1.28.0")]
unsafe impl GlobalAlloc for System {
Expand Down
13 changes: 6 additions & 7 deletions library/std/src/sys/unix/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#![allow(dead_code)] // runtime init functions not used during testing

use crate::ffi::OsString;
use crate::marker::PhantomData;
use crate::vec;

/// One-time global initialization.
Expand All @@ -26,9 +25,11 @@ pub fn args() -> Args {

pub struct Args {
iter: vec::IntoIter<OsString>,
_dont_send_or_sync_me: PhantomData<*mut ()>,
}

impl !Send for Args {}
impl !Sync for Args {}

impl Args {
pub fn inner_debug(&self) -> &[OsString] {
self.iter.as_slice()
Expand Down Expand Up @@ -76,7 +77,6 @@ impl DoubleEndedIterator for Args {
mod imp {
use super::Args;
use crate::ffi::{CStr, OsString};
use crate::marker::PhantomData;
use crate::os::unix::prelude::*;
use crate::ptr;
use crate::sync::atomic::{AtomicIsize, AtomicPtr, Ordering};
Expand Down Expand Up @@ -133,7 +133,7 @@ mod imp {
}

pub fn args() -> Args {
Args { iter: clone().into_iter(), _dont_send_or_sync_me: PhantomData }
Args { iter: clone().into_iter() }
}

fn clone() -> Vec<OsString> {
Expand All @@ -155,7 +155,6 @@ mod imp {
mod imp {
use super::Args;
use crate::ffi::CStr;
use crate::marker::PhantomData;

pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}

Expand All @@ -180,7 +179,7 @@ mod imp {
})
.collect::<Vec<_>>()
};
Args { iter: vec.into_iter(), _dont_send_or_sync_me: PhantomData }
Args { iter: vec.into_iter() }
}

// As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs
Expand Down Expand Up @@ -247,6 +246,6 @@ mod imp {
}
}

Args { iter: res.into_iter(), _dont_send_or_sync_me: PhantomData }
Args { iter: res.into_iter() }
}
}
7 changes: 4 additions & 3 deletions library/std/src/sys/unix/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use crate::ffi::{CStr, CString, OsStr, OsString};
use crate::fmt;
use crate::io;
use crate::iter;
use crate::marker::PhantomData;
use crate::mem;
use crate::memchr;
use crate::path::{self, PathBuf};
Expand Down Expand Up @@ -465,9 +464,11 @@ pub fn current_exe() -> io::Result<PathBuf> {

pub struct Env {
iter: vec::IntoIter<(OsString, OsString)>,
_dont_send_or_sync_me: PhantomData<*mut ()>,
}

impl !Send for Env {}
impl !Sync for Env {}

impl Iterator for Env {
type Item = (OsString, OsString);
fn next(&mut self) -> Option<(OsString, OsString)> {
Expand Down Expand Up @@ -515,7 +516,7 @@ pub fn env() -> Env {
environ = environ.add(1);
}
}
return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData };
return Env { iter: result.into_iter() };
}

fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
Expand Down
10 changes: 4 additions & 6 deletions library/std/src/sys/wasi/args.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#![deny(unsafe_op_in_unsafe_fn)]

use crate::ffi::{CStr, OsStr, OsString};
use crate::marker::PhantomData;
use crate::os::wasi::ffi::OsStrExt;
use crate::vec;

Expand All @@ -11,15 +10,14 @@ pub unsafe fn cleanup() {}

pub struct Args {
iter: vec::IntoIter<OsString>,
_dont_send_or_sync_me: PhantomData<*mut ()>,
}

impl !Send for Args {}
impl !Sync for Args {}

/// Returns the command line arguments
pub fn args() -> Args {
Args {
iter: maybe_args().unwrap_or(Vec::new()).into_iter(),
_dont_send_or_sync_me: PhantomData,
}
Args { iter: maybe_args().unwrap_or(Vec::new()).into_iter() }
}

fn maybe_args() -> Option<Vec<OsString>> {
Expand Down
Loading