Skip to content

Commit efdc16b

Browse files
committed
Improve safety & usability of |size_t| and |ssize_t|.
1 parent 0f2eaa2 commit efdc16b

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
@@ -253,6 +253,50 @@ pub mod types {
253253
}
254254

255255
// Standard types that are scalar but vary by OS and arch.
256+
//
257+
// ISO C's `size_t` is defined to be the type of the result of the
258+
// `sizeof` operator and the type of the size parameter to `malloc`. That
259+
// is, C's `size_t` is only required to hold the size of the largest object
260+
// that can be allocated. In particular, it is legal for a C implementation
261+
// to have a maximum object size smaller than the entire address space. For
262+
// example, a C implementation may have an maximum object size of 2^32
263+
// bytes with a 64-bit address space, and typedef `size_t` as `uint32_t` so
264+
// that `sizeof(size_t) == 4` and `sizeof(void*) == 8`.
265+
//
266+
// Rust's `usize`, on the other hand, is defined to always be the same size
267+
// as a pointer. This means that it is possible, in theory, to have a
268+
// platform where `usize` can represent values that `size_t` cannot
269+
// represent. However, on the vast majority of systems, `usize` and
270+
// `size_t` are represented the same way. If it were required to explicitly
271+
// cast `usize` to `size_t` on common platforms, then many programmers
272+
// would habitually write expressions such as
273+
// `my_slice.len() as libc::size_t` expecting this to always work and be
274+
// safe. But such a cast is *not* safe on the uncommon platforms where
275+
// `mem::sizeof(libc::size_t) < mem::size_t(usize)`. Consequently, to
276+
// reduce the chances of programmers becoming habituated to such casts that
277+
// would be unsafe on unusual platforms, we have adopted the following
278+
// convention:
279+
//
280+
// * On common platforms where
281+
// `mem::sizeof(libc::size_t) == mem::sizeof(usize)`, `libc::size_t` must
282+
// be a type alias of `usize`, and `libc::ssize_t` must be a type alias
283+
// of `isize`.
284+
//
285+
// * On uncommon platforms where
286+
// `mem::sizeof(libc::size_t) != mem::sizeof(usize)`, `libc::size_t` and
287+
// `libc::ssize_t` must be defined as types other than `usize` and
288+
// `isize`.
289+
//
290+
// * Code that was written without consideration for the uncommon platforms
291+
// should not do any explicit casting between `libc::size_t` and `usize`
292+
// or `libc::ssize_t` and `isize`. Such code will fail to compile on the
293+
// uncommon platforms; this is better than executing with unsafe
294+
// truncations.
295+
//
296+
// * Code that was written with full consideration of the uncommon
297+
// platforms should have explicit casts using `num::cast` or other
298+
// methods that avoid unintended truncation. Such code will then work on
299+
// all platforms.
256300

257301
#[cfg(any(target_os = "linux", target_os = "android", target_os = "nacl"))]
258302
pub mod os {
@@ -471,7 +515,7 @@ pub mod types {
471515
pub type c_ulong = u32;
472516
pub type c_float = f32;
473517
pub type c_double = f64;
474-
pub type size_t = u32;
518+
pub type size_t = usize;
475519
pub type ptrdiff_t = i32;
476520
pub type clock_t = i32;
477521
pub type time_t = i32;
@@ -501,7 +545,7 @@ pub mod types {
501545
pub type gid_t = u32;
502546
pub type useconds_t = u32;
503547
pub type mode_t = u32;
504-
pub type ssize_t = i32;
548+
pub type ssize_t = isize;
505549
}
506550
#[cfg(all(any(target_arch = "arm", target_arch = "x86"),
507551
target_os = "android"))]
@@ -516,7 +560,7 @@ pub mod types {
516560
pub type useconds_t = u32;
517561

518562
pub type mode_t = u16;
519-
pub type ssize_t = i32;
563+
pub type ssize_t = isize;
520564
}
521565
#[cfg(any(all(any(target_arch = "arm", target_arch = "x86"),
522566
not(target_os = "android")),
@@ -709,7 +753,7 @@ pub mod types {
709753
pub type c_ulong = u64;
710754
pub type c_float = f32;
711755
pub type c_double = f64;
712-
pub type size_t = u64;
756+
pub type size_t = usize;
713757
pub type ptrdiff_t = i64;
714758
pub type clock_t = i64;
715759
pub type time_t = i64;
@@ -736,7 +780,7 @@ pub mod types {
736780
pub type gid_t = u32;
737781
pub type useconds_t = u32;
738782
pub type mode_t = u32;
739-
pub type ssize_t = i64;
783+
pub type ssize_t = isize;
740784
}
741785
#[cfg(not(target_arch = "aarch64"))]
742786
pub mod posix01 {
@@ -1058,7 +1102,7 @@ pub mod types {
10581102
pub type c_ulong = u32;
10591103
pub type c_float = f32;
10601104
pub type c_double = f64;
1061-
pub type size_t = u32;
1105+
pub type size_t = usize;
10621106
pub type ptrdiff_t = i32;
10631107
pub type clock_t = i32;
10641108
pub type time_t = i32;
@@ -1082,7 +1126,7 @@ pub mod types {
10821126
pub type gid_t = u32;
10831127
pub type useconds_t = u32;
10841128
pub type mode_t = u16;
1085-
pub type ssize_t = i32;
1129+
pub type ssize_t = isize;
10861130
}
10871131
pub mod posix01 {
10881132
use types::common::c95::c_void;
@@ -1154,7 +1198,7 @@ pub mod types {
11541198
pub type c_ulong = u64;
11551199
pub type c_float = f32;
11561200
pub type c_double = f64;
1157-
pub type size_t = u64;
1201+
pub type size_t = usize;
11581202
pub type ptrdiff_t = i64;
11591203
pub type clock_t = i32;
11601204
pub type time_t = i64;
@@ -1178,7 +1222,7 @@ pub mod types {
11781222
pub type gid_t = u32;
11791223
pub type useconds_t = u32;
11801224
pub type mode_t = u16;
1181-
pub type ssize_t = i64;
1225+
pub type ssize_t = isize;
11821226
}
11831227
pub mod posix01 {
11841228
use types::common::c95::c_void;
@@ -1439,7 +1483,7 @@ pub mod types {
14391483
pub type c_ulong = u64;
14401484
pub type c_float = f32;
14411485
pub type c_double = f64;
1442-
pub type size_t = u64;
1486+
pub type size_t = usize;
14431487
pub type ptrdiff_t = i64;
14441488
pub type clock_t = i32;
14451489
pub type time_t = i64;
@@ -1462,7 +1506,7 @@ pub mod types {
14621506
pub type gid_t = u32;
14631507
pub type useconds_t = u32;
14641508
pub type mode_t = u16;
1465-
pub type ssize_t = i64;
1509+
pub type ssize_t = isize;
14661510
}
14671511
pub mod posix01 {
14681512
use types::common::c95::c_void;
@@ -1775,7 +1819,7 @@ pub mod types {
17751819
pub type c_ulong = u64;
17761820
pub type c_float = f32;
17771821
pub type c_double = f64;
1778-
pub type size_t = u64;
1822+
pub type size_t = usize;
17791823
pub type ptrdiff_t = i64;
17801824
pub type clock_t = i64;
17811825
pub type time_t = i64;
@@ -1799,7 +1843,7 @@ pub mod types {
17991843
pub type gid_t = u32;
18001844
pub type useconds_t = u32;
18011845
pub type mode_t = u32;
1802-
pub type ssize_t = c_long;
1846+
pub type ssize_t = isize;
18031847
}
18041848
pub mod posix01 {
18051849
use types::common::c95::c_void;
@@ -2054,10 +2098,7 @@ pub mod types {
20542098
pub type c_float = f32;
20552099
pub type c_double = f64;
20562100

2057-
#[cfg(target_arch = "x86")]
2058-
pub type size_t = u32;
2059-
#[cfg(target_arch = "x86_64")]
2060-
pub type size_t = u64;
2101+
pub type size_t = usize;
20612102

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

2110-
#[cfg(target_arch = "x86")]
2111-
pub type ssize_t = i32;
2112-
#[cfg(target_arch = "x86_64")]
2113-
pub type ssize_t = i64;
2151+
pub type ssize_t = isize;
21142152
}
21152153

21162154
pub mod posix01 {
@@ -2586,7 +2624,7 @@ pub mod types {
25862624
pub type gid_t = u32;
25872625
pub type useconds_t = u32;
25882626
pub type mode_t = u16;
2589-
pub type ssize_t = c_long;
2627+
pub type ssize_t = isize;
25902628
}
25912629
pub mod posix01 {
25922630
use types::common::c99::{int32_t, int64_t, uint32_t};
@@ -2699,7 +2737,7 @@ pub mod types {
26992737
pub type gid_t = u32;
27002738
pub type useconds_t = u32;
27012739
pub type mode_t = u16;
2702-
pub type ssize_t = c_long;
2740+
pub type ssize_t = isize;
27032741
}
27042742
pub mod posix01 {
27052743
use types::common::c99::{int32_t, int64_t};

0 commit comments

Comments
 (0)