Skip to content

Commit 058a0f0

Browse files
committed
liblibc: Fix prototype of functions taking char *const argv[]
The execv family of functions do not modify their arguments, so they do not need mutable pointers. The C prototypes take a constant array of mutable C-strings, but that's a legacy quirk from before C had const (since C string literals have type `char *`). The Rust prototypes had `*mut` in the wrong place, anyway: to match the C prototypes, it should have been `*const *mut c_char`. But it is safe to pass constant strings (like string literals) to these functions. getopt is a special case, since GNU getopt modifies its arguments despite the `const` claim in the prototype. It is apparently only well-defined to call getopt on the actual argc and argv parameters passed to main, anyway. Change it to take `*mut *mut c_char` for an attempt at safety, but probably nobody should be using it from Rust, since there's no great way to get at the parameters as passed to main. Also fix the one caller of execvp in libstd, which now no longer needs an unsafe cast. Fixes #16290.
1 parent a951569 commit 058a0f0

File tree

2 files changed

+19
-17
lines changed

2 files changed

+19
-17
lines changed

src/liblibc/lib.rs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5493,17 +5493,17 @@ pub mod funcs {
54935493
pub fn dup2(src: c_int, dst: c_int) -> c_int;
54945494
#[link_name = "_execv"]
54955495
pub fn execv(prog: *const c_char,
5496-
argv: *mut *const c_char) -> intptr_t;
5496+
argv: *const *const c_char) -> intptr_t;
54975497
#[link_name = "_execve"]
5498-
pub fn execve(prog: *const c_char, argv: *mut *const c_char,
5499-
envp: *mut *const c_char)
5498+
pub fn execve(prog: *const c_char, argv: *const *const c_char,
5499+
envp: *const *const c_char)
55005500
-> c_int;
55015501
#[link_name = "_execvp"]
55025502
pub fn execvp(c: *const c_char,
5503-
argv: *mut *const c_char) -> c_int;
5503+
argv: *const *const c_char) -> c_int;
55045504
#[link_name = "_execvpe"]
5505-
pub fn execvpe(c: *const c_char, argv: *mut *const c_char,
5506-
envp: *mut *const c_char) -> c_int;
5505+
pub fn execvpe(c: *const c_char, argv: *const *const c_char,
5506+
envp: *const *const c_char) -> c_int;
55075507
#[link_name = "_getcwd"]
55085508
pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char;
55095509
#[link_name = "_getpid"]
@@ -5687,12 +5687,12 @@ pub mod funcs {
56875687
pub fn dup(fd: c_int) -> c_int;
56885688
pub fn dup2(src: c_int, dst: c_int) -> c_int;
56895689
pub fn execv(prog: *const c_char,
5690-
argv: *mut *const c_char) -> c_int;
5691-
pub fn execve(prog: *const c_char, argv: *mut *const c_char,
5692-
envp: *mut *const c_char)
5690+
argv: *const *const c_char) -> c_int;
5691+
pub fn execve(prog: *const c_char, argv: *const *const c_char,
5692+
envp: *const *const c_char)
56935693
-> c_int;
56945694
pub fn execvp(c: *const c_char,
5695-
argv: *mut *const c_char) -> c_int;
5695+
argv: *const *const c_char) -> c_int;
56965696
pub fn fork() -> pid_t;
56975697
pub fn fpathconf(filedes: c_int, name: c_int) -> c_long;
56985698
pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char;
@@ -5702,7 +5702,9 @@ pub mod funcs {
57025702
pub fn getgroups(ngroups_max: c_int, groups: *mut gid_t)
57035703
-> c_int;
57045704
pub fn getlogin() -> *mut c_char;
5705-
pub fn getopt(argc: c_int, argv: *mut *const c_char,
5705+
// GNU getopt(3) modifies its arguments despite the
5706+
// char * const [] prototype; see the manpage.
5707+
pub fn getopt(argc: c_int, argv: *mut *mut c_char,
57065708
optstr: *const c_char) -> c_int;
57075709
pub fn getpgrp() -> pid_t;
57085710
pub fn getpid() -> pid_t;
@@ -5752,19 +5754,19 @@ pub mod funcs {
57525754
pub fn dup(fd: c_int) -> c_int;
57535755
pub fn dup2(src: c_int, dst: c_int) -> c_int;
57545756
pub fn execv(prog: *const c_char,
5755-
argv: *mut *const c_char) -> c_int;
5756-
pub fn execve(prog: *const c_char, argv: *mut *const c_char,
5757-
envp: *mut *const c_char)
5757+
argv: *const *const c_char) -> c_int;
5758+
pub fn execve(prog: *const c_char, argv: *const *const c_char,
5759+
envp: *const *const c_char)
57585760
-> c_int;
57595761
pub fn execvp(c: *const c_char,
5760-
argv: *mut *const c_char) -> c_int;
5762+
argv: *const *const c_char) -> c_int;
57615763
pub fn fork() -> pid_t;
57625764
pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char;
57635765
pub fn getegid() -> gid_t;
57645766
pub fn geteuid() -> uid_t;
57655767
pub fn getgid() -> gid_t;
57665768
pub fn getlogin() -> *mut c_char;
5767-
pub fn getopt(argc: c_int, argv: *mut *const c_char,
5769+
pub fn getopt(argc: c_int, argv: *const *const c_char,
57685770
optstr: *const c_char) -> c_int;
57695771
pub fn getuid() -> uid_t;
57705772
pub fn getsid(pid: pid_t) -> pid_t;

src/libstd/sys/unix/process.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ impl Process {
313313
if !envp.is_null() {
314314
*sys::os::environ() = envp as *const _;
315315
}
316-
let _ = libc::execvp(*argv, argv as *mut _);
316+
let _ = libc::execvp(*argv, argv);
317317
fail(&mut output)
318318
}
319319

0 commit comments

Comments
 (0)