From 608fff33688154e3f2e9409d3215cb28fc39b81f Mon Sep 17 00:00:00 2001 From: Finagolfin Date: Fri, 1 Dec 2023 19:19:40 +0530 Subject: [PATCH] Android: add better nullability checks for nullability annotations added in NDK 26 --- Sources/Foundation/FileHandle.swift | 7 ++++- Sources/Foundation/FileManager+POSIX.swift | 34 +++++++++++++++------ Sources/Foundation/FileManager.swift | 8 ++--- Sources/Foundation/Host.swift | 3 +- Tests/Foundation/Tests/TestFileHandle.swift | 2 +- Tests/Foundation/Tests/TestTimeZone.swift | 2 +- 6 files changed, 38 insertions(+), 18 deletions(-) diff --git a/Sources/Foundation/FileHandle.swift b/Sources/Foundation/FileHandle.swift index a538a2975e..f5db4ce298 100644 --- a/Sources/Foundation/FileHandle.swift +++ b/Sources/Foundation/FileHandle.swift @@ -307,10 +307,15 @@ open class FileHandle : NSObject { if options.contains(.alwaysMapped) { // Filesizes are often 64bit even on 32bit systems let mapSize = min(length, Int(clamping: statbuf.st_size)) + #if os(Android) + // Bionic mmap() now returns _Nonnull, so the force unwrap below isn't needed. let data = mmap(nil, mapSize, PROT_READ, MAP_PRIVATE, _fd, 0) + #else + let data = mmap(nil, mapSize, PROT_READ, MAP_PRIVATE, _fd, 0)! + #endif // Swift does not currently expose MAP_FAILURE if data != UnsafeMutableRawPointer(bitPattern: -1) { - return NSData.NSDataReadResult(bytes: data!, length: mapSize) { buffer, length in + return NSData.NSDataReadResult(bytes: data, length: mapSize) { buffer, length in munmap(buffer, length) } } diff --git a/Sources/Foundation/FileManager+POSIX.swift b/Sources/Foundation/FileManager+POSIX.swift index d90ece91e6..d2bbd22bfc 100644 --- a/Sources/Foundation/FileManager+POSIX.swift +++ b/Sources/Foundation/FileManager+POSIX.swift @@ -741,20 +741,26 @@ extension FileManager { if rmdir(fsRep) == 0 { return } else if errno == ENOTEMPTY { + #if os(Android) + let ps = UnsafeMutablePointer>.allocate(capacity: 2) + ps.initialize(to: UnsafeMutablePointer(mutating: fsRep)) + ps.advanced(by: 1).initialize(to: unsafeBitCast(0, to: UnsafeMutablePointer.self)) + #else let ps = UnsafeMutablePointer?>.allocate(capacity: 2) ps.initialize(to: UnsafeMutablePointer(mutating: fsRep)) ps.advanced(by: 1).initialize(to: nil) + #endif let stream = fts_open(ps, FTS_PHYSICAL | FTS_XDEV | FTS_NOCHDIR | FTS_NOSTAT, nil) ps.deinitialize(count: 2) ps.deallocate() - if stream != nil { + if let openStream = stream { defer { - fts_close(stream) + fts_close(openStream) } - while let current = fts_read(stream)?.pointee { - let itemPath = string(withFileSystemRepresentation: current.fts_path, length: Int(current.fts_pathlen)) + while let current = fts_read(openStream)?.pointee, let current_path = current.fts_path { + let itemPath = string(withFileSystemRepresentation: current_path, length: Int(current.fts_pathlen)) guard alreadyConfirmed || shouldRemoveItemAtPath(itemPath, isURL: isURL) else { continue } @@ -762,11 +768,11 @@ extension FileManager { do { switch Int32(current.fts_info) { case FTS_DEFAULT, FTS_F, FTS_NSOK, FTS_SL, FTS_SLNONE: - if unlink(current.fts_path) == -1 { + if unlink(current_path) == -1 { throw _NSErrorWithErrno(errno, reading: false, path: itemPath) } case FTS_DP: - if rmdir(current.fts_path) == -1 { + if rmdir(current_path) == -1 { throw _NSErrorWithErrno(errno, reading: false, path: itemPath) } case FTS_DNR, FTS_ERR, FTS_NS: @@ -1085,10 +1091,18 @@ extension FileManager { do { guard fm.fileExists(atPath: _url.path) else { throw _NSErrorWithErrno(ENOENT, reading: true, url: url) } _stream = try FileManager.default._fileSystemRepresentation(withPath: _url.path) { fsRep in + #if os(Android) + let ps = UnsafeMutablePointer>.allocate(capacity: 2) + #else let ps = UnsafeMutablePointer?>.allocate(capacity: 2) + #endif defer { ps.deallocate() } ps.initialize(to: UnsafeMutablePointer(mutating: fsRep)) + #if os(Android) + ps.advanced(by: 1).initialize(to: unsafeBitCast(0, to: UnsafeMutablePointer.self)) + #else ps.advanced(by: 1).initialize(to: nil) + #endif return fts_open(ps, FTS_PHYSICAL | FTS_XDEV | FTS_NOCHDIR | FTS_NOSTAT, nil) } if _stream == nil { @@ -1135,14 +1149,14 @@ extension FileManager { } _current = fts_read(stream) - while let current = _current { - let filename = FileManager.default.string(withFileSystemRepresentation: current.pointee.fts_path, length: Int(current.pointee.fts_pathlen)) + while let current = _current, let current_path = current.pointee.fts_path { + let filename = FileManager.default.string(withFileSystemRepresentation: current_path, length: Int(current.pointee.fts_pathlen)) switch Int32(current.pointee.fts_info) { case FTS_D: let (showFile, skipDescendants) = match(filename: filename, to: _options, isDir: true) if skipDescendants { - fts_set(_stream, _current, FTS_SKIP) + fts_set(stream, current, FTS_SKIP) } if showFile { return URL(fileURLWithPath: filename, isDirectory: true) @@ -1315,7 +1329,7 @@ extension FileManager { let finalErrno = originalItemURL.withUnsafeFileSystemRepresentation { (originalFS) -> Int32? in return newItemURL.withUnsafeFileSystemRepresentation { (newItemFS) -> Int32? in // This is an atomic operation in many OSes, but is not guaranteed to be atomic by the standard. - if rename(newItemFS, originalFS) == 0 { + if let newFS = newItemFS, let origFS = originalFS, rename(newFS, origFS) == 0 { return nil } else { return errno diff --git a/Sources/Foundation/FileManager.swift b/Sources/Foundation/FileManager.swift index 1aa3038a01..9fdb495c3e 100644 --- a/Sources/Foundation/FileManager.swift +++ b/Sources/Foundation/FileManager.swift @@ -568,13 +568,13 @@ open class FileManager : NSObject { let attributes = try windowsFileAttributes(atPath: path) let type = FileAttributeType(attributes: attributes, atPath: path) #else - if let pwd = getpwuid(s.st_uid), pwd.pointee.pw_name != nil { - let name = String(cString: pwd.pointee.pw_name) + if let pwd = getpwuid(s.st_uid), let pwd_name = pwd.pointee.pw_name { + let name = String(cString: pwd_name) result[.ownerAccountName] = name } - if let grd = getgrgid(s.st_gid), grd.pointee.gr_name != nil { - let name = String(cString: grd.pointee.gr_name) + if let grd = getgrgid(s.st_gid), let grd_name = grd.pointee.gr_name { + let name = String(cString: grd_name) result[.groupOwnerAccountName] = name } diff --git a/Sources/Foundation/Host.swift b/Sources/Foundation/Host.swift index 5fe7b29c5b..ce571abe78 100644 --- a/Sources/Foundation/Host.swift +++ b/Sources/Foundation/Host.swift @@ -25,7 +25,8 @@ import WinSDK // getnameinfo uses size_t for its 4th and 6th arguments. private func getnameinfo(_ addr: UnsafePointer?, _ addrlen: socklen_t, _ host: UnsafeMutablePointer?, _ hostlen: socklen_t, _ serv: UnsafeMutablePointer?, _ servlen: socklen_t, _ flags: Int32) -> Int32 { - return Glibc.getnameinfo(addr, addrlen, host, Int(hostlen), serv, Int(servlen), flags) + guard let saddr = addr else { return -1 } + return Glibc.getnameinfo(saddr, addrlen, host, Int(hostlen), serv, Int(servlen), flags) } // getifaddrs and freeifaddrs are not available in Android 6.0 or earlier, so call these functions dynamically. diff --git a/Tests/Foundation/Tests/TestFileHandle.swift b/Tests/Foundation/Tests/TestFileHandle.swift index 5416c41c4e..91e1bdc0ac 100644 --- a/Tests/Foundation/Tests/TestFileHandle.swift +++ b/Tests/Foundation/Tests/TestFileHandle.swift @@ -111,7 +111,7 @@ class TestFileHandle : XCTestCase { #else var fds: [Int32] = [-1, -1] fds.withUnsafeMutableBufferPointer { (pointer) -> Void in - pipe(pointer.baseAddress) + pipe(pointer.baseAddress!) } close(fds[1]) diff --git a/Tests/Foundation/Tests/TestTimeZone.swift b/Tests/Foundation/Tests/TestTimeZone.swift index 5e15c00026..373e21b263 100644 --- a/Tests/Foundation/Tests/TestTimeZone.swift +++ b/Tests/Foundation/Tests/TestTimeZone.swift @@ -160,7 +160,7 @@ class TestTimeZone: XCTestCase { var lt = tm() localtime_r(&t, <) let zoneName = NSTimeZone.system.abbreviation() ?? "Invalid Abbreviation" - let expectedName = String(cString: lt.tm_zone, encoding: .ascii) ?? "Invalid Zone" + let expectedName = String(cString: lt.tm_zone!, encoding: .ascii) ?? "Invalid Zone" XCTAssertEqual(zoneName, expectedName, "expected name \"\(expectedName)\" is not equal to \"\(zoneName)\"") } #endif