Insecure exceptions - Empty or no catch - Swift

Insecure exceptions - Empty or no catch - Swift

Need

Proper exception handling and error management

Context

  • Usage of Swift 5.0 for iOS app development
  • Usage of Foundation for building responsive and accessible web interfaces

Description

Non compliant code

        func vulnerableFunction() {
    do {
        // Some code that might generate an error
        let fileURL = try FileManager.default
            .url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
            .appendingPathComponent("TestDocument.txt")

        let savedText = try String(contentsOf: fileURL)
        print(savedText)
    } catch {
        // Empty catch block
    }
}
        
        

The above Swift code demonstrates a function that attempts to read a text file from the document directory of an iOS application. This operation can throw an error if the file does not exist or if there's a problem accessing the file.

The issue here is that the catch block is empty. This means that if an error occurs, the application will not handle it properly. The error will be caught, but nothing will be done to address it. This can lead to the application continuing to run in an erroneous state, or even crashing, without providing any useful feedback to the user or to the developer.

In other words, the application is ignoring any potential errors that might arise when trying to access a file. This can lead to unexpected behavior and could potentially make the application temporarily or permanently unavailable, as the error is not being handled or logged.

Steps

  • Identify all the potential error-prone code blocks.
  • Add appropriate error handling code using try-catch blocks.
  • Inside the catch block, handle the error appropriately by logging, displaying an error message, or taking necessary actions.
  • Avoid empty catch blocks as they hide potential errors and make it difficult to diagnose issues.
  • Consider using specific catch blocks for different types of errors to handle them differently.
  • Ensure that the application remains in a stable state even when exceptions occur.

Compliant code

        func fixedFunction() {
    do {
        // Some code that might generate an error
        let fileURL = try FileManager.default
            .url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
            .appendingPathComponent("TestDocument.txt")

        let savedText = try String(contentsOf: fileURL)
        print(savedText)
    } catch let error as NSError {
        // Handle the error
        print("Failed to read file: \\(error)")
    }
}
        
        

The above code is a fixed version of the vulnerable code. The vulnerability was that the catch block was empty, which means that if an error occurred in the try block, it would not be handled properly. This could lead to the application becoming temporarily or permanently unavailable.

In the fixed code, the catch block has been filled with code that handles the error. Specifically, it prints an error message that includes the details of the error. This allows developers to understand what went wrong if an error occurs.

The error is caught as an NSError, which is a general type that can catch all kinds of errors. If there are specific types of errors that need to be handled differently, additional catch blocks can be added for those specific error types.

By handling errors properly, the application can remain in a stable state even when exceptions occur. This improves the reliability and usability of the application.

References