@@ -20,14 +20,13 @@ internal func _swift_stdlib_getUnsafeArgvArgc(_: UnsafeMutablePointer<Int32>)
2020
2121/// Command-line arguments for the current process.
2222@frozen // namespace
23- public enum CommandLine : ~ BitwiseCopyable {
24- }
23+ public enum CommandLine: ~ BitwiseCopyable { }
2524
2625extension CommandLine {
2726 /// The backing static variable for argument count may come either from the
2827 /// entry point or it may need to be computed e.g. if we're in the REPL.
2928 @usableFromInline
30- internal static var _argc : Int32 = Int32 ( )
29+ internal static var _argc : Int32 = 0
3130
3231 /// The backing static variable for arguments may come either from the
3332 /// entry point or it may need to be computed e.g. if we're in the REPL.
@@ -37,12 +36,27 @@ extension CommandLine {
3736 @usableFromInline
3837 internal static var _unsafeArgv :
3938 UnsafeMutablePointer < UnsafeMutablePointer < Int8 > ? >
40- = _swift_stdlib_getUnsafeArgvArgc ( & _argc)
39+ = _swift_stdlib_getUnsafeArgvArgc ( & _argc)
4140
4241 /// Access to the raw argc value from C.
4342 public static var argc : Int32 {
44- _ = CommandLine . unsafeArgv // Force evaluation of argv.
45- return _argc
43+ // We intentionally ignore the argc value given to us from
44+ // '_swift_stdlib_getUnsafeArgvArgc' because argv and argc are mutable, so
45+ // someone can mutate the contents of argv and never update the argc value.
46+ // This results in an out of sync argc which can lead to crashes on first
47+ // access to 'CommandLine.arguments' due to attempting to read '0 ..< argc'
48+ // strings.
49+ //
50+ // Note: It's still entirely possible that someone may update argv after
51+ // this iteration and before we actually read argv, but we have no control
52+ // over synchronizing access to argc and argv.
53+ var argc : Int32 = 0
54+
55+ while let _ = _unsafeArgv [ Int ( argc) ] {
56+ argc += 1
57+ }
58+
59+ return argc
4660 }
4761
4862 /// Access to the raw argv value from C.
0 commit comments