diff options
| author | Dylan DPC <99973273+Dylan-DPC@users.noreply.github.com> | 2023-02-11 11:15:54 +0530 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-02-11 11:15:54 +0530 |
| commit | 0e8f0b03cd94d9611063daaa516af2ae3489c6b5 (patch) | |
| tree | 1c4e1a348748109ceaa217c76412f8f631b302da /library/std/src/sys/unix/args.rs | |
| parent | 0781d5dd8e7ee76dfa2e3d6f78386231d2465a7a (diff) | |
| parent | e97203c3f893893611818997bbeb0116ded2605f (diff) | |
| download | rust-0e8f0b03cd94d9611063daaa516af2ae3489c6b5.tar.gz rust-0e8f0b03cd94d9611063daaa516af2ae3489c6b5.zip | |
Rollup merge of #106001 - sdroege:glibc-skip-over-null-argv, r=ChrisDenton
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 https://github.com/rust-lang/rust/issues/105999
Diffstat (limited to 'library/std/src/sys/unix/args.rs')
| -rw-r--r-- | library/std/src/sys/unix/args.rs | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs index a342f0f5e85..a5ce6d5120d 100644 --- a/library/std/src/sys/unix/args.rs +++ b/library/std/src/sys/unix/args.rs @@ -141,12 +141,28 @@ mod imp { // list. let argv = ARGV.load(Ordering::Relaxed); let argc = if argv.is_null() { 0 } else { ARGC.load(Ordering::Relaxed) }; - (0..argc) - .map(|i| { - let cstr = CStr::from_ptr(*argv.offset(i) as *const libc::c_char); - OsStringExt::from_vec(cstr.to_bytes().to_vec()) - }) - .collect() + let mut args = Vec::with_capacity(argc as usize); + for i in 0..argc { + let ptr = *argv.offset(i) as *const libc::c_char; + + // 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. + if ptr.is_null() { + break; + } + + let cstr = CStr::from_ptr(ptr); + args.push(OsStringExt::from_vec(cstr.to_bytes().to_vec())); + } + + args } } } |
