Skip to content

Commit 2dbaccd

Browse files
committed
Improve safety & usability of |size_t| and |ssize_t|.
1 parent 7bb0d0d commit 2dbaccd

File tree

1 file changed

+61
-23
lines changed

1 file changed

+61
-23
lines changed

src/liblibc/lib.rs

Lines changed: 61 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,50 @@ pub mod types {
228228
}
229229

230230
// Standard types that are scalar but vary by OS and arch.
231+
//
232+
// ISO C's `size_t` is defined to be the type of the result of the
233+
// `sizeof` operator and the type of the size parameter to `malloc`. That
234+
// is, C's `size_t` is only required to hold the size of the largest object
235+
// that can be allocated. In particular, it is legal for a C implementation
236+
// to have a maximum object size smaller than the entire address space. For
237+
// example, a C implementation may have an maximum object size of 2^32
238+
// bytes with a 64-bit address space, and typedef `size_t` as `uint32_t` so
239+
// that `sizeof(size_t) == 4` and `sizeof(void*) == 8`.
240+
//
241+
// Rust's `usize`, on the other hand, is defined to always be the same size
242+
// as a pointer. This means that it is possible, in theory, to have a
243+
// platform where `usize` can represent values that `size_t` cannot
244+
// represent. However, on the vast majority of systems, `usize` and
245+
// `size_t` are represented the same way. If it were required to explicitly
246+
// cast `usize` to `size_t` on common platforms, then many programmers
247+
// would habitually write expressions such as
248+
// `my_slice.len() as libc::size_t` expecting this to always work and be
249+
// safe. But such a cast is *not* safe on the uncommon platforms where
250+
// `mem::sizeof(libc::size_t) < mem::size_t(usize)`. Consequently, to
251+
// reduce the chances of programmers becoming habituated to such casts that
252+
// would be unsafe on unusual platforms, we have adopted the following
253+
// convention:
254+
//
255+
// * On common platforms where
256+
// `mem::sizeof(libc::size_t) == mem::sizeof(usize)`, `libc::size_t` must
257+
// be a type alias of `usize`, and `libc::ssize_t` must be a type alias
258+
// of `isize`.
259+
//
260+
// * On uncommon platforms where
261+
// `mem::sizeof(libc::size_t) != mem::sizeof(usize)`, `libc::size_t` and
262+
// `libc::ssize_t` must be defined as types other than `usize` and
263+
// `isize`.
264+
//
265+
// * Code that was written without consideration for the uncommon platforms
266+
// should not do any explicit casting between `libc::size_t` and `usize`
267+
// or `libc::ssize_t` and `isize`. Such code will fail to compile on the
268+
// uncommon platforms; this is better than executing with unsafe
269+
// truncations.
270+
//
271+
// * Code that was written with full consideration of the uncommon
272+
// platforms should have explicit casts using `num::cast` or other
273+
// methods that avoid unintended truncation. Such code will then work on
274+
// all platforms.
231275

232276
#[cfg(any(target_os = "linux", target_os = "android", target_os = "nacl"))]
233277
pub mod os {
@@ -429,7 +473,7 @@ pub mod types {
429473
pub type c_ulong = u32;
430474
pub type c_float = f32;
431475
pub type c_double = f64;
432-
pub type size_t = u32;
476+
pub type size_t = usize;
433477
pub type ptrdiff_t = i32;
434478
pub type clock_t = i32;
435479
pub type time_t = i32;
@@ -459,7 +503,7 @@ pub mod types {
459503
pub type gid_t = u32;
460504
pub type useconds_t = u32;
461505
pub type mode_t = u32;
462-
pub type ssize_t = i32;
506+
pub type ssize_t = isize;
463507
}
464508
#[cfg(all(any(target_arch = "arm", target_arch = "x86"),
465509
target_os = "android"))]
@@ -474,7 +518,7 @@ pub mod types {
474518
pub type useconds_t = u32;
475519

476520
pub type mode_t = u16;
477-
pub type ssize_t = i32;
521+
pub type ssize_t = isize;
478522
}
479523
#[cfg(any(all(any(target_arch = "arm", target_arch = "x86"),
480524
not(target_os = "android")),
@@ -655,7 +699,7 @@ pub mod types {
655699
pub type c_ulong = u64;
656700
pub type c_float = f32;
657701
pub type c_double = f64;
658-
pub type size_t = u64;
702+
pub type size_t = usize;
659703
pub type ptrdiff_t = i64;
660704
pub type clock_t = i64;
661705
pub type time_t = i64;
@@ -682,7 +726,7 @@ pub mod types {
682726
pub type gid_t = u32;
683727
pub type useconds_t = u32;
684728
pub type mode_t = u32;
685-
pub type ssize_t = i64;
729+
pub type ssize_t = isize;
686730
}
687731
#[cfg(not(target_arch = "aarch64"))]
688732
pub mod posix01 {
@@ -980,7 +1024,7 @@ pub mod types {
9801024
pub type c_ulong = u32;
9811025
pub type c_float = f32;
9821026
pub type c_double = f64;
983-
pub type size_t = u32;
1027+
pub type size_t = usize;
9841028
pub type ptrdiff_t = i32;
9851029
pub type clock_t = i32;
9861030
pub type time_t = i32;
@@ -1004,7 +1048,7 @@ pub mod types {
10041048
pub type gid_t = u32;
10051049
pub type useconds_t = u32;
10061050
pub type mode_t = u16;
1007-
pub type ssize_t = i32;
1051+
pub type ssize_t = isize;
10081052
}
10091053
pub mod posix01 {
10101054
use types::common::c95::{c_void};
@@ -1074,7 +1118,7 @@ pub mod types {
10741118
pub type c_ulong = u64;
10751119
pub type c_float = f32;
10761120
pub type c_double = f64;
1077-
pub type size_t = u64;
1121+
pub type size_t = usize;
10781122
pub type ptrdiff_t = i64;
10791123
pub type clock_t = i32;
10801124
pub type time_t = i64;
@@ -1098,7 +1142,7 @@ pub mod types {
10981142
pub type gid_t = u32;
10991143
pub type useconds_t = u32;
11001144
pub type mode_t = u16;
1101-
pub type ssize_t = i64;
1145+
pub type ssize_t = isize;
11021146
}
11031147
pub mod posix01 {
11041148
use types::common::c95::{c_void};
@@ -1340,7 +1384,7 @@ pub mod types {
13401384
pub type c_ulong = u64;
13411385
pub type c_float = f32;
13421386
pub type c_double = f64;
1343-
pub type size_t = u64;
1387+
pub type size_t = usize;
13441388
pub type ptrdiff_t = i64;
13451389
pub type clock_t = i32;
13461390
pub type time_t = i64;
@@ -1363,7 +1407,7 @@ pub mod types {
13631407
pub type gid_t = u32;
13641408
pub type useconds_t = u32;
13651409
pub type mode_t = u16;
1366-
pub type ssize_t = i64;
1410+
pub type ssize_t = isize;
13671411
}
13681412
pub mod posix01 {
13691413
use types::common::c95::{c_void};
@@ -1625,7 +1669,7 @@ pub mod types {
16251669
pub type c_ulong = u64;
16261670
pub type c_float = f32;
16271671
pub type c_double = f64;
1628-
pub type size_t = u64;
1672+
pub type size_t = usize;
16291673
pub type ptrdiff_t = i64;
16301674
pub type clock_t = i64;
16311675
pub type time_t = i64;
@@ -1649,7 +1693,7 @@ pub mod types {
16491693
pub type gid_t = u32;
16501694
pub type useconds_t = u32;
16511695
pub type mode_t = u32;
1652-
pub type ssize_t = c_long;
1696+
pub type ssize_t = isize;
16531697
}
16541698
pub mod posix01 {
16551699
use types::common::c95::{c_void};
@@ -1845,10 +1889,7 @@ pub mod types {
18451889
pub type c_float = f32;
18461890
pub type c_double = f64;
18471891

1848-
#[cfg(target_arch = "x86")]
1849-
pub type size_t = u32;
1850-
#[cfg(target_arch = "x86_64")]
1851-
pub type size_t = u64;
1892+
pub type size_t = usize;
18521893

18531894
#[cfg(target_arch = "x86")]
18541895
pub type ptrdiff_t = i32;
@@ -1898,10 +1939,7 @@ pub mod types {
18981939
pub type useconds_t = u32;
18991940
pub type mode_t = u16;
19001941

1901-
#[cfg(target_arch = "x86")]
1902-
pub type ssize_t = i32;
1903-
#[cfg(target_arch = "x86_64")]
1904-
pub type ssize_t = i64;
1942+
pub type ssize_t = isize;
19051943
}
19061944

19071945
pub mod posix01 {
@@ -2345,7 +2383,7 @@ pub mod types {
23452383
pub type gid_t = u32;
23462384
pub type useconds_t = u32;
23472385
pub type mode_t = u16;
2348-
pub type ssize_t = c_long;
2386+
pub type ssize_t = isize;
23492387
}
23502388
pub mod posix01 {
23512389
use types::common::c99::{int32_t, int64_t, uint32_t};
@@ -2453,7 +2491,7 @@ pub mod types {
24532491
pub type gid_t = u32;
24542492
pub type useconds_t = u32;
24552493
pub type mode_t = u16;
2456-
pub type ssize_t = c_long;
2494+
pub type ssize_t = isize;
24572495
}
24582496
pub mod posix01 {
24592497
use types::common::c99::{int32_t, int64_t};

0 commit comments

Comments
 (0)