@@ -20,14 +20,13 @@ internal func _swift_stdlib_getUnsafeArgvArgc(_: UnsafeMutablePointer<Int32>)
20
20
21
21
/// Command-line arguments for the current process.
22
22
@frozen // namespace
23
- public enum CommandLine : ~ BitwiseCopyable {
24
- }
23
+ public enum CommandLine: ~ BitwiseCopyable { }
25
24
26
25
extension CommandLine {
27
26
/// The backing static variable for argument count may come either from the
28
27
/// entry point or it may need to be computed e.g. if we're in the REPL.
29
28
@usableFromInline
30
- internal static var _argc : Int32 = Int32 ( )
29
+ internal static var _argc : Int32 = 0
31
30
32
31
/// The backing static variable for arguments may come either from the
33
32
/// entry point or it may need to be computed e.g. if we're in the REPL.
@@ -37,12 +36,27 @@ extension CommandLine {
37
36
@usableFromInline
38
37
internal static var _unsafeArgv :
39
38
UnsafeMutablePointer < UnsafeMutablePointer < Int8 > ? >
40
- = _swift_stdlib_getUnsafeArgvArgc ( & _argc)
39
+ = _swift_stdlib_getUnsafeArgvArgc ( & _argc)
41
40
42
41
/// Access to the raw argc value from C.
43
42
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
46
60
}
47
61
48
62
/// Access to the raw argv value from C.
0 commit comments