|
1 | 1 | // --- stubs ---
|
2 | 2 |
|
| 3 | +class NSObject { |
| 4 | +} |
| 5 | + |
3 | 6 | class Data {
|
4 | 7 | init<S>(_ elements: S) {}
|
5 |
| - func copyBytes(to: UnsafeMutablePointer<UInt8>, count: Int) {} |
6 | 8 | }
|
7 | 9 |
|
8 | 10 | struct URL {
|
9 | 11 | init?(string: String) {}
|
| 12 | + |
| 13 | + func appendingPathComponent(_ pathComponent: String) -> URL { return self } |
| 14 | +} |
| 15 | + |
| 16 | +class FileManager : NSObject { |
| 17 | + class var `default`: FileManager { get { return FileManager() } } |
| 18 | + |
| 19 | + var homeDirectoryForCurrentUser: URL { get { return URL(string: "")! } } |
| 20 | +} |
| 21 | + |
| 22 | +class Bundle : NSObject { |
| 23 | + class var main: Bundle { get { return Bundle() } } |
| 24 | + |
| 25 | + func path(forResource name: String?, ofType ext: String?) -> String? { return "" } |
10 | 26 | }
|
11 | 27 |
|
12 |
| -extension String { |
13 |
| - init(contentsOf: URL) { |
14 |
| - let data = "" |
15 |
| - self.init(data) |
| 28 | +struct FilePath { |
| 29 | + init?(_ url: URL) { } |
| 30 | + init(_ string: String) { } |
| 31 | +} |
| 32 | + |
| 33 | +struct FileDescriptor { |
| 34 | + let rawValue: CInt |
| 35 | + |
| 36 | + struct AccessMode : RawRepresentable { |
| 37 | + var rawValue: CInt |
| 38 | + |
| 39 | + static let readOnly = AccessMode(rawValue: 0) |
| 40 | + } |
| 41 | + |
| 42 | + static func open( |
| 43 | + _ path: FilePath, |
| 44 | + _ mode: FileDescriptor.AccessMode, |
| 45 | + options: Int? = nil, |
| 46 | + permissions: Int? = nil, |
| 47 | + retryOnInterrupt: Bool = true |
| 48 | + ) throws -> FileDescriptor { |
| 49 | + return FileDescriptor(rawValue: 0) |
16 | 50 | }
|
17 | 51 | }
|
18 | 52 |
|
@@ -46,53 +80,93 @@ func xmlParseInNodeContext(_ node: xmlNodePtr!, _ data: UnsafePointer<CChar>!, _
|
46 | 80 | func xmlCtxtReadMemory(_ ctxt: xmlParserCtxtPtr!, _ buffer: UnsafePointer<CChar>!, _ size: Int32, _ URL: UnsafePointer<CChar>!, _ encoding: UnsafePointer<CChar>!, _ options: Int32) -> xmlDocPtr! { return xmlDocPtr.allocate(capacity: 0) }
|
47 | 81 | func xmlCtxtReadFd(_ ctxt: xmlParserCtxtPtr!, _ fd: Int32, _ URL: UnsafePointer<CChar>!, _ encoding: UnsafePointer<CChar>!, _ options: Int32) -> xmlDocPtr! { return xmlDocPtr.allocate(capacity: 0) }
|
48 | 82 | func xmlCtxtReadIO(_ ctxt: xmlParserCtxtPtr!, _ ioread: xmlInputReadCallback!, _ ioclose: xmlInputCloseCallback!, _ ioctx: UnsafeMutableRawPointer!, _ URL: UnsafePointer<CChar>!, _ encoding: UnsafePointer<CChar>!, _ options: Int32) -> xmlDocPtr! { return xmlDocPtr.allocate(capacity: 0) }
|
| 83 | +func xmlParseChunk(_ ctxt: xmlParserCtxtPtr!, _ chunk: UnsafePointer<CChar>?, _ size: Int32, _ terminate: Int32) -> Int32 { return 0 } |
49 | 84 |
|
50 | 85 | // --- tests ---
|
51 | 86 |
|
52 | 87 | func sourcePtr() -> UnsafeMutablePointer<UInt8> { return UnsafeMutablePointer<UInt8>.allocate(capacity: 0) }
|
53 | 88 | func sourceCharPtr() -> UnsafeMutablePointer<CChar> { return UnsafeMutablePointer<CChar>.allocate(capacity: 0) }
|
54 | 89 |
|
| 90 | +func getACtxt() -> xmlParserCtxtPtr { |
| 91 | + return 0 as! xmlParserCtxtPtr |
| 92 | +} |
| 93 | + |
55 | 94 | func test() {
|
56 | 95 | let remotePtr = sourcePtr()
|
57 | 96 | let remoteCharPtr = sourceCharPtr()
|
| 97 | + let safeCharPtr = UnsafeMutablePointer<CChar>.allocate(capacity: 1024) |
| 98 | + safeCharPtr.initialize(repeating: 0, count: 1024) |
| 99 | + |
58 | 100 | let _ = xmlReadFile(remoteCharPtr, nil, 0) // NO XXE: external entities not enabled
|
59 |
| - let _ = xmlReadFile(remoteCharPtr, nil, Int32(XML_PARSE_NOENT.rawValue)) // $ hasXXE=57 |
60 |
| - let _ = xmlReadFile(remoteCharPtr, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) // $ hasXXE=57 |
61 |
| - let _ = xmlReadFile(remoteCharPtr, nil, Int32(XML_PARSE_NOENT.rawValue | XML_PARSE_DTDLOAD.rawValue)) // $ hasXXE=57 |
62 |
| - let _ = xmlReadFile(remoteCharPtr, nil, Int32(XML_PARSE_NOENT.rawValue | 0)) // $ hasXXE=57 |
| 101 | + let _ = xmlReadFile(remoteCharPtr, nil, Int32(XML_PARSE_NOENT.rawValue)) // $ hasXXE=96 |
| 102 | + let _ = xmlReadFile(remoteCharPtr, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) // $ hasXXE=96 |
| 103 | + let _ = xmlReadFile(remoteCharPtr, nil, Int32(XML_PARSE_NOENT.rawValue | XML_PARSE_DTDLOAD.rawValue)) // $ hasXXE=96 |
| 104 | + let _ = xmlReadFile(remoteCharPtr, nil, Int32(XML_PARSE_NOENT.rawValue | 0)) // $ hasXXE=96 |
63 | 105 | let _ = xmlReadDoc(remotePtr, nil, nil, 0) // NO XXE: external entities not enabled
|
64 |
| - let _ = xmlReadDoc(remotePtr, nil, nil, Int32(XML_PARSE_NOENT.rawValue)) // $ hasXXE=56 |
65 |
| - let _ = xmlReadDoc(remotePtr, nil, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) // $ hasXXE=56 |
| 106 | + let _ = xmlReadDoc(remotePtr, nil, nil, Int32(XML_PARSE_NOENT.rawValue)) // $ hasXXE=95 |
| 107 | + let _ = xmlReadDoc(remotePtr, nil, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) // $ hasXXE=95 |
66 | 108 | let _ = xmlCtxtReadFile(nil, remoteCharPtr, nil, 0) // NO XXE: external entities not enabled
|
67 |
| - let _ = xmlCtxtReadFile(nil, remoteCharPtr, nil, Int32(XML_PARSE_NOENT.rawValue)) // $ hasXXE=57 |
68 |
| - let _ = xmlCtxtReadFile(nil, remoteCharPtr, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) // $ hasXXE=57 |
| 109 | + let _ = xmlCtxtReadFile(nil, remoteCharPtr, nil, Int32(XML_PARSE_NOENT.rawValue)) // $ hasXXE=96 |
| 110 | + let _ = xmlCtxtReadFile(nil, remoteCharPtr, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) // $ hasXXE=96 |
69 | 111 | let _ = xmlParseInNodeContext(nil, remoteCharPtr, -1, 0, nil) // NO XXE: external entities not enabled
|
70 |
| - let _ = xmlParseInNodeContext(nil, remoteCharPtr, -1, Int32(XML_PARSE_DTDLOAD.rawValue), nil) // $ hasXXE=57 |
71 |
| - let _ = xmlParseInNodeContext(nil, remoteCharPtr, -1, Int32(XML_PARSE_NOENT.rawValue), nil) // $ hasXXE=57 |
| 112 | + let _ = xmlParseInNodeContext(nil, remoteCharPtr, -1, Int32(XML_PARSE_DTDLOAD.rawValue), nil) // $ hasXXE=96 |
| 113 | + let _ = xmlParseInNodeContext(nil, remoteCharPtr, -1, Int32(XML_PARSE_NOENT.rawValue), nil) // $ hasXXE=96 |
72 | 114 | let _ = xmlCtxtReadDoc(nil, remotePtr, nil, nil, 0) // NO XXE: external entities not enabled
|
73 |
| - let _ = xmlCtxtReadDoc(nil, remotePtr, nil, nil, Int32(XML_PARSE_NOENT.rawValue)) // $ hasXXE=56 |
74 |
| - let _ = xmlCtxtReadDoc(nil, remotePtr, nil, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) // $ hasXXE=56 |
| 115 | + let _ = xmlCtxtReadDoc(nil, remotePtr, nil, nil, Int32(XML_PARSE_NOENT.rawValue)) // $ hasXXE=95 |
| 116 | + let _ = xmlCtxtReadDoc(nil, remotePtr, nil, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) // $ hasXXE=95 |
75 | 117 | let _ = xmlReadMemory(remoteCharPtr, -1, nil, nil, 0) // NO XXE: external entities not enabled
|
76 |
| - let _ = xmlReadMemory(remoteCharPtr, -1, nil, nil, Int32(XML_PARSE_NOENT.rawValue)) // $ hasXXE=57 |
77 |
| - let _ = xmlReadMemory(remoteCharPtr, -1, nil, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) // $ hasXXE=57 |
| 118 | + let _ = xmlReadMemory(remoteCharPtr, -1, nil, nil, Int32(XML_PARSE_NOENT.rawValue)) // $ hasXXE=96 |
| 119 | + let _ = xmlReadMemory(remoteCharPtr, -1, nil, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) // $ hasXXE=96 |
78 | 120 | let _ = xmlCtxtReadMemory(nil, remoteCharPtr, -1, nil, nil, 0) // NO XXE: external entities not enabled
|
79 |
| - let _ = xmlCtxtReadMemory(nil, remoteCharPtr, -1, nil, nil, Int32(XML_PARSE_NOENT.rawValue)) // $ hasXXE=57 |
80 |
| - let _ = xmlCtxtReadMemory(nil, remoteCharPtr, -1, nil, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) // $ hasXXE=57 |
81 |
| - // TODO: We would need to model taint around `xmlParserCtxtPtr`, file descriptors, and `xmlInputReadCallback` |
82 |
| - // to be able to alert on these methods. Not doing it for now because of the effort required vs the expected gain. |
83 |
| - let _ = xmlCtxtUseOptions(nil, 0) |
84 |
| - let _ = xmlCtxtUseOptions(nil, Int32(XML_PARSE_NOENT.rawValue)) |
85 |
| - let _ = xmlCtxtUseOptions(nil, Int32(XML_PARSE_DTDLOAD.rawValue)) |
86 |
| - let _ = xmlReadFd(0, nil, nil, 0) |
87 |
| - let _ = xmlReadFd(0, nil, nil, Int32(XML_PARSE_NOENT.rawValue)) |
88 |
| - let _ = xmlReadFd(0, nil, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) |
89 |
| - let _ = xmlCtxtReadFd(nil, 0, nil, nil, 0) |
90 |
| - let _ = xmlCtxtReadFd(nil, 0, nil, nil, Int32(XML_PARSE_NOENT.rawValue)) |
91 |
| - let _ = xmlCtxtReadFd(nil, 0, nil, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) |
92 |
| - let _ = xmlReadIO(nil, nil, nil, nil, nil, 0) |
93 |
| - let _ = xmlReadIO(nil, nil, nil, nil, nil, Int32(XML_PARSE_NOENT.rawValue)) |
94 |
| - let _ = xmlReadIO(nil, nil, nil, nil, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) |
95 |
| - let _ = xmlCtxtReadIO(nil, nil, nil, nil, nil, nil, 0) |
96 |
| - let _ = xmlCtxtReadIO(nil, nil, nil, nil, nil, nil, Int32(XML_PARSE_NOENT.rawValue)) |
97 |
| - let _ = xmlCtxtReadIO(nil, nil, nil, nil, nil, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) |
| 121 | + let _ = xmlCtxtReadMemory(nil, remoteCharPtr, -1, nil, nil, Int32(XML_PARSE_NOENT.rawValue)) // $ hasXXE=96 |
| 122 | + let _ = xmlCtxtReadMemory(nil, remoteCharPtr, -1, nil, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) // $ hasXXE=96 |
| 123 | + |
| 124 | + let ctxt1 = getACtxt() |
| 125 | + if (xmlCtxtUseOptions(ctxt1, 0) == 0) { // NO XXE: external entities not enabled |
| 126 | + let _ = xmlParseChunk(ctxt1, remoteCharPtr, 1024, 0) |
| 127 | + } |
| 128 | + |
| 129 | + let ctxt2 = getACtxt() |
| 130 | + if (xmlCtxtUseOptions(ctxt2, Int32(XML_PARSE_NOENT.rawValue)) == 0) { // $ MISSING: hasXXE=96 |
| 131 | + let _ = xmlParseChunk(ctxt2, remoteCharPtr, 1024, 0) |
| 132 | + } |
| 133 | + |
| 134 | + let ctxt3 = getACtxt() |
| 135 | + if (xmlCtxtUseOptions(ctxt3, Int32(XML_PARSE_DTDLOAD.rawValue)) == 0) { // $ MISSING: hasXXE=96 |
| 136 | + let _ = xmlParseChunk(ctxt3, remoteCharPtr, 1024, 0) |
| 137 | + } |
| 138 | + |
| 139 | + let ctxt4 = getACtxt() |
| 140 | + if (xmlCtxtUseOptions(ctxt4, Int32(XML_PARSE_DTDLOAD.rawValue)) == 0) { // $ NO XXE: the input chunk isn't tainted |
| 141 | + let _ = xmlParseChunk(ctxt4, safeCharPtr, 1024, 0) |
| 142 | + } |
| 143 | + |
| 144 | + let remotePath = FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent("shared.xml") |
| 145 | + let safePath = Bundle.main.path(forResource: "my", ofType: "xml") |
| 146 | + let remoteFd = try! FileDescriptor.open(FilePath(remotePath)!, FileDescriptor.AccessMode.readOnly) |
| 147 | + let safeFd = try! FileDescriptor.open(FilePath(safePath!), FileDescriptor.AccessMode.readOnly) |
| 148 | + |
| 149 | + let _ = xmlReadFd(remoteFd.rawValue, nil, nil, 0) // NO XXE: external entities not enabled |
| 150 | + let _ = xmlReadFd(remoteFd.rawValue, nil, nil, Int32(XML_PARSE_NOENT.rawValue)) // $ MISSING: hasXXE=146 |
| 151 | + let _ = xmlReadFd(remoteFd.rawValue, nil, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) // $ MISSING: hasXXE=146 |
| 152 | + let _ = xmlReadFd(safeFd.rawValue, nil, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) // NO XXE: the input file is trusted |
| 153 | + |
| 154 | + let ctxt5 = getACtxt() |
| 155 | + let _ = xmlCtxtReadFd(ctxt5, remoteFd.rawValue, nil, nil, 0) // NO XXE: external entities not enabled |
| 156 | + let _ = xmlCtxtReadFd(ctxt5, remoteFd.rawValue, nil, nil, Int32(XML_PARSE_NOENT.rawValue)) // $ MISSING: hasXXE=146 |
| 157 | + let _ = xmlCtxtReadFd(ctxt5, remoteFd.rawValue, nil, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) // $ MISSING: hasXXE=146 |
| 158 | + let _ = xmlCtxtReadFd(ctxt5, safeFd.rawValue, nil, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) // NO XXE: the input file is trusted |
| 159 | + |
| 160 | + let ctxt6 = getACtxt() |
| 161 | + if (xmlCtxtUseOptions(ctxt6, Int32(XML_PARSE_NOENT.rawValue)) == 0) { // $ MISSING: hasXXE=146 |
| 162 | + let _ = xmlCtxtReadFd(ctxt6, remoteFd.rawValue, nil, nil, 0) |
| 163 | + } |
| 164 | + |
| 165 | + let _ = xmlReadIO(nil, nil, nil, nil, nil, 0) // NO XXE: external entities not enabled |
| 166 | + let _ = xmlReadIO(nil, nil, nil, nil, nil, Int32(XML_PARSE_NOENT.rawValue)) // $ MISSING: hasXXE=? |
| 167 | + let _ = xmlReadIO(nil, nil, nil, nil, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) // $ MISSING: hasXXE=? |
| 168 | + |
| 169 | + let _ = xmlCtxtReadIO(nil, nil, nil, nil, nil, nil, 0) // NO XXE: external entities not enabled |
| 170 | + let _ = xmlCtxtReadIO(nil, nil, nil, nil, nil, nil, Int32(XML_PARSE_NOENT.rawValue)) // $ MISSING: hasXXE=? |
| 171 | + let _ = xmlCtxtReadIO(nil, nil, nil, nil, nil, nil, Int32(XML_PARSE_DTDLOAD.rawValue)) // $ MISSING: hasXXE=? |
98 | 172 | }
|
0 commit comments