Skip to content

Merge main into package #4961

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Docs/GettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ swift-corelibs-foundation swift-corelibs-xctest

Build and test steps:

0. Run Xcode with the latest toolchain. Follow [the instructions here](https://swift.org/download/#installation) to start Xcode with the correct toolchain.
0. Run Xcode with the latest toolchain. Follow [the instructions here](https://www.swift.org/install/macos/#installation-via-swiftorg-package-installer) to start Xcode with the correct toolchain.
0. Open `Foundation.xcworkspace`.
0. Build the _SwiftFoundation_ target. This builds CoreFoundation and Foundation.
0. Run (Cmd-R) the _TestFoundation_ target. This builds CoreFoundation, Foundation, XCTest, and TestFoundation, then runs the tests.
Expand Down
9 changes: 4 additions & 5 deletions Sources/CoreFoundation/CFXMLPreferencesDomain.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,18 +273,17 @@ static Boolean __CFWriteBytesToFileWithAtomicity(CFURLRef url, const void *bytes
close(fd);

if (atomic) {
// If the file was renamed successfully and we wrote it as root we need to reset the owner & group as they were.
if (writingFileAsRoot) {
chown(auxPath, owner, group);
}
// preserve the mode as passed in originally
chmod(auxPath, mode);

if (0 != rename(auxPath, cpath)) {
unlink(auxPath);
return false;
}

// If the file was renamed successfully and we wrote it as root we need to reset the owner & group as they were.
if (writingFileAsRoot) {
chown(cpath, owner, group);
}
}
return true;
}
Expand Down
8 changes: 4 additions & 4 deletions Sources/Foundation/NSLock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ private typealias _RecursiveMutexPointer = UnsafeMutablePointer<pthread_mutex_t>
private typealias _ConditionVariablePointer = UnsafeMutablePointer<pthread_cond_t>
#endif

open class NSLock: NSObject, NSLocking {
open class NSLock: NSObject, NSLocking, @unchecked Sendable {
internal var mutex = _MutexPointer.allocate(capacity: 1)
#if os(macOS) || os(iOS) || os(Windows)
private var timeoutCond = _ConditionVariablePointer.allocate(capacity: 1)
Expand Down Expand Up @@ -165,7 +165,7 @@ extension NSLock {
}

#if SWIFT_CORELIBS_FOUNDATION_HAS_THREADS
open class NSConditionLock : NSObject, NSLocking {
open class NSConditionLock : NSObject, NSLocking, @unchecked Sendable {
internal var _cond = NSCondition()
internal var _value: Int
internal var _thread: _swift_CFThreadRef?
Expand Down Expand Up @@ -259,7 +259,7 @@ open class NSConditionLock : NSObject, NSLocking {
}
#endif

open class NSRecursiveLock: NSObject, NSLocking {
open class NSRecursiveLock: NSObject, NSLocking, @unchecked Sendable {
internal var mutex = _RecursiveMutexPointer.allocate(capacity: 1)
#if os(macOS) || os(iOS) || os(Windows)
private var timeoutCond = _ConditionVariablePointer.allocate(capacity: 1)
Expand Down Expand Up @@ -381,7 +381,7 @@ open class NSRecursiveLock: NSObject, NSLocking {
open var name: String?
}

open class NSCondition: NSObject, NSLocking {
open class NSCondition: NSObject, NSLocking, @unchecked Sendable {
internal var mutex = _MutexPointer.allocate(capacity: 1)
internal var cond = _ConditionVariablePointer.allocate(capacity: 1)

Expand Down
71 changes: 61 additions & 10 deletions Sources/FoundationNetworking/URLSession/libcurl/EasyHandle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -182,17 +182,17 @@ extension _EasyHandle {
_config = config
}

/// Set allowed protocols
/// Set the CA bundle path automatically if it isn't set
///
/// - Note: This has security implications. Not limiting this, someone could
/// redirect a HTTP request into one of the many other protocols that libcurl
/// supports.
/// - SeeAlso: https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html
/// - SeeAlso: https://curl.haxx.se/libcurl/c/CURLOPT_REDIR_PROTOCOLS.html
func setAllowedProtocolsToHTTPAndHTTPS() {
let protocols = (CFURLSessionProtocolHTTP | CFURLSessionProtocolHTTPS)
try! CFURLSession_easy_setopt_long(rawHandle, CFURLSessionOptionPROTOCOLS, protocols).asError()
try! CFURLSession_easy_setopt_long(rawHandle, CFURLSessionOptionREDIR_PROTOCOLS, protocols).asError()
/// Curl does not necessarily know where to find the CA root bundle,
/// and in that case we need to specify where it is. There was a hack
/// to do this automatically for Android but allowing an environment
/// variable to control the location of the CA root bundle seems like
/// a security issue in general.
///
/// Rather than doing that, we have a list of places we might expect
/// to find it, and search those until we locate a suitable file.
func setCARootBundlePath() {
#if os(Android)
// See https://curl.haxx.se/docs/sslcerts.html
// For SSL on Android you need a "cacert.pem" to be
Expand All @@ -205,8 +205,58 @@ extension _EasyHandle {
else {
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionCAINFO, caInfo).asError()
}
return
}
#endif

#if !NS_CURL_MISSING_CURLINFO_CAINFO
#if !os(Windows) && !os(macOS) && !os(iOS) && !os(watchOS) && !os(tvOS)
// Check if there is a default path; if there is, it will already
// be set, so leave things alone
var p: UnsafeMutablePointer<Int8>? = nil

try! CFURLSession_easy_getinfo_charp(rawHandle, CFURLSessionInfoCAINFO, &p).asError()

if p != nil {
return
}

// Otherwise, search a list of known paths
let paths = [
"/etc/ssl/certs/ca-certificates.crt",
"/etc/pki/tls/certs/ca-bundle.crt",
"/usr/share/ssl/certs/ca-bundle.crt",
"/usr/local/share/certs/ca-root-nss.crt",
"/etc/ssl/cert.pem"
]

for path in paths {
var isDirectory: ObjCBool = false
if FileManager.default.fileExists(atPath: path,
isDirectory: &isDirectory)
&& !isDirectory.boolValue {
path.withCString { pathPtr in
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionCAINFO, UnsafeMutablePointer(mutating: pathPtr)).asError()
}
return
}
}
#endif // !os(Windows) && !os(macOS) && !os(iOS) && !os(watchOS) && !os(tvOS)
#endif // !NS_CURL_MISSING_CURLINFO_CAINFO
}

/// Set allowed protocols
///
/// - Note: This has security implications. Not limiting this, someone could
/// redirect a HTTP request into one of the many other protocols that libcurl
/// supports.
/// - SeeAlso: https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html
/// - SeeAlso: https://curl.haxx.se/libcurl/c/CURLOPT_REDIR_PROTOCOLS.html
func setAllowedProtocolsToHTTPAndHTTPS() {
let protocols = (CFURLSessionProtocolHTTP | CFURLSessionProtocolHTTPS)
try! CFURLSession_easy_setopt_long(rawHandle, CFURLSessionOptionPROTOCOLS, protocols).asError()
try! CFURLSession_easy_setopt_long(rawHandle, CFURLSessionOptionREDIR_PROTOCOLS, protocols).asError()
setCARootBundlePath()
//TODO: Added in libcurl 7.45.0
//TODO: Set default protocol for schemeless URLs
//CURLOPT_DEFAULT_PROTOCOL available only in libcurl 7.45.0
Expand All @@ -217,6 +267,7 @@ extension _EasyHandle {
let redirectProtocols = (CFURLSessionProtocolHTTP | CFURLSessionProtocolHTTPS)
try! CFURLSession_easy_setopt_long(rawHandle, CFURLSessionOptionPROTOCOLS, protocols).asError()
try! CFURLSession_easy_setopt_long(rawHandle, CFURLSessionOptionREDIR_PROTOCOLS, redirectProtocols).asError()
setCARootBundlePath()
}

//TODO: Proxy setting, namely CFURLSessionOptionPROXY, CFURLSessionOptionPROXYPORT,
Expand Down
3 changes: 3 additions & 0 deletions Sources/_CFURLSessionInterface/CFURLSessionInterface.c
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,9 @@ CFURLSessionInfo const CFURLSessionInfoFTP_ENTRY_PATH = { CURLINFO_FTP_ENTRY_PAT
CFURLSessionInfo const CFURLSessionInfoREDIRECT_URL = { CURLINFO_REDIRECT_URL };
CFURLSessionInfo const CFURLSessionInfoPRIMARY_IP = { CURLINFO_PRIMARY_IP };
CFURLSessionInfo const CFURLSessionInfoAPPCONNECT_TIME = { CURLINFO_APPCONNECT_TIME };
#if !NS_CURL_MISSING_CURLINFO_CAINFO
CFURLSessionInfo const CFURLSessionInfoCAINFO = { CURLINFO_CAINFO };
#endif
CFURLSessionInfo const CFURLSessionInfoCERTINFO = { CURLINFO_CERTINFO };
CFURLSessionInfo const CFURLSessionInfoCONDITION_UNMET = { CURLINFO_CONDITION_UNMET };
CFURLSessionInfo const CFURLSessionInfoRTSP_SESSION_ID = { CURLINFO_RTSP_SESSION_ID };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@ CF_EXPORT CFURLSessionInfo const CFURLSessionInfoFTP_ENTRY_PATH; // CURLINFO_FTP
CF_EXPORT CFURLSessionInfo const CFURLSessionInfoREDIRECT_URL; // CURLINFO_REDIRECT_URL
CF_EXPORT CFURLSessionInfo const CFURLSessionInfoPRIMARY_IP; // CURLINFO_PRIMARY_IP
CF_EXPORT CFURLSessionInfo const CFURLSessionInfoAPPCONNECT_TIME; // CURLINFO_APPCONNECT_TIME
CF_EXPORT CFURLSessionInfo const CFURLSessionInfoCAINFO; // CURLINFO_CAINFO
CF_EXPORT CFURLSessionInfo const CFURLSessionInfoCERTINFO; // CURLINFO_CERTINFO
CF_EXPORT CFURLSessionInfo const CFURLSessionInfoCONDITION_UNMET; // CURLINFO_CONDITION_UNMET
CF_EXPORT CFURLSessionInfo const CFURLSessionInfoRTSP_SESSION_ID; // CURLINFO_RTSP_SESSION_ID
Expand Down