Skip to content

Commit 40bc8a5

Browse files
committed
SR-6968: ProcessInfo.processInfo.environment only gets once
- Reparse the environment variables each time ProcessInfo.processinfo.enviroment is read.
1 parent cd24576 commit 40bc8a5

File tree

2 files changed

+59
-7
lines changed

2 files changed

+59
-7
lines changed

Foundation/ProcessInfo.swift

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,28 @@ open class ProcessInfo: NSObject {
4141

4242
}
4343

44-
45-
internal static var _environment: [String : String] = {
46-
return Dictionary<String, String>._unconditionallyBridgeFromObjectiveC(__CFGetEnvironment()._nsObject)
47-
}()
48-
4944
open var environment: [String : String] {
50-
return ProcessInfo._environment
45+
let equalSign = Int32(UInt8(ascii: "="))
46+
var env: [String : String] = [:]
47+
var idx = 0
48+
let envp = environ
49+
50+
while let entry = envp.advanced(by: idx).pointee {
51+
if let value = strchr(entry, equalSign) {
52+
let keyLen = entry.distance(to: value)
53+
guard keyLen > 0 else {
54+
continue
55+
}
56+
if let key = NSString(bytes: entry, length: keyLen, encoding: String.Encoding.utf8.rawValue) {
57+
env[key._swiftObject] = String(cString: value.advanced(by: 1))
58+
}
59+
} else {
60+
let key = String(cString: entry)
61+
env[key] = ""
62+
}
63+
idx += 1
64+
}
65+
return env
5166
}
5267

5368
open var arguments: [String] {

TestFoundation/TestProcessInfo.swift

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class TestProcessInfo : XCTestCase {
2424
("test_operatingSystemVersion", test_operatingSystemVersion ),
2525
("test_processName", test_processName ),
2626
("test_globallyUniqueString", test_globallyUniqueString ),
27+
("test_environment", test_environment),
2728
]
2829
}
2930

@@ -66,5 +67,41 @@ class TestProcessInfo : XCTestCase {
6667
XCTAssertEqual(parts[3].utf16.count, 4)
6768
XCTAssertEqual(parts[4].utf16.count, 12)
6869
}
69-
70+
71+
func test_environment() {
72+
let preset = ProcessInfo.processInfo.environment["test"]
73+
setenv("test", "worked", 1)
74+
let postset = ProcessInfo.processInfo.environment["test"]
75+
XCTAssertNil(preset)
76+
XCTAssertEqual(postset, "worked")
77+
78+
// Bad values that wont be stored
79+
XCTAssertEqual(setenv("", "", 1), -1)
80+
XCTAssertEqual(setenv("bad1=", "", 1), -1)
81+
XCTAssertEqual(setenv("bad2=", "1", 1) ,-1)
82+
XCTAssertEqual(setenv("bad3=", "=2", 1), -1)
83+
84+
// Good values that will be, check splitting on '='
85+
XCTAssertEqual(setenv("var1", "",1 ), 0)
86+
XCTAssertEqual(setenv("var2", "=", 1), 0)
87+
XCTAssertEqual(setenv("var3", "=x", 1), 0)
88+
XCTAssertEqual(setenv("var4", "x=", 1), 0)
89+
XCTAssertEqual(setenv("var5", "=x=", 1), 0)
90+
91+
let env = ProcessInfo.processInfo.environment
92+
93+
XCTAssertNil(env[""])
94+
XCTAssertNil(env["bad1"])
95+
XCTAssertNil(env["bad1="])
96+
XCTAssertNil(env["bad2"])
97+
XCTAssertNil(env["bad2="])
98+
XCTAssertNil(env["bad3"])
99+
XCTAssertNil(env["bad3="])
100+
101+
XCTAssertEqual(env["var1"], "")
102+
XCTAssertEqual(env["var2"], "=")
103+
XCTAssertEqual(env["var3"], "=x")
104+
XCTAssertEqual(env["var4"], "x=")
105+
XCTAssertEqual(env["var5"], "=x=")
106+
}
70107
}

0 commit comments

Comments
 (0)