This branch contains the new generation of the SWAN framework.
SWAN is a static program analysis framework that enables deep dataflow analysis for Swift applications (incl. iOS/macOS). Its applications include finding API misuses using typestate analysis and detecting security vulnerabilities using taint analysis.
We aim to provide developers and researchers with an easy-to-use and well-documented platform for analyzing Swift applications.
- Wrappers for
swiftcthat build and dump SIL
- SIL parser (99% coverage, up to 100k lines/second)
- Well documented intermediate representation (IR), called SWIRL
- Ability to write models for black-box functions with SWIRL
- Partial language and Swift Standard Library models
- Modular IR translation pipeline (for integration with other engines)
- Development tool for viewing Swift, SIL, and SWIRL side-by-side
- Optimizations: multi-threaded module processing, caching, selective parsing
- Cross-module analysis support
- Synchronized Pushdown Systems (SPDS) integration
- Call graph construction
- Configurable taint analysis
- Configurable typestate analysis
- Analysis for Visits Location Service and Standard Location Service for finding energy inefficient configuration
- Annotation checker for regression testing
Currently working on
- Improving taint and typestate analysis
- More language and Swift Standard Library modeling
- iOS lifecycle support
- Crypto API misuse detection
- ... and much more!
Relevant Wiki pages
- SIL To SWIRL Spec
- IDE Configuration
- Writing Analysis
- Detecting Inefficient Location API Configurations
For now, you will need to build the framework to use SWAN, but we will soon make a release available.
We have tested SWAN on macOS Big Sur with Xcode 12.5 and Ubuntu 20.04 with Swift 5.4. You need Xcode Command Line Tools installed for macOS, or the latest Swift release for Linux (see this). Anything involving Xcode will not work on Linux, but you should be able to build Swift Package Manager projects. You also need Java 8.
git clone https://github.com/themaplelab/swan.git -b spds
Add your GitHub username and personal access token (with read:packages) to
jvm/gradle.properties. The SPDS dependency requires this. Do not push these credentials.
/usr/local/bin/ or add it to
$PATH. On Linux,
swift-demangle is distributed alongside
swiftc, so you do not need to do this step. You also need
xcodebuild to be on
sudo cp /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-demangle /usr/local/bin/
build.sh in the repo root. You can also run the nested
build.sh scripts from root to build separate toolchain components.
All toolchain components should now be available in
lib/. If you want to make sure everything works, you can run run
./gradlew build in
SWAN's toolchain uses a three-step process:
- Build the Swift application and dump SIL to a directory
- Analyze the SIL in the directory
- Process analysis results
1. Dump SIL using either
You can dump SIL for Xcode projects with
swan-xcodebuild. Give it the same arguments you give
xcodebuild, but put them after
swan-xcodebuild specific arguments go before
--). If you specify a single architecture with
-arch, the build time will be faster and
swan-xcodebuild will have less output to parse.
It will build your project and then dump the SIL to the
swan-dir/ directory. You can optionally specify an alternative directory name with
swan-xcodebuild -- -project MyProject.xcodeproj -scheme MyScheme -arch arm64
The same idea applies for
swan-swiftc, which dumps SIL for single
.swift files, and you only need to specify the Swift file.
swan-swiftc -- MyFile.swift
Generating Xcode projects
To build your project with
(swan-)xcodebuild you need an
.xcodeproj. If your project uses the Swift Package Manager (SPM), you will need to generate a
.xcodeproj for your project, which you can do with
swift package generate-xcodeproj. If you use CocoaPods, make sure to use
-workspace instead of
-project. You can also look into adding XcodeGen to your project to generate the
.xcodeproj. If you are unsure what schemes or targets you can build, you can use
2. Run Analysis
driver.jar to analyze the SIL in the
swan-dir/. You can use
-h to view the driver options.
You can learn about how to write analysis for SWAN here. Use
-t to give the driver a taint analysis specification. Use
-e to give the driver a typestate specification. You can view some example specifications in
-p to enable path-tracking. Note that path-tracking sometimes hangs (see the related issue for details). The default analysis will still show you the source and sink callsite locations.
The analysis engine (SDPS) may run out of stack memory. Currently, it will not tell you if this has happened. You can use
-Xss to increase the stack memory.
3. Processing analysis results
The driver writes analysis results to
You can annotate the source code and verify the results are correct automatically with
Taint analysis example:
let sourced = source(); //!testing!source sink(sunk: sourced); //!testing!sink
Typestate analysis example:
let f = File() f.open() //?FileOpenClose?error
Once you run the driver, you can run the following to check the annotations against the results.
java -jar annotation.jar swan-dir/
This is intended for automatic regression testing. You can take a look inside
tests/ to get a better idea of how annotation testing works.
tests/README.md contains more information about testing.
jvm/ in IntelliJ. Be sure to select Import as Gradle Project.
Install the Scala plugin (Preferences -> Plugins, Search for Scala).
See IDE Configuration if you would like to configure syntax highlighting for SWIRL and SIL.
You can use the Playground run configurations to debug specific Swift, SIL, and SWIRL cases. Just paste the code in question to the appropriate