Sfoglia il codice sorgente

Colors: add a mechanism to resolve the ambiguity between the two ways of representing colors that were conflicting with each other due to mistakes made over the years in the community. Various fixes from Fuzzing

Miguel de Icaza 4 anni fa
parent
commit
fcefefd991

+ 27 - 4
Sources/SwiftTerm/Buffer.swift

@@ -31,7 +31,11 @@ class Buffer {
         get { _yBase }
         get { _yBase }
         set {
         set {
             if newValue > _lines.count {
             if newValue > _lines.count {
-                //abort ()
+//                #if DEBUG
+//                abort ()
+//                #else
+//                return
+//                #endif
             }
             }
             _yBase = newValue
             _yBase = newValue
         }
         }
@@ -41,10 +45,14 @@ class Buffer {
     public var yDisp: Int {
     public var yDisp: Int {
         get { return _yDisp }
         get { return _yDisp }
         set {
         set {
-            _yDisp = newValue
             if _yDisp < 0 {
             if _yDisp < 0 {
+                #if DEBUG
                 abort()
                 abort()
+                #else
+                return
+                #endif
             }
             }
+            _yDisp = newValue
         }
         }
     }
     }
     /**
     /**
@@ -57,7 +65,11 @@ class Buffer {
         get { return _x }
         get { return _x }
         set(newValue) {
         set(newValue) {
             if newValue < 0 {
             if newValue < 0 {
-                abort ()
+                #if DEBUG
+                abort()
+                #else
+                return
+                #endif
             }
             }
             _x = newValue
             _x = newValue
         }
         }
@@ -70,7 +82,11 @@ class Buffer {
         get { return _y }
         get { return _y }
         set(newValue) {
         set(newValue) {
             if newValue < 0 {
             if newValue < 0 {
+                #if DEBUG
                 abort()
                 abort()
+                #else
+                return
+                #endif
             }
             }
             _y = newValue
             _y = newValue
         }
         }
@@ -83,10 +99,14 @@ class Buffer {
     public var scrollBottom: Int {
     public var scrollBottom: Int {
         get { _scrollBottom }
         get { _scrollBottom }
         set {
         set {
-            _scrollBottom = newValue
             if newValue < 0 {
             if newValue < 0 {
+                #if DEBUG
                 abort()
                 abort()
+                #else
+                return
+                #endif
             }
             }
+            _scrollBottom = newValue
         }
         }
     }
     }
     
     
@@ -771,6 +791,9 @@ class Buffer {
 
 
             let lastLineLength = wrappedLines [wrappedLines.count - 1].getTrimmedLength ()
             let lastLineLength = wrappedLines [wrappedLines.count - 1].getTrimmedLength ()
             let destLineLengths = getNewLineLengths (wrappedLines: wrappedLines, oldCols: oldCols, newCols: newCols)
             let destLineLengths = getNewLineLengths (wrappedLines: wrappedLines, oldCols: oldCols, newCols: newCols)
+            if destLineLengths.count == 0 {
+                continue
+            }
             let linesToAdd = destLineLengths.count - wrappedLines.count
             let linesToAdd = destLineLengths.count - wrappedLines.count
 
 
             var trimmedLines: Int
             var trimmedLines: Int

+ 10 - 1
Sources/SwiftTerm/EscapeSequenceParser.swift

@@ -293,6 +293,7 @@ class EscapeSequenceParser {
     // buffers over several calls
     // buffers over several calls
     var _osc: cstring
     var _osc: cstring
     var _pars: [Int]
     var _pars: [Int]
+    var _parsTxt: [UInt8]
     var _collect: cstring
     var _collect: cstring
     var printHandler: PrintHandler = { (slice : ArraySlice<UInt8>) -> () in }
     var printHandler: PrintHandler = { (slice : ArraySlice<UInt8>) -> () in }
     var printStateReset: () -> () = {  }
     var printStateReset: () -> () = {  }
@@ -304,6 +305,7 @@ class EscapeSequenceParser {
         table = EscapeSequenceParser.buildVt500TransitionTable()
         table = EscapeSequenceParser.buildVt500TransitionTable()
         _osc = []
         _osc = []
         _pars = [0]
         _pars = [0]
+        _parsTxt = []
         _collect = []
         _collect = []
         // "\"
         // "\"
         setEscHandler("\\", ParserEscHandlerFallback)
         setEscHandler("\\", ParserEscHandlerFallback)
@@ -380,6 +382,7 @@ class EscapeSequenceParser {
         var osc = self._osc
         var osc = self._osc
         var collect = self._collect
         var collect = self._collect
         var pars = self._pars
         var pars = self._pars
+        var parsTxt = self._parsTxt
         var dcsHandler = activeDcsHandler
         var dcsHandler = activeDcsHandler
         
         
         //dump (data)
         //dump (data)
@@ -412,7 +415,7 @@ class EscapeSequenceParser {
                 // Prevent attempts at overflowing - crash 
                 // Prevent attempts at overflowing - crash 
                 let willOverflow =  newV > ((Int.max/10)-10)
                 let willOverflow =  newV > ((Int.max/10)-10)
                 pars [pars.count - 1] = willOverflow ? 0 : newV
                 pars [pars.count - 1] = willOverflow ? 0 : newV
-                
+                parsTxt.append(code)
                 i += 1
                 i += 1
                 continue
                 continue
             }
             }
@@ -483,11 +486,13 @@ class EscapeSequenceParser {
             case .csiDispatch:
             case .csiDispatch:
                 // Trigger CSI handler
                 // Trigger CSI handler
                 if let handler = csiHandlers [code] {
                 if let handler = csiHandlers [code] {
+                    _parsTxt = parsTxt
                     handler (pars, collect)
                     handler (pars, collect)
                 } else {
                 } else {
                     csiHandlerFallback (pars, collect, code)
                     csiHandlerFallback (pars, collect, code)
                 }
                 }
             case .param:
             case .param:
+                parsTxt.append(code)
                 if code == 0x3b || code == 0x3a {
                 if code == 0x3b || code == 0x3a {
                     pars.append (0)
                     pars.append (0)
                 } else {
                 } else {
@@ -512,6 +517,7 @@ class EscapeSequenceParser {
                 }
                 }
                 osc = []
                 osc = []
                 pars = [0]
                 pars = [0]
+                parsTxt = []
                 collect = []
                 collect = []
                 dcs = -1
                 dcs = -1
                 printStateReset()
                 printStateReset()
@@ -537,6 +543,7 @@ class EscapeSequenceParser {
                 }
                 }
                 osc = []
                 osc = []
                 pars = [0]
                 pars = [0]
+                parsTxt = []
                 collect = []
                 collect = []
                 dcs = -1
                 dcs = -1
                 printStateReset()
                 printStateReset()
@@ -584,6 +591,7 @@ class EscapeSequenceParser {
                 }
                 }
                 osc = []
                 osc = []
                 pars = [0]
                 pars = [0]
+                parsTxt = []
                 collect = []
                 collect = []
                 dcs = -1
                 dcs = -1
                 printStateReset()
                 printStateReset()
@@ -601,6 +609,7 @@ class EscapeSequenceParser {
         _osc = osc
         _osc = osc
         _collect = collect
         _collect = collect
         _pars = pars
         _pars = pars
+        _parsTxt = parsTxt
         
         
         // save active dcs handler reference
         // save active dcs handler reference
         activeDcsHandler = dcsHandler
         activeDcsHandler = dcsHandler

+ 0 - 1
Sources/SwiftTerm/Mac/MacTerminalView.swift

@@ -89,7 +89,6 @@ open class TerminalView: NSView, NSTextInputClient, NSUserInterfaceValidations {
     
     
     // These structures are parallel, maybe should be merged, but one contains the attributed text to render
     // These structures are parallel, maybe should be merged, but one contains the attributed text to render
     var attrStrBuffer: CircularList<ViewLineInfo>!
     var attrStrBuffer: CircularList<ViewLineInfo>!
-
     // Attribute dictionary, maps a console attribute (color, flags) to the corresponding dictionary
     // Attribute dictionary, maps a console attribute (color, flags) to the corresponding dictionary
     // of attributes for an NSAttributedString
     // of attributes for an NSAttributedString
     var attributes: [Attribute: [NSAttributedString.Key:Any]] = [:]
     var attributes: [Attribute: [NSAttributedString.Key:Any]] = [:]

+ 78 - 78
Sources/SwiftTerm/Terminal.swift

@@ -1956,7 +1956,9 @@ open class Terminal {
         if buffer.y < buffer.scrollTop || buffer.y > buffer.scrollBottom {
         if buffer.y < buffer.scrollTop || buffer.y > buffer.scrollBottom {
             return
             return
         }
         }
-        var p = max (pars.count == 0 ? 1 : pars [0], 1)
+        // to prevent a Denial of Service
+        let maxLines = buffer._lines.maxLength * 2
+        var p = min (maxLines, max (pars.count == 0 ? 1 : pars [0], 1))
         let row = buffer.y + buffer.yBase
         let row = buffer.y + buffer.yBase
         
         
         let scrollBottomRowsOffset = rows - 1 - buffer.scrollBottom
         let scrollBottomRowsOffset = rows - 1 - buffer.scrollBottom
@@ -2172,8 +2174,8 @@ open class Terminal {
             // We only support copying on the same page, and the page being 1
             // We only support copying on the same page, and the page being 1
             if pars [4] == pars [7] && pars [4] == 1 {
             if pars [4] == pars [7] && pars [4] == 1 {
                 if let (top, left, bottom, right) = getRectangleFromRequest(pars [0...3]) {
                 if let (top, left, bottom, right) = getRectangleFromRequest(pars [0...3]) {
-                    let rowTarget = pars [5]-1
-                    let colTarget = pars [6]-1
+                    let rowTarget = min (rows-1, pars [5]-1)
+                    let colTarget = min (cols-1, pars [6]-1)
                     
                     
                     // Block size
                     // Block size
                     let columns = right-left+1
                     let columns = right-left+1
@@ -2942,6 +2944,67 @@ open class Terminal {
         let def = CharData.defaultAttr
         let def = CharData.defaultAttr
 
 
         var i = 0
         var i = 0
+        
+        // Extended Colors
+        //
+        // There is an ambiguity here that is troublesome, to support extended
+        // colors and colorspaces, two competing systems exists, one uses for example:
+        // 38;2;R;G;B;NEXT - foreground true color
+        // 38:2:ColorSpace:R:G:B:REST;NEXT - second style for the same
+        //
+        // The former apparently was a mistake, but we need to disambiguate the meaning
+        // of pars, based on whether the above uses ":" or ";" we need that, because
+        // the SGR is a collection of attributes, so after our parameter values, we
+        // need to continue processing
+        //
+        //
+        func parseExtendedColor () -> Attribute.Color? {
+            var color: Attribute.Color? = nil
+            let v = parser._parsTxt
+            
+            // If this is the new style
+            if v.count > 2 && v [2] == UInt8(ascii: ":") {
+                // Color style, we ignore "ColorSpace"
+                i += 1
+                if i+3 < parCount {
+                    color = Attribute.Color.trueColor(
+                          red: UInt8(min (pars [i+1], 255)),
+                        green: UInt8(min (pars [i+2], 255)),
+                         blue: UInt8(min (pars [i+3], 255)))
+                }
+                i += 4
+            } else {
+                switch pars [i] {
+                case 2: // RGB color
+                    i += 1
+                    if i+2 < parCount {
+                        color = Attribute.Color.trueColor(
+                              red: UInt8(min (pars [i], 255)),
+                            green: UInt8(min (pars [i+1], 255)),
+                             blue: UInt8(min (pars [i+2], 255)))
+                    }
+                    i += 3
+                    
+                case 3: // CMY color - not supported
+                    break
+                    
+                case 4: // CMYK color - not supported
+                    break
+                    
+                case 5: // indexed color
+                    if i+1 < parCount {
+                        fg = Attribute.Color.ansi256(code: UInt8 (min (255, pars [i+1])))
+                        i += 1
+                    }
+                    i += 1
+
+                default:
+                    break
+                }
+            }
+            return color
+        }
+        
         while i < parCount {
         while i < parCount {
             var p = pars [i]
             var p = pars [i]
             switch p {
             switch p {
@@ -3003,44 +3066,11 @@ open class Terminal {
                 // fg color 8
                 // fg color 8
                 fg = Attribute.Color.ansi256(code: UInt8(p - 30))
                 fg = Attribute.Color.ansi256(code: UInt8(p - 30))
             case 38:
             case 38:
-                // Extended Foreground colors
-                if i+1 < parCount {
-                    switch pars [i+1] {
-                    case 2: // RGB color
-                        // Well this is a problem, if there are 3 arguments, expect R/G/B, if there are
-                        // more than 3, skip the first that would be the colorspace
-                        if i+5 < parCount {
-                            i += 1
-                        }
-                        if i+4 < parCount {
-                            fg = Attribute.Color.trueColor(
-                                  red: UInt8(min (pars [i+2], 255)),
-                                green: UInt8(min (pars [i+3], 255)),
-                                 blue: UInt8(min (pars [i+4], 255)))
-                        }
-                        // Given the historical disagreement that was caused by an ambiguous spec,
-                        // we eat all the remaining parameters.  At least until I can figure out if there
-                        i = parCount
-                        break
-                        
-                    case 3: // CMY color - not supported
-                        break
-                        
-                    case 4: // CMYK color - not supported
-                        break
-                        
-                    case 5: // indexed color
-                        if i+2 < parCount {
-                            fg = Attribute.Color.ansi256(code: UInt8 (min (255, pars [i+2])))
-                            i += 1
-                        }
-                        i += 1
-                        
-                    default:
-                        break
-                    }
+                i += 1
+                if let parsed = parseExtendedColor () {
+                    fg = parsed
                 }
                 }
-                
+                continue
             case 39:
             case 39:
                 // reset fg
                 // reset fg
                 fg = CharData.defaultAttr.fg
                 fg = CharData.defaultAttr.fg
@@ -3048,44 +3078,12 @@ open class Terminal {
                 // bg color 8
                 // bg color 8
                 bg = Attribute.Color.ansi256(code: UInt8(p - 40))
                 bg = Attribute.Color.ansi256(code: UInt8(p - 40))
             case 48:
             case 48:
-                // Extended Background colors
-                if i+1 < parCount {
-                    // bg color 256
-                    switch pars [i+1] {
-                    case 2: // RGB color
-                        // Well this is a problem, if there are 3 arguments, expect R/G/B, if there are
-                        // more than 3, skip the first that would be the colorspace
-                        if i+5 < parCount {
-                            i += 1
-                        }
-                        if i+4 < parCount {
-                            bg = Attribute.Color.trueColor(
-                                red:   UInt8(min (255, pars [i+2])),
-                                green: UInt8(min (255, pars [i+3])),
-                                blue:  UInt8(min (255, pars [i+4])))
-                        }
-                        // Given the historical disagreement that was caused by an ambiguous spec,
-                        // we eat all the remaining parameters.  At least until I can figure out if there
-                        i = parCount
-                        break
-                        
-                    case 3: // CMY color - not supported
-                        break
-                        
-                    case 4: // CMYK color - not supported
-                        break
-                        
-                    case 5: // indexed color
-                        if i+2 < parCount {
-                            bg = Attribute.Color.ansi256(code: UInt8 (min (255, pars [i+2])))
-                            i += 1
-                        }
-                        i += 1
-
-                    default:
-                        break
-                    }
+                i += 1
+                if let parsed = parseExtendedColor() {
+                    bg = parsed
                 }
                 }
+                continue
+                
             case 49:
             case 49:
                 // reset bg
                 // reset bg
                 bg = CharData.defaultAttr.bg
                 bg = CharData.defaultAttr.bg
@@ -3728,7 +3726,9 @@ open class Terminal {
     //
     //
     func cmdRepeatPrecedingCharacter (_ pars: [Int], collect: cstring)
     func cmdRepeatPrecedingCharacter (_ pars: [Int], collect: cstring)
     {
     {
-        let p = max (pars.count == 0 ? 1 : pars [0], 1)
+        // Maximum repeat, to avoid a denial of service
+        let maxRepeat = cols*rows*2
+        let p = min (maxRepeat, max (pars.count == 0 ? 1 : pars [0], 1))
         let line = buffer.lines [buffer.yBase + buffer.y]
         let line = buffer.lines [buffer.yBase + buffer.y]
         let chData = buffer.x - 1 < 0 ? CharData (attribute: CharData.defaultAttr) : line [buffer.x - 1]
         let chData = buffer.x - 1 < 0 ? CharData (attribute: CharData.defaultAttr) : line [buffer.x - 1]
         
         

+ 0 - 88
Sources/SwiftTermFuzz/main.swift

@@ -30,91 +30,3 @@ var queue = DispatchQueue(label: "Runner", qos: .userInteractive, attributes: .c
     t.feed (byteArray: arr)
     t.feed (byteArray: arr)
     return 0
     return 0
 }
 }
-
-// For manually testing stuff and use the Xcode debugger
-func testInput (d: Data)
-{
-    let h = HeadlessTerminal (queue: queue) { exitCode in }
-    var data : [UInt8] = []
-    data.append(contentsOf: d)
-    let t = h.terminal!
-    t.silentLog = true
-    t.feed (byteArray: data)
-}
-
-func testCrashes ()
-{
-    let crashes = [
-        "crash-a58b5a38135bd7ffadad8b420ab8dcd0c3e4a1bd",
-        "crash-840102113e655342bfc30d2749406756a6e812d3",
-        "crash-654c8421b816426f584c3347a72cd2e869602ed5",
-        "crash-c6f850474ed073bb5b2e032c13d66819e68acc88",
-        "crash-a18a4cccc2a2b1c6f14ea804d15dd7f93682abf2",
-        "crash-b274a2639cd901a107778760708bb759c52086f8",
-        
-        "crash-9ff2abe9af46be74ca774b8d684e1df0737aa0bf",
-        "crash-fb6fa24871a603f7920dd24d467c449ac5b8d893",
-        "crash-f8e22628b8a2bb06d06fa9c064fe3a7363c35bde",
-        "crash-dc9cf799322b1223cb9a0e40283cb61812d50fbb",
-        "crash-c5c6e20dacfbb1a72599f8e135321a343d0dc2c6",
-        "crash-d38b59abae508cafa02c586d1706cf734977e6eb",
-        "crash-96e8d67b4e139f9eaebb950c5d25b7d5bd456359",
-        "crash-be2c5a1d40465efe36dd95771161829427dd6356",
-        "crash-3154715068e3ec98c7b425cc0fe56c1dbd1e1f58",
-        "crash-41df255a79feb00f8ded38dac7a51065a2758977",
-        "crash-45157239bc429db89546e2f0fea38b26f608b8d9",
-        
-        
-        "crash-2f5d273ae2f2bb95152905486bd9bfd8afa83c02",
-        "crash-17381a13c18b7bda011f260e38952fb8fb7e4616",
-        "crash-0a14a360e820c3801095d8bdbc130b3e18d55261",
-        "slow-unit-16849a4439a9ada62a289f64d122b3f898410375",
-        "slow-unit-be2210ab3bc792ab4932a65d0aecd1e3bbdb7db1",
-        "slow-unit-cb67af81341f405834d562bcb49570e2d3a95348",
-        "slow-unit-ff24adf923bfd5c9ccb4d58722c31c48d3f86480",
-
-        "crash-166a328f85dd916e1602764a1792f95b7d749a0e",
-        "crash-2b6b8631ea3cc418a069994de53e207da2d81230",
-        "crash-509b3b6f6b74c483c515eecb5114f2f21f7ca576",
-        "crash-698522a0a18e4fa7dcd0ee6b232d24cacecec07d",
-        "crash-6f6c2b5c064f8ef4510305a3e04b2ef2c646b731",
-        "crash-8876cfdf6927d0729ceccb6ae1c03da57c402eca",
-        "crash-b60503f1c280209282018547ac732afd6d735dd9",
-        "crash-ce788aaf77fa3219df3dea89f4a6771662402ebe",
-        "crash-cf873cabbbf89413ae6f40ffc3f87e452cb9ed9b",
-        "crash-e68d1073bb2f9140f95b4d9ad8dd076e5827f6c8",
-        "crash-e6a7981c673480824152b1f8c948fac0d4a294f4",
-
-        "crash-039a0b21c56b1e3a7a51056dd4f8daa9130c7312",
-        "crash-36eb1fbfdb3a61e7b17b166d190ffd85ad9c80ab",
-        "crash-4ba9dc95bc1c5d691fd9e80a4de72d65184e5c56",
-        "crash-59fb9d3b7ab81c1782d26dfc69a962fae49ec449",
-        "crash-64300317b2f97db7bfacfd77ba4d879e9726fd68",
-        "crash-b926cdde789b73ff9680ff9ab643f13fa36c0571",
-        "crash-c1147059ce893629e13289b43ae2b2ad1edcf44f",
-        "crash-de2a0b4222547592208f7f85e2cd5b2730194daa",
-        "crash-e1f2f0f2ef07d6d728316fa1bc336e6d1d699b99",
-        "crash-ec47d21af677ee8eb18f91e150cdfb5d41d931c1",
-
-        
-    ]
-    
-    for crash in crashes {
-        let url = URL(fileURLWithPath: "/Users/miguel/cvs/SwiftTerm/\(crash)")
-        let data: Data
-        do {
-            print ("Running test \(crash)")
-            data = try Data(contentsOf: url)
-        } catch {
-            print ("Caught error loading \(crash)")
-            continue
-        }
-
-        testInput (d: data)
-        
-        print ("passed crash \(crash)")
-    }
-    print ("Happy!")
-}
-
- //testCrashes()

+ 112 - 1
Tests/SwiftTermTests/FuzzerTests.swift

@@ -1,8 +1,119 @@
 //
 //
-//  File.swift
+// FuzzerTests: runs the tests that feed the fuzzer inputs
 //  
 //  
 //
 //
 //  Created by Miguel de Icaza on 4/29/21.
 //  Created by Miguel de Icaza on 4/29/21.
 //
 //
 
 
 import Foundation
 import Foundation
+import XCTest
+import Foundation
+
+@testable import SwiftTerm
+
+final class FuzzerTests: XCTestCase {
+    var queue = DispatchQueue(label: "Runner", qos: .userInteractive, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
+    
+    // For manually testing stuff and use the Xcode debugger
+    func testInput (d: Data)
+    {
+        let h = HeadlessTerminal (queue: queue) { exitCode in }
+        var data : [UInt8] = []
+        data.append(contentsOf: d)
+        let t = h.terminal!
+        t.silentLog = true
+        t.feed (byteArray: data)
+    }
+
+    // These do not really test crashes, they are just slow:
+    //        "slow-unit-0c2689cd9f79cf89245ff42a5c312ebf0742e5be",
+    //        "slow-unit-16849a4439a9ada62a289f64d122b3f898410375",
+    //        "slow-unit-be2210ab3bc792ab4932a65d0aecd1e3bbdb7db1",
+    //        "slow-unit-cb67af81341f405834d562bcb49570e2d3a95348",
+    //        "slow-unit-ff24adf923bfd5c9ccb4d58722c31c48d3f86480",
+
+    func test (_ crash: String) {
+        var file: String
+        let t1 = "/Users/miguel/cvs/SwiftTerm/\(crash)"
+        let t2 = "/Users/miguel/cvs/SwiftTermFuzzerResults/\(crash)"
+        
+        if FileManager.default.fileExists(atPath: t1) {
+            file = t1
+        } else if FileManager.default.fileExists(atPath: t2) {
+            file = t2
+        } else {
+            print ("Data file \(crash) not found in the peer directory or this directory")
+            return
+        }
+        let url = URL(fileURLWithPath: file)
+        let data: Data
+        do {
+            print ("Running test \(crash)")
+            data = try Data(contentsOf: url)
+        } catch {
+            print ("Failure to load the data file \(crash)")
+            return
+        }
+
+        testInput (d: data)
+    }
+    
+    func testCrashes ()
+    {
+        return 
+        test ("crash-661c9f1d29d682c0d7fd640fa57266b24c9a8ed2")
+        test ("crash-a455aeceaf7374464ee888fbf85691ef91ab6480")
+        test ("crash-a58b5a38135bd7ffadad8b420ab8dcd0c3e4a1bd")
+        test ("crash-840102113e655342bfc30d2749406756a6e812d3")
+        test ("crash-654c8421b816426f584c3347a72cd2e869602ed5")
+        test ("crash-c6f850474ed073bb5b2e032c13d66819e68acc88")
+        test ("crash-a18a4cccc2a2b1c6f14ea804d15dd7f93682abf2")
+        test ("crash-b274a2639cd901a107778760708bb759c52086f8")
+        test ("crash-9ff2abe9af46be74ca774b8d684e1df0737aa0bf")
+        test ("crash-fb6fa24871a603f7920dd24d467c449ac5b8d893")
+        test ("crash-f8e22628b8a2bb06d06fa9c064fe3a7363c35bde")
+        test ("crash-dc9cf799322b1223cb9a0e40283cb61812d50fbb")
+        test ("crash-c5c6e20dacfbb1a72599f8e135321a343d0dc2c6")
+        test ("crash-d38b59abae508cafa02c586d1706cf734977e6eb")
+        test ("crash-96e8d67b4e139f9eaebb950c5d25b7d5bd456359")
+        test ("crash-be2c5a1d40465efe36dd95771161829427dd6356")
+        test ("crash-3154715068e3ec98c7b425cc0fe56c1dbd1e1f58")
+        test ("crash-41df255a79feb00f8ded38dac7a51065a2758977")
+        test ("crash-45157239bc429db89546e2f0fea38b26f608b8d9")
+        test ("crash-2f5d273ae2f2bb95152905486bd9bfd8afa83c02")
+        test ("crash-17381a13c18b7bda011f260e38952fb8fb7e4616")
+        test ("crash-0a14a360e820c3801095d8bdbc130b3e18d55261")
+        test ("crash-166a328f85dd916e1602764a1792f95b7d749a0e")
+        test ("crash-2b6b8631ea3cc418a069994de53e207da2d81230")
+        test ("crash-509b3b6f6b74c483c515eecb5114f2f21f7ca576")
+        test ("crash-698522a0a18e4fa7dcd0ee6b232d24cacecec07d")
+        test ("crash-6f6c2b5c064f8ef4510305a3e04b2ef2c646b731")
+        test ("crash-8876cfdf6927d0729ceccb6ae1c03da57c402eca")
+        test ("crash-b60503f1c280209282018547ac732afd6d735dd9")
+        test ("crash-ce788aaf77fa3219df3dea89f4a6771662402ebe")
+        test ("crash-cf873cabbbf89413ae6f40ffc3f87e452cb9ed9b")
+        test ("crash-e68d1073bb2f9140f95b4d9ad8dd076e5827f6c8")
+        test ("crash-e6a7981c673480824152b1f8c948fac0d4a294f4")
+        test ("crash-039a0b21c56b1e3a7a51056dd4f8daa9130c7312")
+        test ("crash-36eb1fbfdb3a61e7b17b166d190ffd85ad9c80ab")
+        test ("crash-4ba9dc95bc1c5d691fd9e80a4de72d65184e5c56")
+        test ("crash-59fb9d3b7ab81c1782d26dfc69a962fae49ec449")
+        test ("crash-64300317b2f97db7bfacfd77ba4d879e9726fd68")
+        test ("crash-b926cdde789b73ff9680ff9ab643f13fa36c0571")
+        test ("crash-c1147059ce893629e13289b43ae2b2ad1edcf44f")
+        test ("crash-de2a0b4222547592208f7f85e2cd5b2730194daa")
+        test ("crash-e1f2f0f2ef07d6d728316fa1bc336e6d1d699b99")
+        test ("crash-ec47d21af677ee8eb18f91e150cdfb5d41d931c1")
+    }
+    
+    func testTimeouts ()
+    {
+        test ("timeout-44d56090b5e02248f1d90d2ff371d27abaae532f")
+        test ("timeout-8244fb7b31c904aff447c0456cebd79688f142db")
+    }
+    
+    static var allTests = [
+        ("testFuzzerCrashes", testCrashes),
+        ("testFuzzerTimeouts", testTimeouts)
+    ]
+}