Swift: Add heuristic path injection sinks.

This commit is contained in:
Geoffrey White
2023-11-09 17:16:04 +00:00
parent ebf7231be7
commit 5a09a325f2
2 changed files with 41 additions and 6 deletions

View File

@@ -61,6 +61,41 @@ private class EnumConstructorPathInjectionSink extends PathInjectionSink {
}
}
/**
* A string that might be a label for a path argument.
*/
pragma[inline]
private predicate pathLikeHeuristic(string label) {
label =
[
"atFile", "atPath", "atDirectory", "toFile", "toPath", "toDirectory", "inFile", "inPath",
"inDirectory", "contentsOfFile", "contentsOfPath", "contentsOfDirectory", "filePath",
"directory", "directoryPath"
]
}
/**
* A path injection sink that is determined by imprecise methods.
*/
private class HeuristicPathInjectionSink extends PathInjectionSink {
HeuristicPathInjectionSink() {
// by parameter name
exists(CallExpr ce, int ix, ParamDecl pd |
pathLikeHeuristic(pragma[only_bind_into](pd.getName())) and
pd.getType().getUnderlyingType().getName() = ["String", "NSString"] and
pd = ce.getStaticTarget().getParam(ix) and
this.asExpr() = ce.getArgument(ix).getExpr()
)
or
// by argument name
exists(Argument a |
pathLikeHeuristic(pragma[only_bind_into](a.getLabel())) and
a.getExpr().getType().getUnderlyingType().getName() = ["String", "NSString"] and
this.asExpr() = a.getExpr()
)
}
}
private class DefaultPathInjectionBarrier extends PathInjectionBarrier {
DefaultPathInjectionBarrier() {
// This is a simplified implementation.

View File

@@ -452,7 +452,7 @@ func testPathInjection2(s1: UnsafeMutablePointer<String>, s2: UnsafeMutablePoint
u1.appendPathComponent(remoteString)
_ = NSData(contentsOf: u1) // $ hasPathInjection=445
let u2 = URL(filePath: remoteString)
let u2 = URL(filePath: remoteString) // $ hasPathInjection=445
_ = NSData(contentsOf: u2) // $ hasPathInjection=445
let u3 = NSURL(string: "")!
@@ -504,13 +504,13 @@ class MyFile {
func testPathInjectionHeuristics() {
let remoteString = String(contentsOf: URL(string: "http://example.com/")!)
myOpenFile1(atPath: remoteString) // $ MISSING: hasPathInjection=
myOpenFile2(remoteString) // $ MISSING: hasPathInjection=
myFindFiles(ofType: 0, inDirectory: remoteString) // $ MISSING: hasPathInjection=
myOpenFile1(atPath: remoteString) // $ hasPathInjection=505
myOpenFile2(remoteString) // $ hasPathInjection=505
myFindFiles(ofType: 0, inDirectory: remoteString) // $ hasPathInjection=505
let mc = MyClass(contentsOfFile: remoteString) // $ MISSING: hasPathInjection=
let mc = MyClass(contentsOfFile: remoteString) // $ hasPathInjection=505
mc.doSomething(keyPath: remoteString) // good - not a path
mc.write(toFile: remoteString) // $ MISSING: hasPathInjection=
mc.write(toFile: remoteString) // $ hasPathInjection=505
let mf1 = MyFile(path: "")
let mf2 = MyFile(path: remoteString) // $ MISSING: hasPathInjection=