Skip to content

Improve safety & usability of |size_t| and |ssize_t|. #29222

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Changes from all commits
Commits
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
10 changes: 5 additions & 5 deletions src/liballoc_jemalloc/lib.rs
Original file line number Diff line number Diff line change
@@ -77,7 +77,7 @@ fn align_to_flags(align: usize) -> c_int {
#[no_mangle]
pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
let flags = align_to_flags(align);
unsafe { je_mallocx(size as size_t, flags) as *mut u8 }
unsafe { je_mallocx(size, flags) as *mut u8 }
}

#[no_mangle]
@@ -87,7 +87,7 @@ pub extern "C" fn __rust_reallocate(ptr: *mut u8,
align: usize)
-> *mut u8 {
let flags = align_to_flags(align);
unsafe { je_rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8 }
unsafe { je_rallocx(ptr as *mut c_void, size, flags) as *mut u8 }
}

#[no_mangle]
@@ -97,17 +97,17 @@ pub extern "C" fn __rust_reallocate_inplace(ptr: *mut u8,
align: usize)
-> usize {
let flags = align_to_flags(align);
unsafe { je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) as usize }
unsafe { je_xallocx(ptr as *mut c_void, size, 0, flags) }
}

#[no_mangle]
pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) {
let flags = align_to_flags(align);
unsafe { je_sdallocx(ptr as *mut c_void, old_size as size_t, flags) }
unsafe { je_sdallocx(ptr as *mut c_void, old_size, flags) }
}

#[no_mangle]
pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize {
let flags = align_to_flags(align);
unsafe { je_nallocx(size as size_t, flags) as usize }
unsafe { je_nallocx(size, flags) }
}
12 changes: 6 additions & 6 deletions src/liballoc_system/lib.rs
Original file line number Diff line number Diff line change
@@ -92,16 +92,16 @@ mod imp {

pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
if align <= MIN_ALIGN {
libc::malloc(size as libc::size_t) as *mut u8
libc::malloc(size) as *mut u8
} else {
#[cfg(target_os = "android")]
unsafe fn more_aligned_malloc(size: usize, align: usize) -> *mut u8 {
memalign(align as libc::size_t, size as libc::size_t) as *mut u8
memalign(align, size) as *mut u8
}
#[cfg(not(target_os = "android"))]
unsafe fn more_aligned_malloc(size: usize, align: usize) -> *mut u8 {
let mut out = ptr::null_mut();
let ret = posix_memalign(&mut out, align as libc::size_t, size as libc::size_t);
let ret = posix_memalign(&mut out, align, size);
if ret != 0 {
ptr::null_mut()
} else {
@@ -114,7 +114,7 @@ mod imp {

pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
if align <= MIN_ALIGN {
libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
libc::realloc(ptr as *mut libc::c_void, size) as *mut u8
} else {
let new_ptr = allocate(size, align);
ptr::copy(ptr, new_ptr, cmp::min(size, old_size));
@@ -171,7 +171,7 @@ mod imp {
if align <= MIN_ALIGN {
HeapAlloc(GetProcessHeap(), 0, size as SIZE_T) as *mut u8
} else {
let ptr = HeapAlloc(GetProcessHeap(), 0, (size + align) as SIZE_T) as *mut u8;
let ptr = HeapAlloc(GetProcessHeap(), 0, size + align) as *mut u8;
if ptr.is_null() {
return ptr
}
@@ -204,7 +204,7 @@ mod imp {
let new = HeapReAlloc(GetProcessHeap(),
HEAP_REALLOC_IN_PLACE_ONLY,
ptr as LPVOID,
size as SIZE_T) as *mut u8;
size) as *mut u8;
if new.is_null() {
old_size
} else {
12 changes: 9 additions & 3 deletions src/libcore/num/mod.rs
Original file line number Diff line number Diff line change
@@ -1473,9 +1473,12 @@ impl fmt::Display for ParseIntError {

pub use num::dec2flt::ParseFloatError;

// Conversion traits for primitive integer types
// Conversions T -> T are covered by a blanket impl and therefore excluded
// Some conversions from and to usize/isize are not implemented due to portability concerns
// Conversion traits for primitive integer types (only) where the conversion is
// guaranteed to be lossless on all platforms. Conversions T -> T are covered
// by a blanket impl and therefore excluded. Conversions from `usize` and
// `isize` to other types are not implemented because there are no primitive
// integer types that are defined to be at least as large as them on all
// architectures.
macro_rules! impl_from {
($Small: ty, $Large: ty) => {
#[stable(feature = "lossless_int_conv", since = "1.5.0")]
@@ -1496,6 +1499,7 @@ impl_from! { u8, u64 }
impl_from! { u8, usize }
impl_from! { u16, u32 }
impl_from! { u16, u64 }
impl_from! { u16, usize }
impl_from! { u32, u64 }

// Signed -> Signed
@@ -1505,12 +1509,14 @@ impl_from! { i8, i64 }
impl_from! { i8, isize }
impl_from! { i16, i32 }
impl_from! { i16, i64 }
impl_from! { i16, isize }
impl_from! { i32, i64 }

// Unsigned -> Signed
impl_from! { u8, i16 }
impl_from! { u8, i32 }
impl_from! { u8, i64 }
impl_from! { u8, isize }
impl_from! { u16, i32 }
impl_from! { u16, i64 }
impl_from! { u32, i64 }
10 changes: 3 additions & 7 deletions src/libflate/lib.rs
Original file line number Diff line number Diff line change
@@ -103,10 +103,8 @@ const TDEFL_WRITE_ZLIB_HEADER: c_int = 0x01000; // write zlib header and adler32
fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Bytes {
unsafe {
let mut outsz: size_t = 0;
let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _,
bytes.len() as size_t,
&mut outsz,
flags);
let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _, bytes.len(),
&mut outsz, flags);
assert!(!res.is_null());
Bytes {
ptr: Unique::new(res as *mut u8),
@@ -129,9 +127,7 @@ fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Result<Bytes, Error> {
unsafe {
let mut outsz: size_t = 0;
let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *const _,
bytes.len() as size_t,
&mut outsz,
flags);
bytes.len(), &mut outsz, flags);
if !res.is_null() {
Ok(Bytes {
ptr: Unique::new(res as *mut u8),
84 changes: 61 additions & 23 deletions src/liblibc/lib.rs
Original file line number Diff line number Diff line change
@@ -253,6 +253,50 @@ pub mod types {
}

// Standard types that are scalar but vary by OS and arch.
//
// ISO C's `size_t` is defined to be the type of the result of the
// `sizeof` operator and the type of the size parameter to `malloc`. That
// is, C's `size_t` is only required to hold the size of the largest object
// that can be allocated. In particular, it is legal for a C implementation
// to have a maximum object size smaller than the entire address space. For
// example, a C implementation may have an maximum object size of 2^32
// bytes with a 64-bit address space, and typedef `size_t` as `uint32_t` so
// that `sizeof(size_t) == 4` and `sizeof(void*) == 8`.
//
// Rust's `usize`, on the other hand, is defined to always be the same size
// as a pointer. This means that it is possible, in theory, to have a
// platform where `usize` can represent values that `size_t` cannot
// represent. However, on the vast majority of systems, `usize` and
// `size_t` are represented the same way. If it were required to explicitly
// cast `usize` to `size_t` on common platforms, then many programmers
// would habitually write expressions such as
// `my_slice.len() as libc::size_t` expecting this to always work and be
// safe. But such a cast is *not* safe on the uncommon platforms where
// `mem::sizeof(libc::size_t) < mem::size_t(usize)`. Consequently, to
// reduce the chances of programmers becoming habituated to such casts that
// would be unsafe on unusual platforms, we have adopted the following
// convention:
//
// * On common platforms where
// `mem::sizeof(libc::size_t) == mem::sizeof(usize)`, `libc::size_t` must
// be a type alias of `usize`, and `libc::ssize_t` must be a type alias
// of `isize`.
//
// * On uncommon platforms where
// `mem::sizeof(libc::size_t) != mem::sizeof(usize)`, `libc::size_t` and
// `libc::ssize_t` must be defined as types other than `usize` and
// `isize`.
//
// * Code that was written without consideration for the uncommon platforms
// should not do any explicit casting between `libc::size_t` and `usize`
// or `libc::ssize_t` and `isize`. Such code will fail to compile on the
// uncommon platforms; this is better than executing with unsafe
// truncations.
//
// * Code that was written with full consideration of the uncommon
// platforms should have explicit casts using `num::cast` or other
// methods that avoid unintended truncation. Such code will then work on
// all platforms.

#[cfg(any(target_os = "linux", target_os = "android", target_os = "nacl"))]
pub mod os {
@@ -471,7 +515,7 @@ pub mod types {
pub type c_ulong = u32;
pub type c_float = f32;
pub type c_double = f64;
pub type size_t = u32;
pub type size_t = usize;
pub type ptrdiff_t = i32;
pub type clock_t = i32;
pub type time_t = i32;
@@ -501,7 +545,7 @@ pub mod types {
pub type gid_t = u32;
pub type useconds_t = u32;
pub type mode_t = u32;
pub type ssize_t = i32;
pub type ssize_t = isize;
}
#[cfg(all(any(target_arch = "arm", target_arch = "x86"),
target_os = "android"))]
@@ -516,7 +560,7 @@ pub mod types {
pub type useconds_t = u32;

pub type mode_t = u16;
pub type ssize_t = i32;
pub type ssize_t = isize;
}
#[cfg(any(all(any(target_arch = "arm", target_arch = "x86"),
not(target_os = "android")),
@@ -709,7 +753,7 @@ pub mod types {
pub type c_ulong = u64;
pub type c_float = f32;
pub type c_double = f64;
pub type size_t = u64;
pub type size_t = usize;
pub type ptrdiff_t = i64;
pub type clock_t = i64;
pub type time_t = i64;
@@ -736,7 +780,7 @@ pub mod types {
pub type gid_t = u32;
pub type useconds_t = u32;
pub type mode_t = u32;
pub type ssize_t = i64;
pub type ssize_t = isize;
}
#[cfg(not(target_arch = "aarch64"))]
pub mod posix01 {
@@ -1058,7 +1102,7 @@ pub mod types {
pub type c_ulong = u32;
pub type c_float = f32;
pub type c_double = f64;
pub type size_t = u32;
pub type size_t = usize;
pub type ptrdiff_t = i32;
pub type clock_t = i32;
pub type time_t = i32;
@@ -1082,7 +1126,7 @@ pub mod types {
pub type gid_t = u32;
pub type useconds_t = u32;
pub type mode_t = u16;
pub type ssize_t = i32;
pub type ssize_t = isize;
}
pub mod posix01 {
use types::common::c95::c_void;
@@ -1154,7 +1198,7 @@ pub mod types {
pub type c_ulong = u64;
pub type c_float = f32;
pub type c_double = f64;
pub type size_t = u64;
pub type size_t = usize;
pub type ptrdiff_t = i64;
pub type clock_t = i32;
pub type time_t = i64;
@@ -1178,7 +1222,7 @@ pub mod types {
pub type gid_t = u32;
pub type useconds_t = u32;
pub type mode_t = u16;
pub type ssize_t = i64;
pub type ssize_t = isize;
}
pub mod posix01 {
use types::common::c95::c_void;
@@ -1439,7 +1483,7 @@ pub mod types {
pub type c_ulong = u64;
pub type c_float = f32;
pub type c_double = f64;
pub type size_t = u64;
pub type size_t = usize;
pub type ptrdiff_t = i64;
pub type clock_t = i32;
pub type time_t = i64;
@@ -1462,7 +1506,7 @@ pub mod types {
pub type gid_t = u32;
pub type useconds_t = u32;
pub type mode_t = u16;
pub type ssize_t = i64;
pub type ssize_t = isize;
}
pub mod posix01 {
use types::common::c95::c_void;
@@ -1775,7 +1819,7 @@ pub mod types {
pub type c_ulong = u64;
pub type c_float = f32;
pub type c_double = f64;
pub type size_t = u64;
pub type size_t = usize;
pub type ptrdiff_t = i64;
pub type clock_t = i64;
pub type time_t = i64;
@@ -1799,7 +1843,7 @@ pub mod types {
pub type gid_t = u32;
pub type useconds_t = u32;
pub type mode_t = u32;
pub type ssize_t = c_long;
pub type ssize_t = isize;
}
pub mod posix01 {
use types::common::c95::c_void;
@@ -2054,10 +2098,7 @@ pub mod types {
pub type c_float = f32;
pub type c_double = f64;

#[cfg(target_arch = "x86")]
pub type size_t = u32;
#[cfg(target_arch = "x86_64")]
pub type size_t = u64;
pub type size_t = usize;

#[cfg(target_arch = "x86")]
pub type ptrdiff_t = i32;
@@ -2107,10 +2148,7 @@ pub mod types {
pub type useconds_t = u32;
pub type mode_t = u16;

#[cfg(target_arch = "x86")]
pub type ssize_t = i32;
#[cfg(target_arch = "x86_64")]
pub type ssize_t = i64;
pub type ssize_t = isize;
}

pub mod posix01 {
@@ -2586,7 +2624,7 @@ pub mod types {
pub type gid_t = u32;
pub type useconds_t = u32;
pub type mode_t = u16;
pub type ssize_t = c_long;
pub type ssize_t = isize;
}
pub mod posix01 {
use types::common::c99::{int32_t, int64_t, uint32_t};
@@ -2699,7 +2737,7 @@ pub mod types {
pub type gid_t = u32;
pub type useconds_t = u32;
pub type mode_t = u16;
pub type ssize_t = c_long;
pub type ssize_t = isize;
}
pub mod posix01 {
use types::common::c99::{int32_t, int64_t};
4 changes: 1 addition & 3 deletions src/librustc_trans/back/archive.rs
Original file line number Diff line number Diff line change
@@ -21,7 +21,6 @@ use std::process::{Command, Output, Stdio};
use std::ptr;
use std::str;

use libc;
use llvm::archive_ro::{ArchiveRO, Child};
use llvm::{self, ArchiveKind};
use rustc::metadata::loader::METADATA_FILENAME;
@@ -489,8 +488,7 @@ impl<'a> ArchiveBuilder<'a> {

let dst = self.config.dst.to_str().unwrap().as_bytes();
let dst = try!(CString::new(dst));
let r = llvm::LLVMRustWriteArchive(dst.as_ptr(),
members.len() as libc::size_t,
let r = llvm::LLVMRustWriteArchive(dst.as_ptr(), members.len(),
members.as_ptr(),
self.should_update_symbols,
kind);
4 changes: 2 additions & 2 deletions src/librustc_trans/back/lto.rs
Original file line number Diff line number Diff line change
@@ -100,7 +100,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
time(sess.time_passes(), &format!("ll link {}", name), || unsafe {
if !llvm::LLVMRustLinkInExternalBitcode(llmod,
ptr as *const libc::c_char,
bc_decoded.len() as libc::size_t) {
bc_decoded.len()) {
write::llvm_err(sess.diagnostic().handler(),
format!("failed to load bc of `{}`",
&name[..]));
@@ -118,7 +118,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
unsafe {
llvm::LLVMRustRunRestrictionPass(llmod,
ptr as *const *const libc::c_char,
arr.len() as libc::size_t);
arr.len());
}

if sess.no_landing_pads() {
Loading