Swift: Additional test cases.

This commit is contained in:
Geoffrey White
2023-10-11 09:22:29 +01:00
parent c587dbb72a
commit 0e4cd7f52f
3 changed files with 165 additions and 59 deletions

View File

@@ -3,9 +3,7 @@
*/
import swift
import FlowConfig
import TestFlow::PathGraph
from TestFlow::PathNode src, TestFlow::PathNode sink
where TestFlow::flowPath(src, sink)
select sink, src, sink, "result"
from Function f
where f.getName().matches("os_log%")
select f, concat(f.getInterfaceType().toString(), ", ")

View File

@@ -1,2 +1,2 @@
failures
testFailures
failures

View File

@@ -1,5 +1,7 @@
// --- stubs ---
class NSObject { }
func NSLog(_ format: String, _ args: CVarArg...) {}
func NSLogv(_ format: String, _ args: CVaListPointer) {}
func getVaList(_ args: [CVarArg]) -> CVaListPointer { return CVaListPointer(_fromUnsafeMutablePointer: UnsafeMutablePointer(bitPattern: 0)!) }
@@ -78,63 +80,88 @@ struct Logger {
func warning(_: OSLogMessage) {}
func fault(_: OSLogMessage) {}
func critical(_: OSLogMessage) {}
}
class OSLog : NSObject {
static let `default` = OSLog(rawValue: 0)
let rawValue: UInt8
init(rawValue: UInt8) { self.rawValue = rawValue}
}
extension String : CVarArg {
public var _cVarArgEncoding: [Int] { get { return [] } }
}
// from ObjC API; slightly simplified.
func os_log(_ message: StaticString,
dso: UnsafeRawPointer? = nil,
log: OSLog = .default,
type: OSLogType = .default,
_ args: CVarArg...) { }
// --- tests ---
func test1(password: String, passwordHash : String, passphrase: String, pass_phrase: String) {
print(password) // $ hasCleartextLogging=87
print(password, separator: "") // $ $ hasCleartextLogging=88
print("", separator: password) // $ hasCleartextLogging=89
print(password, separator: "", terminator: "") // $ hasCleartextLogging=90
print("", separator: password, terminator: "") // $ hasCleartextLogging=91
print("", separator: "", terminator: password) // $ hasCleartextLogging=92
print(passwordHash) // Safe
print(password) // $ hasCleartextLogging=105
print(password, separator: "") // $ $ hasCleartextLogging=106
print("", separator: password) // $ hasCleartextLogging=107
print(password, separator: "", terminator: "") // $ hasCleartextLogging=108
print("", separator: password, terminator: "") // $ hasCleartextLogging=109
print("", separator: "", terminator: password) // $ hasCleartextLogging=110
print(passwordHash) // safe
NSLog(password) // $ hasCleartextLogging=95
NSLog("%@", password as! CVarArg) // $ hasCleartextLogging=96
NSLog("%@ %@", "" as! CVarArg, password as! CVarArg) // $ hasCleartextLogging=97
NSLog("\(password)") // $ hasCleartextLogging=98
NSLogv("%@", getVaList([password as! CVarArg])) // $ hasCleartextLogging=99
NSLogv("%@ %@", getVaList(["" as! CVarArg, password as! CVarArg])) // $ hasCleartextLogging=100
NSLog(passwordHash) // SAfe
NSLogv("%@", getVaList([passwordHash as! CVarArg])) // Safe
debugPrint(password) // $ hasCleartextLogging=113
dump(password) // $ hasCleartextLogging=115
NSLog(password) // $ hasCleartextLogging=117
NSLog("%@", password) // $ hasCleartextLogging=118
NSLog("%@ %@", "", password) // $ hasCleartextLogging=119
NSLog("\(password)") // $ hasCleartextLogging=120
NSLogv("%@", getVaList([password])) // $ hasCleartextLogging=121
NSLogv("%@ %@", getVaList(["", password])) // $ hasCleartextLogging=122
NSLog(passwordHash) // safe
NSLogv("%@", getVaList([passwordHash])) // safe
let bankAccount: Int = 0
let log = Logger()
// These MISSING test cases will be fixed when we properly generate the CFG around autoclosures.
log.log("\(password)") // Safe
log.log("\(password, privacy: .auto)") // Safe
log.log("\(password, privacy: .private)") // Safe
log.log("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=110
log.log("\(passwordHash, privacy: .public)") // Safe
log.log("\(password, privacy: .sensitive)") // Safe
log.log("\(bankAccount)") // $ MISSING: hasCleartextLogging=113
log.log("\(bankAccount, privacy: .auto)") // $ MISSING: hasCleartextLogging=114
log.log("\(bankAccount, privacy: .private)") // Safe
log.log("\(bankAccount, privacy: .public)") // $ MISSING: hasCleartextLogging=116
log.log("\(bankAccount, privacy: .sensitive)") // Safe
log.log(level: .default, "\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=118
log.trace("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=119
log.trace("\(passwordHash, privacy: .public)") // Safe
log.debug("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=121
log.debug("\(passwordHash, privacy: .public)") // Safe
log.info("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=123
log.info("\(passwordHash, privacy: .public)") // Safe
log.notice("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=125
log.notice("\(passwordHash, privacy: .public)") // Safe
log.warning("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=127
log.warning("\(passwordHash, privacy: .public)") // Safe
log.error("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=129
log.error("\(passwordHash, privacy: .public)") // Safe
log.critical("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=131
log.critical("\(passwordHash, privacy: .public)") // Safe
log.fault("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=133
log.fault("\(passwordHash, privacy: .public)") // Safe
log.log("\(password)") // safe
log.log("\(password, privacy: .auto)") // safe
log.log("\(password, privacy: .private)") // safe
log.log("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=132
log.log("\(passwordHash, privacy: .public)") // safe
log.log("\(password, privacy: .sensitive)") // safe
log.log("\(bankAccount)") // $ MISSING: hasCleartextLogging=135
log.log("\(bankAccount, privacy: .auto)") // $ MISSING: hasCleartextLogging=136
log.log("\(bankAccount, privacy: .private)") // safe
log.log("\(bankAccount, privacy: .public)") // $ MISSING: hasCleartextLogging=138
log.log("\(bankAccount, privacy: .sensitive)") // safe
log.log(level: .default, "\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=140
log.trace("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=141
log.trace("\(passwordHash, privacy: .public)") // safe
log.debug("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=143
log.debug("\(passwordHash, privacy: .public)") // safe
log.info("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=145
log.info("\(passwordHash, privacy: .public)") // safe
log.notice("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=147
log.notice("\(passwordHash, privacy: .public)") // safe
log.warning("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=149
log.warning("\(passwordHash, privacy: .public)") // safe
log.error("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=151
log.error("\(passwordHash, privacy: .public)") // safe
log.critical("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=153
log.critical("\(passwordHash, privacy: .public)") // safe
log.fault("\(password, privacy: .public)") // $ MISSING: hasCleartextLogging=155
log.fault("\(passwordHash, privacy: .public)") // safe
NSLog(passphrase) // $ hasCleartextLogging=158
NSLog(pass_phrase) // $ hasCleartextLogging=159
os_log("%@", log: .default, type: .default, "") // safe
os_log("%@", log: .default, type: .default, password) // $ MISSING: hasCleartextLogging=161
os_log("%@ %@ %@", log: .default, type: .default, "", "", password) // $ MISSING: hasCleartextLogging=162
NSLog(passphrase) // $ hasCleartextLogging=136
NSLog(pass_phrase) // $ hasCleartextLogging=137
}
class MyClass {
@@ -148,16 +175,16 @@ func doSomething(password: String) { }
func test3(x: String) {
// alternative evidence of sensitivity...
NSLog(x) // $ MISSING: hasCleartextLogging=152
NSLog(x) // $ MISSING: hasCleartextLogging=179
doSomething(password: x);
NSLog(x) // $ hasCleartextLogging=152
NSLog(x) // $ hasCleartextLogging=179
let y = getPassword();
NSLog(y) // $ hasCleartextLogging=155
NSLog(y) // $ hasCleartextLogging=182
let z = MyClass()
NSLog(z.harmless) // Safe
NSLog(z.password) // $ hasCleartextLogging=160
NSLog(z.harmless) // safe
NSLog(z.password) // $ hasCleartextLogging=187
}
struct MyOuter {
@@ -170,6 +197,87 @@ struct MyOuter {
}
func test3(mo : MyOuter) {
NSLog(mo.password.value) // $ hasCleartextLogging=173
NSLog(mo.harmless.value) // Safe
// struct members...
NSLog(mo.password.value) // $ hasCleartextLogging=202
NSLog(mo.harmless.value) // safe
}
func test4(harmless: String, password: String) {
// functions with an `in:` target for the write...
var myString1 = ""
var myString2 = ""
var myString3 = ""
var myString4 = ""
var myString5 = ""
var myString6 = ""
var myString7 = ""
var myString8 = ""
var myString9 = ""
var myString10 = ""
var myString11 = ""
var myString12 = ""
var myString13 = ""
print(harmless, to: &myString1)
print(myString1) // safe
print(password, to: &myString2) // $ SPURIOUS: hasCleartextLogging=225
print(myString2) // $ MISSING: hasCleartextLogging=225
print("log: " + password, to: &myString3) // $ SPURIOUS: hasCleartextLogging=228
print(myString3) // $ MISSING: hasCleartextLogging=228
debugPrint(harmless, to: &myString4)
debugPrint(myString4) // safe
debugPrint(password, to: &myString5) // $ SPURIOUS: hasCleartextLogging=234
debugPrint(myString5) // $ MISSING: hasCleartextLogging=234
dump(harmless, to: &myString6)
dump(myString6) // safe
dump(password, to: &myString7) // $ SPURIOUS: hasCleartextLogging=240
dump(myString7) // $ MISSING: hasCleartextLogging=240
myString8.write(harmless)
print(myString8)
myString9.write(password)
print(myString9) // $ hasCleartextLogging=246
myString10.write(harmless)
myString10.write(password)
myString10.write(harmless)
print(myString10) // $ hasCleartextLogging=250
harmless.write(to: &myString11)
print(myString11)
password.write(to: &myString12)
print(myString12) // $ hasCleartextLogging=257
print(password, to: &myString13) // $ SPURIOUS: hasCleartextLogging=260
debugPrint(password, to: &myString13) // $ SPURIOUS: hasCleartextLogging=261
dump(password, to: &myString13) // $ SPURIOUS: hasCleartextLogging=262
myString13.write(password) // safe - only printed to another string
password.write(to: &myString13) // safe - only printed to another string
}
func test5(password: String, caseNum: Int) {
// `assert` methods...
// (these would only be a danger in certain builds)
switch caseNum {
case 0:
assert(false, password) // $ MISSING: hasCleartextLogging=273
case 1:
assertionFailure(password) // $ MISSING: hasCleartextLogging=275
case 2:
precondition(false, password) // $ MISSING: hasCleartextLogging=277
case 3:
preconditionFailure(password) // $ MISSING: hasCleartextLogging=279
default:
fatalError(password) // $ MISSING: hasCleartextLogging=281
}
}