Skip to content

Commit e97203c

Browse files
committed
Stop at the first NULL argument when iterating argv
Some C commandline parsers (e.g. GLib and Qt) are replacing already handled arguments in `argv` with `NULL` and move them to the end. That means that `argc` might be bigger than the actual number of non-`NULL` pointers in `argv` at this point. To handle this we simply stop iterating at the first `NULL` argument. `argv` is also guaranteed to be `NULL`-terminated so any non-`NULL` arguments after the first `NULL` can safely be ignored. Fixes #105999
1 parent 1d12c3c commit e97203c

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

library/std/src/sys/unix/args.rs

+22-6
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,28 @@ mod imp {
141141
// list.
142142
let argv = ARGV.load(Ordering::Relaxed);
143143
let argc = if argv.is_null() { 0 } else { ARGC.load(Ordering::Relaxed) };
144-
(0..argc)
145-
.map(|i| {
146-
let cstr = CStr::from_ptr(*argv.offset(i) as *const libc::c_char);
147-
OsStringExt::from_vec(cstr.to_bytes().to_vec())
148-
})
149-
.collect()
144+
let mut args = Vec::with_capacity(argc as usize);
145+
for i in 0..argc {
146+
let ptr = *argv.offset(i) as *const libc::c_char;
147+
148+
// Some C commandline parsers (e.g. GLib and Qt) are replacing already
149+
// handled arguments in `argv` with `NULL` and move them to the end. That
150+
// means that `argc` might be bigger than the actual number of non-`NULL`
151+
// pointers in `argv` at this point.
152+
//
153+
// To handle this we simply stop iterating at the first `NULL` argument.
154+
//
155+
// `argv` is also guaranteed to be `NULL`-terminated so any non-`NULL` arguments
156+
// after the first `NULL` can safely be ignored.
157+
if ptr.is_null() {
158+
break;
159+
}
160+
161+
let cstr = CStr::from_ptr(ptr);
162+
args.push(OsStringExt::from_vec(cstr.to_bytes().to_vec()));
163+
}
164+
165+
args
150166
}
151167
}
152168
}

0 commit comments

Comments
 (0)