about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2023-02-11 11:15:54 +0530
committerGitHub <noreply@github.com>2023-02-11 11:15:54 +0530
commit0e8f0b03cd94d9611063daaa516af2ae3489c6b5 (patch)
tree1c4e1a348748109ceaa217c76412f8f631b302da /library/std/src
parent0781d5dd8e7ee76dfa2e3d6f78386231d2465a7a (diff)
parente97203c3f893893611818997bbeb0116ded2605f (diff)
downloadrust-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')
-rw-r--r--library/std/src/sys/unix/args.rs28
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
         }
     }
 }